July 16, 2014

NuGet Package for Sandcastle

Did you ever want to build Visual Studio-quality reference documentation from your XML code comments by simply referencing a NuGet package?
Well now you can!

The latest release of White Tie includes full support for generating documentation using Sandcastle. No configuration necessary. (You must install Sandcastle yourself though - see the details below).

Add a reference to White Tie's NuGet Package and then simply build your project in Release mode to generate reference documentation.


If you haven't installed Sandcastle, then White Tie gracefully skips generating documentation. You must install Sandcastle yourself if you want White Tie to generate documentation for your project. Note that you may have to reboot your computer after installing Sandcastle for its changes to take effect. At the very least, you'll have to restart Visual Studio.

White Tie's only requirements are that you must install Microsoft's HTML Help v1 Compiler and Sandcastle's tools. The required steps are highlighted in the following image of the Sandcastle Guided Installer. The other options provided by the installer, such as SHFB Visual Studio Package, are not used by White Tie at all. Of course, you're free to install them anyway if you'd like.

White Tie's Required Sandcastle Installer Steps

After you've installed Sandcastle, documentation is generated automatically when you build your project in Release mode. This is configurable via MSBuild properties, as is almost everything in White Tie (see the following section for details). The result is a compiled help file (.chm) in your project's output folder (typically, bin\Release\). In addition, White Tie packs the compiled help file into the NuGet package that it generates for your project as well.

Documentation Configuration

The purpose of White Tie is to make packaging and deployment of OSS projects, or any other kind of project, really simple. White Tie uses sensible default configurations across all of its features. However, it's also highly configurable to allow for customizations.

White Tie offers many configuration options in the form of MSBuild properties and items that control if and how documentation is generated, a NuGet package is generated, static analysis is executed and output is copied to a local deployment directory.

The configuration options for generating documentation (as of White Tie v1.3.5) are as follows.
See the official documentation for details.

MSBuild Properties

  • $(BuildDocumentationEnabled)
  • $(DocumentationProjectName)
  • $(DocumentationProductName)
  • $(DocumentationCompanyName)
  • $(DocumentationCopyright)
  • $(DocumentationVersion)
  • $(DocumentationProjectSummary)
  • $(DocumentationRootTopicEnabled)
  • $(DocumentationRootTopicTitle)
  • $(DocumentationFeedbackEmail)
  • $(DocumentationFeedbackLinkText)
  • $(DocumentationHeader)
  • $(DocumentationFooter)
  • $(DocumentationStyle)
  • $(DocumentationLanguage)

MSBuild Items

  • @(DocumentationContent)
  • @(DocumentationImage)
  • @(DocumentationNamespace)
  • @(DocumentationSource)
  • @(DocumentationReference)
  • @(DocumentationFrameworkReference)

Undocumented Sandcastle Configuration Properties and Items

Advanced users of Sandcastle may be wondering how to configure Sandcastle's many other options that are missing from the list above.

Well, in addition to the properties and items listed above, White Tie supports several properties and items that are specific to Sandcastle; however, I've decided to separate these options from the primary group because they aren't general enough for White Tie. In the future, White Tie may support other documentation generators, and perhaps even replace its dependency on Sandcastle entirely. As a result, if you restrict your use to only those configuration options listed above, then in the future you shouldn't have to change anything in order to take advantage of whatever new ways White Tie generates documentation for your project. For example, I can imagine Microsoft offering a very fast and light-weight Roslyn documentation generator and in the future I'd like any project depending on White Tie to switch automatically, with little to no changes necessary, by simply upgrading to a newer version of White Tie.

If you really want to use Sandcastle-specific features anyway, then here they are:

  • $(_SandcastleCopyrightUrl)
  • $(_SandcastleVisibleItems) - Default value is "Attributes, ExplicitInterfaceImplementations, InheritedMembers, InheritedFrameworkMembers, Protected, ProtectedInternalAsProtected"
  • $(_SandcastleMissingTags) - Default value is "IncludeTargets"
  • $(_SandcastleIntelliSenseOutputEnabled) - Default value is "true"
  • $(_SandcastleCodeRemoveRegionMarkers) - Default value is "false"
  • $(_SandcastleHelpFileFormat) - Default value is "HtmlHelp1"
  • $(_SandcastleSdkLinkTarget) - Default value is "Blank"
  • $(_SandcastleSyntaxFilters) - Default value is "Standard"
  • $(_SandcastleHelp2SdkLinkType) - Default value is "Msdn"
  • $(_SandcastleContentPlacement) - Default value is "AboveNamespaces"
  • $(_SandcastleNamingMethod) - Default value is "Guid"
  • $(_SandcastlePreliminary) - Default value is "False"
  • $(_SandcastleBuildAssemblerVerbosity) - Default value is "OnlyWarningsAndErrors"
  • $(_SandcastleNamespaceGrouping) - Default value is "True"
  • $(_SandcastleMaximumGroupParts) - Default value is "2"
  • $(_SandcastleCatalogName) - Default value is "VisualStudio12"
  • $(_SHFBApiFilter) - Default value is "<ApiFilter />"
  • @(SandcastleColorizer) - Default list is "cs;vb"
  • @(SandcastleComponent) - Default list is empty; however, the Code Block Component, API Token Resolution and IntelliSense Component are included immediately before building, so you cannot remove them.
  • @(_SandcastleHelpAttribute) - Default list is "DocSet;DocSet;TargetOS". The Value metadata of these items are {@HtmlHelpName}, NetFramework and Windows, respectively.
  • @(_SHFBTransformArguments) - Default list is empty. You may include: logoFile, logoHeight, logoWidth, logoAltText, logoPlacement, logoAlignment, maxVersionParts and defaultLanguage. Set the Value metadata to the desired value for each item.
  • @(_SandcastleContentLayoutFile) - Default list is empty.
  • @(_SandcastleCodeSnippet) - Default list is empty.
  • @(_SandcastleTokensFile) - Default list is empty.
  • @(_SandcastleResourceItems) - Default list is empty.
September 13, 2009

Sandcastle with Code Contracts

Microsoft Dev Labs has released a new version of Code Contracts.  (For more information about Code Contracts in the .NET Framework 4.0, see System.Diagnostics.Contracts and this article).  If you haven't yet, I highly recommend installing the latest Code Contracts release.  If you're using Visual Studio 2008 then you'll also get a shiny new tab in your project's Properties window.

Shiny New Properties Tab

Figure 1: Code Contracts tab in Visual Studio 2008 project Properties window

Along with the latest features is a new tool that adds documentation for Code Contracts to an assembly's XML documentation file.  The latest release also includes a Sandcastle patch that allows the vs2005 style to include the code contract documentation within an expandable Contracts section, as shown in the following screenshot.


Figure 2: Example Sandcastle output with Contracts section

The following blog post describes how you can patch Sandcastle so that it uses Code Contracts in XML documentation files.  The author chose to use DocProject to automate the build process, but I suspect that it will work with or without any automation tools for Sandcastle.


Note that I've tested this procedure with success in Visual Studio 2008 standard edition.

Just don't forget to create a new DocProject or DocSite project after applying the Sandcastle patch.  You can use the Import Topics and Settings step in the New Project Wizard to copy over the important stuff from an existing project if you'd like.


On a side note, I think this also about ruins my ContractN project ;).  I've abandoned it anyway, so I'll be doing the honorable thing and will close down the ContractN project on CodePlex at some point (to help keep CodePlex clean - just doin' my part).  I'll continue to host the code on my blog in case anybody's interested in learning how to use Context-Bound Objects, in some form or another.

July 08, 2008

MAML Editor: Progress II

In a previous blog post I discussed my work on a WYSIWYG editor for authoring MAML topics, either inside or outside of DocProject.  This post is simply another quick update on my progress.

Preview Release Timeline

A few weeks ago I started a new job and they put me on a project with a tight deadline so I haven't had much time to do anything else.  Last weekend I was still too busy to do much with the editor (even on July 4th) so I missed my most recent target date: yesterday.

I'll probably have time to work on the editor each night this week though so I should be able to put a working preview out there soon.  Last night I was able to almost complete key input behavior processing, which I had actually planned to work on after the preview.  I was also able to complete a few controls; e.g., the alert control now has a drop down list in the header with icon-text pairs as list items (shown in the screenshot below).  It was so easy to implement too compared to having to owner draw items in WinForms apps - WPF is really cool.  The next control I'm going to write is for MAML linking, which should be fun :)


I still have to add the command buttons but I've been deferring that because it should be pretty easy to do with limited functionality for the initial release (e.g., the editor's not schema based yet so all buttons will always be enabled.)  Although, I'll probably only add a small subset of commands initially, which will save time.

One thing that I may do for the preview though is to add the ability to insert custom command buttons through a dialog and have them associated with custom MAML markup. Once the markup is inserted, it can be parsed as if it was being loaded from a MAML file using the existing factory/parser infrastructure - that should fill in the gap nicely for MAML elements that I won't be providing support for in the initial release.  (Note that this is entirely conceptual - I don't know if it'll actually be worth the effort for the preview release.)

The other major feature that the editor is currently lacking is the ability to parse the physical flow back into MAML for save operations (it currently saves as XAML, for testing purposes).  I don't see this being a difficult process though since every element in the document is currently tagged with a parser context object, which provides direct access to the particular parser that can transform the element into MAML, in much the same way that it parses MAML into elements when a topic is loaded.  (Load functionality works fine :)

Originally I was hoping to avoid having to parse the physical flow by simply saving the in-memory LINQ to XML document (this was working for a short while during development), however I discovered later that the only change event that gets raised is the FlowDocument's TextChanged event (IIRC), making it difficult to track the relationship between changes in the flow and the underlying XDocument structure.  Although, I do see an opportunity to implement change tracking like this in the future due to my parser context and parser input behavior designs, but for the sake of time I'll probably defer it until a subsequent beta release.

Screen Capture

The following is an updated image of the same MAML topic being edited as in my last post.  It might not look like much has changed, but functionally speaking, it's now actually becoming a useful app (barring the missing save functionality :).

This time all of the styles that you see are loaded dynamically from XAML style sheets (currently embedded resources, but eventually loose XAML as well) and, although it's not obvious from the image, the editor actually behaves much more like you'd expect from a schema-based editor.  For example, pressing the Delete key at the end of the MAML Introduction will no longer cause the first section's header to move up into the introduction's paragraph.  This behavior is controlled by each individual MAML element - they define their own key press behavior using a custom preview & bubble approach, just like real WPF controls, but they also inherit some default behavior that restricts the flow a bit.

I've also started using WPF annotations for debugging (not visible in the image below) and I also plan to use them to display a delete button near the currently selected block element.  So to delete an entire section from the editor you would click anywhere inside the section and the delete button will appear, perhaps floating at the top-right corner of the element.  That's the way I think it should work for all block elements, such as the MAML introduction, section, procedure, alert table and code block shown in the image below.

(Note: The document shown below was actually loaded from a real MAML topic file.  The red squiggles are real-time spell checking errors provided by WPF and each element's styles were applied dynamically using XAML style sheets.)


June 16, 2008

DocProject 1.11.0 RC - Second Update

Another update was just released for DocProject 1.11.0 RC.  This update replaces the existing installer on the Releases page that was deployed for the first update.

For anyone that had previously downloaded DocProject 1.11.0 RC or the first update, you can download it again if you're experiencing the problem that was fixed by this update.

Note: Make sure to manually uninstall any existing version of DocProject before installing the new version since the version number was not incremented.  Use the Add or Remove Programs dialog in Control Panel.


This time I've fixed a single bug in the XML documentation editor whereby modifying comments in Source mode and then saving the changes would write <see /> elements as <doc:see /> elements instead, which of course Sandcastle ignores because the tags are in an unknown XML namespace.  A similar thing happens to other in-line XML documentation elements too.

I've tried testing a few different scenarios after fixing this issue and I can't seem to break the XML documentation editor anymore, but please keep the feedback coming if anyone can find some more stuff for me to fix.

June 14, 2008

DocProject 1.11.0 RC Updated

An update was just released for DocProject 1.11.0 RC.  It replaces the existing installer on the Releases page.

For anyone that had previously downloaded DocProject 1.11.0 RC you can download it again if you've experienced any of the following bugs.

Note: Make sure to manually uninstall an existing version of DocProject before installing the new version since the version number was not incremented.  Use the Add or Remove Programs dialog in Control Panel.

Issue 1

Missing root Namespaces node in Topic Explorer.


Documenting only one namespace.


The TopicManager class was only creating the root node if the topic had more than one namespace, but since this behavior is invalid it was removed.

Issue 2

Installing for Everyone and both VS 2005 and 2008 did not work properly; the Add-In would not appear in VS.


The custom action that copies the .AddIn files to the target directories is responsible for updating their content so that they're compatible with the target version of VS.  Since the target directory for both VS 2005 and 2008 is the same when installing for Everyone, one copy of the .AddIn file would replace the other, and even that didn't get updated properly.


Since there's already two separate .AddIn files for each version of VS the version number was hard-coded so that it doesn't have to be updated during the installation.  To fix the problem of one file replacing another, the names of the target .AddIn files now include the 4-digit year of the version of VS to which they apply.

Issue 3

Topic Editor does not handle XML documentation tags properly.  The end tag is always moved to the end of the section, causing the element to wrap all of the content from where it's defined to the end of the section.


The HtmlToXmlConverter class provides a mechanism by which tag names can be replaced but it only applies to the start tag of an element and not its end tag.  This issue was introduced when the HtmlEditor control library was updated for the DocToMaml 1.0 Beta program.

The reason why tag replacement is required in the Topic Editor is that a doc prefix is automatically associated with tag names that are registered in DocProject's configuration file since they are not valid HTML elements; the HtmlEditor control will only support an HTML element or an element that is associated with an XML namespace.  This allows styles to be applied, such as those in the TopicDesigner.css file and causes the control to treat the elements more like XML instead of HTML; e.g., unknown tag names are not automatically changed to upper case.  When converting HTML back into XML the doc prefix must be removed, hence the requirement for the tag replacement mechanism of the HtmlToXmlConverter class.


Tag name replacement now works on both the start and end tags so that the parser can properly close the element at the position where the end tag is found in the source XML.

June 09, 2008

DocProject 1.11.0 RC Is Now Available

DocProject 1.11.0 Release Candidate is now available on CodePlex.  It supports the Sandcastle May 2008 Release and contains many bug fixes and new features, most of which are listed below.

  • Full support for both Visual Studio 2005 and Visual Studio 2008 using a single installer.
  • Conceptual topics created in Topic Exporer are now saved with friendly file names and an .aml extension. A dependent companion file (.cmp) for storing metadata is created as well.
  • The topic import feature has been improved and now supports the inclusion of raw HTML topics in Topic Exporer. Legacy MAML topics (those with an .xml extension) are automatically imported into the new format and, if possible, a friendly name is chosen automatically.
  • An optional Import Topics and Settings wizard step has been added to the New Project Wizard. It allows for a single DocProject or DocSite file to be specified from which topics and settings will be imported into the new project automatically.
  • Wildcard characters, including directory recursion (**\ - but only on the most nested directory) is now supported in various dialogs, including External sources.
  • The External sources dialog is now available in the last step of the New Project Wizard.
  • Automatic checkout of source-controlled project items occurs whenever a project option or dialog must write to a file in the project.
  • ResolveExternalLinksComponent now works for conceptual builds and is automatically added to the conceptual configuration files when new DocProjects and DocSites are created. (The standalone release will also be updated.)
  • Open in Visual Studio toolbar button added to the DocProject External UI.
  • New Topic Explorer context menu commands: Copy as reference link, Copy as conceptual link and Copy as topic identifier.
  • New Topic Properties window that provides a user interface (UI) for editing conceptual topic metadata, such as Help 2.x DocSet attributes, index keywords and the topic's display title. This window is reachable by right-mouse clicking a conceptual topic in Topic Explorer and selecting Properties in the context menu.
  • New Help\Settings files are automatically included when DocProjects and DocSites are created:
    • conceptual_snippets.xml: Specifies code snippets written in multiple programming languages that may be included in conceptual topics.
    • tokens.xml: Specifies shared content items for both conceptual topics and XML documentation comments; items are referenced using <token>name</token> elements.
    • links.xml: Specifies external hyperlinks that can be used in both conceptual topics and XML documentation comments. (See ResolveExternalLinksComponent for more information.)
    • metadata.xml: Specifies global Help 2.x metadata that is inserted into all conceptual topics and auto-generated reference topics. Metadata can include attributes such as DocSet, Product, TargetOS and custom values.
    • bibliography.xml: Specifies global reference information for topic bibliographies. Conceptual topics and XML documentation comments that have citations as <cite>name</cite> elements will have bibliographies generated automatically.
  • New management dialogs for Help 1.x and Help 2.x configuration. (Settings are persisted to certain files in Help\Settings\Projects\, Help\Topics\Html\MSHelp2\ and the root Help\ folder.)
    • Configurable Help 1.x project options such as the list of source files, Binary TOC, Default Window and Display progress during builds.
    • Configurable Help 2.x project options.
      • Named URL values such as DefaultPage and HomePage, which may be chosen from a list of topics, and AboutPageInfo, EmptyIndexTerm and NavFailPage, which can be created with DocProject's HTML editor.
      • The Help > About image that appears in Document Explorer. (An HTML page that references the image is automatically generated for the AboutPageIcon named URL.)
      • Global metadata attributes, which are stored in Help\Settings\metadata.xml (more information above).
  • Improved MAML topic templates.
  • The behavior for detecting out-of-date sources and files has changed to allow for more control over change tacking.
    • Modifying individual conceptual topics may change the type of the next build. Changes are detected for MAML topics in Help\Topics\ and raw HTML topics in Help\Topics\Html\.
    • Starting Visual Studio and loading a DocProject or a DocSite does not force a full build anymore unless the output is actually outdated.
    • Another effect is that deleting the .chm or .HxS files no longer causes a partial build; instead, it always causes a full build. To force a partial build you must modify a partial build item.
  • Generate root API topic is now enabled by default in new DocProjects and DocSites.
  • Added inheritdoc tag to the DocProject configuration file so that it appears in the Topic Editor sections list when writing external XML documentation.
  • June 04, 2008

    Sandcastle Styles Project on CodePlex

    The Sandcastle Styles project is now live on CodePlex.  From the project's home page:

    The goal of this project is to improve Sandcastle by providing a rolled-up solution to various presentation style issues in a manner that is highly visible to the Sandcastle community and also involves community feedback.

    This project was started by Paul Selormey, Eric Woodruff and myself.  Currently we're the only active contributors but we'll be happy to take any feedback you have to offer.  Let us know by starting a discussion.

    Sandcastle features and issues should be submitted directly to the Sandcastle Issue Tracker so that the Sandcastle team will be notified.

    What's Inside?

    Eric has included his presentation style patches from the SHFB project - we're now deploying them as a part of Sandcastle Styles.  There are additional bug fixes and modifications that were made for the May 2008 release of Sandcastle as well.  He has also included a new MAML guide as a separate download and custom code providers for VB and C# that can be used to extract assemblies and XML documentation files from Visual Studio Web Site projects.

    We've also added some new features to each presentation style, such as support for the MAML glossary document type, image placement support in MAML, enhanced <autoOutline> in MAML, and also an auto-generated bibliography for both conceptual and reference topics.  Tools such as DocProject and SHFB support these features with the patches applied.

    I've started an Examples project that shows the typical usage of XML documentation comments (all tags supported by Sandcastle) and common MAML markup, such as linking, tokens, code snippets and media.  I've also included DocProject's MAML document templates for those that are using a different tool.  Lastly, there's an API that can be used to test Sandcastle filtering capabilities in our automation tools, which also provides some nice examples of how to add XML documentation to code and how to use the <include/> tag to share comments and keep code neat.

    We expect to improve our library of examples and include additional languages and project types in the future, and I hope to make it available as a separate download as well.  Also, if people will donate language packs for Sandcastle we'll tidy them up and host them.

    Hopefully the community will find this project to be a valuable Sandcastle resource.  Any feedback will be appreciated :)

    June 03, 2008

    MAML Editor: Progress

    This blog post is just an update on my progress creating a WYSIWYG (what you see is what you get) MAML editor.  I've received a lot of feedback (relative) for the MAML editor and I know that people are waiting for one, so I'd like to share with you some information about the one that I'm working on and when it will be available.

    For those of you who are unaware of what MAML is, you can read about it here.

    I've created a very basic MAML editor using .NET 3.5, C# 3.0, LINQ to XML and WPF, but it's not currently my priority since I'm planning to release DocProject 1.11.0 RC later this week.  A preview of the editor will be released though in the next couple of weeks as a standalone WPF application, a VS 2008 package (with MAML item templates) and also a standalone class library so that other tool developers can use the editor in their own applications - although note the dependency on the .NET 3.5 runtime and the DocProject license, which is currently the GNU-GPL.

    The editor isn't schema based yet - I've hard-coded support for the Conceptual document type only, although since that type shares many common elements with other types, like How To and UI Reference, they're basically supported as well.  The only difference now is that there's no schema validation and the UI cannot create several elements that are optional in the schema for the other document types.  Though the current implementation has been designed to be flexible enough so that adding these things should be easy to do later on.

    Since the editor is based on a WPF RichTextBox control, we get a free spell checker with squiggly underlines and an undo/redo buffer.  It's also really simple to implement custom control logic for various elements (the current implementation uses a factory pattern to generate parsers for the individual elements, by name), such as a link editor, tables, images, and other stuff.  So far I've added collapsible sections that actually function when you click the button, some custom logic that controls input behavior for various key presses, and also whitespace normalization for text (Run content in WPF).

    Loading and saving also works, however synchronization between the data model in memory and the logical tree of the WPF content model still needs to be implemented - a major part of the editor - but with the event model and my current architecture I don't think it'll be too difficult; e.g., the data model currently uses XElement instances (from LINQ to XML) that contain annotations for their corresponding WPF content elements (Section, TableCell, Paragraph, Run, etc.) when the data is first parsed.  The idea is to update the document directly when changes in the UI are detected.  Saving the changes are then as simple as saving the XDocument.

    Metadata is also editable, so I've decided to generate two separate files when saving a single topic.  The first file is the topic file itself, which contains the root topic node, its id and revisionNumber attributes, as well as the actual MAML content.  The second file is an XML companion file (to use the Sandcastle lingo) that contains metadata such as the topic's title, TOC title, MS Help attributes and index keywords.  I may have another XML-based file created in the future to save editor settings for individual topics, such as the visibility status of individual sections; i.e., a designer file.

    MAML topics are saved with an .aml extension (Assistance Markup Language) and companion files use a .cmp extension with the same base file name as the .aml topic.  In the VS 2008 package, the .cmp file will be created with a dependency on the .aml so that it appears as a child in Solution Explorer.  The next version of DocProject will provide support for these extensions so that when I release a preview of the editor your existing DocProjects and DocSites will already be compatible.

    There's still a lot more to do before the editor is actually usable for generating quality MAML topics, but it's on its way.  After a bit more functionality is implemented I'll blog about it in more depth and post some screenshots.  For now, check out a screenshot below of the editor as I edit a simple How To topic that was previously written using Visual Studio's XML editor.

    (Note that this is just a temporary WPF app that hosts the control while I develop it.  The final app will have command buttons for semantic markup, such as database, ui, application, system, localUri, etc. and block-level elements such as section, procedure, list and table.   I didn't implement them yet because commands seem pretty simple in WPF and I wanted to concentrate on the basic editor support first, as a WPF proof of concept (I'm a first-time WPF developer :)


    The image above shows a MAML topic with introduction text, a collapsible section, a procedure and a code example.  I also splashed some style in there, like the large font for the section title, just for the screenshot (the final editor will most likely get style information at runtime from WPF content resource themes so that its appearance will be completely customizable, without having to rebuild the source code).

    Clicking the toggle button for the section will actually toggle the visibility of the section's content in the editor (note that the image is ugly only because it's on a button and I didn't remove the border yet).  I plan to add other controls as well for functions such as adding links, tokens and media.  The controls will actually be inside the document as part of the flow like the section toggle button - this is one of the really powerful features of WPF 3.5 flow documents.

    There's even a context menu with Cut, Copy and Paste commands that I didn't have to write since it's provided by WPF.  Editing the text and everything else behaves exactly like you would expect from a WYSIWYG editor, which also means that I'm going to have to add custom logic to attach behavior to specific elements so that everything is a bit less fragile.  For example, one thing that I've done already is to add a behavior so that when the Enter key is pressed the cursor moves to a new line instead of an entirely new paragraph.  Pressing Enter a second time, while on the new blank line, will delete the blank line and start a new paragraph (it's more complicated than that, but you get the idea).  Having a new line within the same paragraph won't change the MAML output, it just provides some control over the appearance while editing.  Of course, if this is confusing or annoying I can always remove it later.

    I'd like to get feedback on my ideas so that I can quickly provide an editor that people are satisfied with.  If you have any suggestions about how the editor can be improved please let know.  Thanks!

    May 03, 2008

    DocProject Roadmap Part II

    In my first DocProject Roadmap post I described my preliminary plans for DocProject 1.x and later versions.  In this post I'm going to discuss the project's current status and some updates to my plans for future versions.

    1.11.0 RC

    DocProject 1.11.0 RC will be deployed within a week after the upcoming Sandcastle release.  It contains several new features and bug fixes, and also a few breaking changes that I'll be sure to mention on the release page.

    I expect a few changes to Sandcastle that may prompt the addition of a few new features to DocProject before the next release (e.g., support for Help 1.x and Help 2.x project management and, possibly, the ability to include raw HTML topics using Topic Explorer), but since I can't start working on them until Sandcastle is released, there's obviously going to be a delay.

    A week should be more than enough time though since I've taken some time off from paid employment to work on my open source projects - a sacrifice that I can barely afford, but working on my own projects is more fun than writing line of business apps and I just couldn't resist after losing my only client anyway (they lost their biggest client first and had to suspend my services, maybe indefinitely).

    Universal Installer

    The next version of DocProject, 1.11.0 RC, can install DocProject for Visual Studio 2005 and 2008 simultaneously, including all supported Express editions.  The code base for DocProject 1.x and DocProject 2008 are now identical and as a result DocProject 2008 now uses the 1.x assemblies.

    Ending Phase I

    I've done a lot of refactoring in 1.11.0 RC, but I still plan to deploy it as the final release candidate (RC) for DocProject 1.x, with compiler optimizations enabled and without any debug symbol databases (.pdb).

    Feedback is a must in this release so that I can iron out showstoppers and maybe even add some mission-critical features that people have been waiting for.  If you're a fan of DocProject and you use VS 2005 then now would be the time to get in your suggestions for DocProject 1.x since most of my focus in the next phase of development is going to be on Visual Studio 2008.

    Unfortunately I didn't get to add some of the features to 1.11.0 RC as I had planned, but they may be added to 1.12.0 or, more likely, DocProject 2008 Beta 3.

    First Production Release

    I still expect 1.12.0 to be the first production release of DocProject, but now it will target both Visual Studio 2005 and 2008.  To support this I've reorganized source control, once again, and included the source for other projects as well, such as DocToMaml.  I've also decided not to package the source code with the installer anymore, starting with 1.11.0 RC.

    My plans for DocProject 1.x after the first production release are to provide subsequent releases for bug fixes and small feature updates only, targeting both VS 2005 and 2008.  The major features that I have been planning will make their first appearance in DocProject 2008 Beta 3.

    DocProject 2008

    After I deploy 1.11.0 RC, development will continue on both 1.12.0 RTW and DocProject 2008 Beta 3 simultaneously, although the most notable of new features will only be included in DocProject 2008 Beta 3.  Some of these features are described below.

    Please let me know which features you're most interested in so that I can prioritize.

    Visual Studio Package

    DocProject currently provides an Add-In that only uses VS automation, but I'd like to provide more integration to create a better Topic Explorer, Topic Editor and Topic Designer, and even a preliminary MAML editor.  I've done some initial research and have already come up with a plan to start development.

    This is an exciting task to work on but I don't plan on the first release being extremely stable as this will be my first VS package; although, I do plan on reusing a fair amount of the automation code since it has already been tested.  I'll also incorporate much of DocProject's current architecture, including its high level of extensibility and its "openness".

    Business logic, infrastructure and utilities will probably end up being mostly the same, but I do want to take this as an opportunity to update some of the designs that DocProject currently uses, like change buffering.

    Standalone UI

    The current DocProject External UI program relies on DocProjects and DocSites that have been created in Visual Studio.  For help authors that just-so-happen to be developers, this isn't a problem.  But for anyone that isn't a developer, the free Visual Studio Express edition works well but doesn't make much sense since it's obviously not designed just for building documentation, and certainly not for authoring it.

    DocProject 2008 Beta 3 will use the new Visual Studio 2008 Shell to provide a tool that has all of DocProject's features, but without requiring Visual Studio to be installed.  I haven't decided yet whether I'm going to use integrated or isolated mode, but I'm leaning towards integrated.

    This should be quite easy to create since DocProject is becoming a VS package anyway.  A blocking issue though is whether MSBuild is provided by the Shell redistributable.  If not, then I may just have to continue to deploy the External UI instead.  I'm also not sure whether the Shell provides C# and VB.NET source code editors, but if not it's no big deal since they aren't available in the current External UI either.  (The code editors would be used to edit the project's build process component.  I think this would be a great feature to have in the standalone app, if possible, but it's not a requirement.)

    My ultimate goal for the standalone UI is to create a program that works with or without Visual Studio.  It must provide the ability to create new DocProjects and DocSites from existing MSBuild project templates, so they work in Visual Studio as well.  It will also provide all of DocProject's existing and upcoming features, including support for UI extensibility; e.g., providers can register new tool bars and tool windows.

    Continuous Integration

    A project option will be available to enable support for continuous integration.  When enabled, DocProject will copy all dependencies into the project, including DocProject and Sandcastle assemblies, configuration files, and the HTML Help Workshop program, allowing them to be easily committed to source control.  After a DocProject or DocSite is checked-in, another team member can get the latest version to their computer or to a build server and all the dependencies will be updated as well, without requiring any installation.

    The only blocking issue of which I'm aware seems to be that Help 2.x requires installation.  DocProject does not use any of the command-line tools that are installed by the VS SDK, however, it does use the MS Help COM interfaces.  Unfortunately, to get the libraries and COM objects installed you must install the VS SDK, but to install the SDK you must first install Visual Studio.  I'll continue to research this when the time comes to see if I can find a workaround, but so far it doesn't look good.

    Continuous Builds

    I mentioned this in my previous roadmap post.  The idea is to detect only the changes made to APIs and XML documentation and have a web server that continuously rebuilds a live DocSite so that the updates are visible immediately to all team members.

    This feature will require dependency detection and differencing algorithms for both API references and XML documentation.  One question is whether these algorithms will perform better than building entire documentation sets from scratch, but I believe that they certainly will in the scenarios where it really matters.

    The goal is that for projects with many large assemblies there should be little delay to see the updates in documentation, at least compared to the very long delay that ensues when rebuilding entire documentation sets from scratch, which is currently the only option with Sandcastle.

    To use this feature you would start be creating a new DocSite project and probably selecting some option in the New Project Wizard to indicate that you want continuous build support.  You would also select a VS solution file or an MSBuild project that the DocSite will use to automatically build sources.  In the last wizard step you would add all of the sources to the project as project references, like normal.  When finished configuring the project as usual, you would deploy it to an intranet web server that all team members can access over HTTP.

    The live DocSite would trigger a rebuild using MSBuild at a configurable time interval.  This way MSBuild will detect updates automatically and the DocSite will always have the latest versions of all sources.  The DocSite will monitor changes to the sources and continuously rebuild only those topics that were affected.  It will also update the DocSiteContents.xml and DocSiteIndex.xml files, as well as the full-text search index.

    One problem might be getting the latest source code onto the server so that the DocSite can rebuild it.  In a team scenario it's probably safe to assume that some sort of source control system is in use.  I'm not sure if it's possible, but if source control systems provide an event model that could be used to automatically get the latest version to the web server after each check-in, that would solve the problem.  Otherwise, manually getting the latest version to the server may be required.  It may be possible to access the source code over a network share (to a build server perhaps) so that it doesn't have to be stored on the web server, although I'm not sure if MSBuild works with UNC.

    Using external sources instead of project references may be another option, but replacing the assemblies on a network share automatically might be just as difficult.  It could be done manually or, as with the solution for project references, using source control events to run a build after each (labeled?) check-in.


    I've already put a few hours into researching localization support in DocProject.  What I discovered, and I'm not surprised, is that if I want an implementation that isn't a hack I'll have to add some new features to support dynamic changes to various configuration files during builds.  Anticipating this problem, I had decided to defer localization support into DocProject 2008.

    I suspect that these new support features will be useful on their own as well, much in the same way that extension methods in C# 3.0 were probably added to support LINQ yet they are even useful by themselves.  The new features will add to DocProject's already high level of extensibility and will be customizable via the DocProject configuration file.

    My goal for localization support is for a single DocProject or DocSite to produce multiple compiled help files for different locales in a single build.  This must be accomplished without affecting the current feature-set of DocProject, including the Sandcastle Build Component drop-down properties and the fact that you can currently change almost anything that you want in the BuildAssembler configuration files.  So in other words, the localization feature must be completely transparent when it's not being used.

    All Sandcastle content items and user-written XML documentation comments will be localizable.  Once implemented, I plan to ask the community to create language packs for content items in various locales (Unfortunately, I only know English, and not so well ;).  A language pack will be a .zip file that contains one or more Sandcastle content documents and an XML manifest file, which describes the contents and rules for locale inheritance.  DocProject 2008 will be able to locate the packs in its installation directory, by default, or a user-configured location.

    With language packs, DocProject can offer out-of-the-box localization for multiple languages so that help authors can simply check a box and build their project to produce multiple compiled help files, one per language.  Localized XML documentation comments can be added to the project's Help\Comments\[locale] folder (e.g., Help\Comments\en-GB) and it will be merged automatically with XML documentation comments from the source code (how it's merged will depend upon the Merge XML documentation project option, in the same exact way that it works now in the current version of DocProject).  Likewise, localized conceptual topics (MAML) may be added to the project's Help\Topics\[locale] folder.

    Instead of trying to write down the many concepts related to implementing localization support that I have echoing around between my ears, I'll just post my notes in their raw form.  If you want more details, please let me know.

    1. add content item mappings to DocProject config file:

      <item name="..." presentationNames="Visual Studio 2005, Sandcastle Hana" source="options-property-name"/>

      - Items that are added here are automatically removed from the content item documents when a project is

    first created.
      - Before each build a dynamic content item document is generated in the working directory for all of the

    items that are configured here.
      - Note that a configChange must be added to register the dynamic content item document.

    2. Add a wizard step, before the Create Shared Content step, that allows a user to specify the values for

    each of the pre-defined_enum_names:

      - Documentation set name
      - Running header text
      - Copyright
      - Company name
      - Default locale (combox box)

    3. Add a Localization Management dialog.

      - Choose the different locales in which distinct documentation sets will be generated by selecting from a

    drop down list, which will add the selection to another list.
        - one locale may be selected as the "working" locale for the dialog; UI elements will apply only to the

    "working" locale.
        - a tree view, like solution explorer, shows only the folders that may be localized within the project;

    e.g., Help\Topics, Help\Comments, etc.
        - one node may be selected at a time.
        - for the selected locale/node, a button can be clicked that will prompt the user to choose a locale from

    which to import files, with the option of specifying whether the import should be performed recursively.
      - Choose a default locale (corresponds to the wizard step option indicated above).
      - A single build will produce all of the documentation sets in each locale.
      - The BuildContext should have a property that returns the current LCID that's being built and another that

    returns the list of all LCIDs that are being built.
      - Output will be stored in sub folders named with the locale (e.g., bin\Debug\sp-SP\ or Help\bin\sp-SP).
      - Local input will be stored in sub folders named with the locale (e.g., Help\Topics\sp-SP\,

    Help\Comments\sp-SP\, Help\Presentation\Style\Content\sp-SP, Help\Presentation\Shared\Content\sp-SP).
      - The default locale's content will be stored at the root;  e.g., Help\Topics\, Help\Comments\, etc. so the

    build process for the default locale will work the same way that it does now.
      - Source input can be managed in the same way that version management works.

    4. Support dynamic updates to config files at build time.

      - Take all of the <add> elements in the <configChanges> element and move them under a sub element named,

      - Add a new sub element named build that will contain <add> elements for changes to be applied during

      - replacements for build changes will work the same as for import changes, although they will also allow

    string replacement tokens: {0} {1} {2} ...
        - The values of replacement tokens will be defined by attributes on the <add> element: value0="..."

    value1="..." value2="..."
        - The values of the replacement attributes are strings that identify the names of public properties on

    the current derived implementation of the BuildSettings class during builds; e.g.,

        - Single-valued properties are converted to strings using Convert.ToString().
        - Properties of System.Collections.IEnumerable implementations are iterated and each element is handled

    recursively.  Single-valued elements are converted to strings and IEnumerables are iterated. 

    The replacement is executed once for each iteration, recursively.
      - When a build starts the configuration files that will be used are copied to the working directory and

    then the build changes are applied.
      - Build assembler will use the config files in the working directory.

    5. Support dynamic localization of config files at build time.

      - Add a new sub element to <configChanges> named, localization.
      - replacements for localization changes will work the same as for build changes, including replacement

    tokens, expect that replacements are specified as properties of the current BuildContext object.
        - BuildEngine implementations should be able to override a method to create a BuildContext

    implementation, such as SandcastleBuildContext, so that properties such as Lcid and Locale are dynamic.
      - When a localized build starts (not the BuildStarting event but the first step of a localized build, which

    is executed repeatedly within a single build - once for each locale), the configured localization
        changes are applied, for the current local, to the working copy of the build assembler config files. 

    Build assembler must then be executed against the localized copy.  (The original copy must not be


    ** The explanations above were created before this example.  This example illustrates the _better_ approach

    when there are conflicts in the notes above since it's more thought out.


    - DaveSexton.DocProject.dll.config -

    Sandcastle presentation configuration section

      <presentation name="..."

    ... all of the attributes that currently appear in a presentation's add element ... >
          <add name="RunningHeaderText" type="System.String" displayName="Running header text"
               description="The text that will appear at the top of each topic." category="Configuration"

    sort="80" />  <!-- the specified type must be convertible to and from System.String

    (serialization is not supported) -->
          <item name="runningHeaderText" value="RunningHeaderText"/>

    <!-- value is the name of a dynamic project option here, but it can be any property that

    exists on a DocProjectOptions implementation -->
          <step type="type name" assembly="assembly name"/>

    <!-- steps are inserted before the Create Shared Content step in the order that

    they are added here -->

      ... more presentations

        ... all of the stuff that is currently in the configChanges section ...

        Note that the default comments folder should be changed from Comments\*.xml to Comments\default\*.xml

    since comments should be segregated by locale; 'default' is used since the default locale can be changed.
        <add name="assign default reference links locale" ....
             xpath="find ResolveReferenceLinksComponent2 locale attribute"
             value0="Locale" />  <!-- Locale refers to a property (that must be added) on the

    SandcastleSettings class -->
        <add name="assign reference links locale" ....
             xpath="find ResolveReferenceLinksComponent2 locale attribute"
             value0="Locale" required="true" />
        <!-- Locale refers to a property on the SandcastleBuildContext class (this class does not currently

    exist; it will derive from BuildContext) -->
        <!-- The required attribute indicates that append should be used if no node is matched by xpath;

    although, I'm not sure if I'll be able to determine programmatically whether xpath is selecting an

    attribute or an element -->

        <add name="assign localized comments" ....
             xpath="find CopyFromIndexComponent with index name='comments' and select


    value0="Locale" />

        <add name="assign shared content items" ....
             xpath="find all of the shared content component's content items that start

    with ..\..\Help\Presentation\"
             replaceWith="..\..\Help\Presentation\content\{0}\{1}" value0="Locale" value1="Regex:[^\\]+.xml"
             collection="true" />  <!-- the collection attribute will indicate whether xpath is expected to

    return a node collection, in which case this change is applied to each node -->

    April 25, 2008

    Sandcastle: Auto-Generated Bibliography

    June 11, 2008 Update: This feature is now available as part of the Sandcastle Styles patch and DocProject 1.11.0 RC.

    Wouldn't it be cool if you could cite books and web sites while authoring MAML and XML documentation comments and have Sandcastle create a per-topic bibliography automatically?

    Someone posted that question in the Sandcastle forums recently and I came up with a solution (in that discussion) that works for the VS 2005 presentation style and both reference and conceptual builds.  Please add your vote to this feature request if you're interested in having this ability in Sandcastle.

    This isn't a feature that I'm going to add specifically to DocProject since it requires updating XSL transformations.  You can add it yourself for now though until it becomes a feature of Sandcastle (hopefully :).  Just follow the instructions that I gave in my post in the Sandcastle forum.

    Once you make the appropriate updates to the presentation style, here's what you can do to start using this feature in code comments.  (Conceptual usage is similar, although you must add an empty <bibliography/> element somewhere in the root of your MAML, preferably before or after the relatedTopics element.)

    First, author some XML documentation comments that contain citations.

        The statistics show that Sandcastle is a popular tool on 
        CodePlex <cite>sandcastle activity stats</cite>.
        DocProject can be used to automate Sandcastle <cite>DocProject</cite>.
        The top referring sites are similar for DocProject and 
        Sandcastle <cite>sandcastle activity stats</cite><cite>docproject activity stats</cite>.

    Next, create a bibliography.xml file that provides additional information.  It will be used for all topics that you write in both conceptual and reference builds.

    <?xml version="1.0" encoding="utf-8" ?>
      <reference name="sandcastle activity stats">
        <title>Sandcastle Activity Statistics</title>
      <reference name="docproject activity stats">
        <title>DocProject Activity Statistics</title>
      <reference name="DocProject">
        <author>Dave Sexton</author>

    Each in-line citation will be replaced with a hyperlink and a number, which corresponds to an entry in the bibliography that is automatically generated at the bottom of each help topic when one or more <cite> elements are detected.

    Example Sandcastle Bibliography