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 19, 2008

DocProject 2008: Custom Visual Studio Project System

For the last couple of weeks I've been testing a new VS package for DocProject 2008.  You can read more about my plans here.

More recently I've been working on a new project system that integrates into Visual Studio 2008 but the current implementation only provides a single template, .docproj, which has very limited functionality at the moment.  I'm considering whether I shouldn't bother creating a custom project system if I can't do what I want since the current implementation (zipped templates copied to a folder during installation) provides seamless integration into VS already and won't require me to invest any more development time in this area.

However, I'd really like to have a custom project system that inherits from the project system that VS provides for the C# and VB.NET class library/web application templates since it will provide the following advantages to DocProject:

  1. Inherit all of the functionality provided by .csproj and .vbproj, including full support for the class library and web application project sub types.  (I'm considering using .csdoc and .vbdoc as the new file extensions.)
  2. I have lots of tested automation code that works against the VSProject system already (provided by EnvDTE).  It could be reused with only minimal changes, if any at all.  This will mean that I'll be able to deploy the next release much sooner and with minimal impact to DocProject's existing codebase.
  3. I could get rid of the DocProject Properties command and tool window and instead integrate the property grid into the typical Properties window by adding a new tab named, DocProject.
  4. Use custom MSBuild properties to store project options instead of using the automation Globals collection, which stores all custom data as attributes on a UserProperties element.  Using actual MSBuild properties provides the obvious advantage of being able to easily set project settings for command-line builds and also has the advantage of being able to make certain properties dependent on the active solution configuration.  (The latter point has been a feature that I've been considering for a while but I've felt that it's not worth the effort to implement if I have to roll my own solution via automation code, so it's been deferred until DocProject 2008.)
  5. Create special project folders that have a different appearance and provide custom behavior when double-clicked; like the Properties folder for example.  In DocProjects and DocSites, the Help folder would probably be a good candidate for a different appearance.  The Comments, Settings and Topics folders could probably have a different appearance and behavior.

I've posted a few questions to the VSX forum in the hopes that someone could give me some pointers as to how I can accomplish my goal of implementing a partially custom project system in Visual Studio 2008; i.e., a system that inherits from the VSProject system that can be automated through the EnvDTE library.  If anyone can answer my questions I'd really appreciate it so that I can make a decision about whether a custom project system is worth the effort for the next Beta release.  Thanks :)

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 06, 2008

    Visual Studio Gallery Updated

    It appears that Microsoft has improved the Visual Studio Gallery by adding the ability for users to rate and review products.  The interface was jazzed up a bit as well.  Nice work MS - the original gallery was more like a project dump but the new release is community-oriented, which I think people will appreciate.

    DocProject has been in the top 10 most visited projects since the VS Gallery went live (it was in the top 3 for quite a while too), which just goes to show you how important documentation is to developers when a tool such as DocProject is more interesting than tools that aid in development.  This certainly motivates me to continue working on it for VS 2008 :)

    I'd like your feedback so please drop by and write a review if you can find the time.  Thanks!

    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 24, 2008

    MAML Migration: The Next Step in the Evolution of Help Authoring

    Are you part of that herd of developers that is used to documenting applications by writing help topics in raw HTML?  The power of it is nice, being able to add a pinch of bold here, a splash of italics there, some CSS for different layouts, a floating image, several nested tables, an abundance of hyperlinks, embedded Flash and media players, and even some JavaScript to boot.  What more could we want?  Or maybe a better question is, what could possibly make us want to give any of that up?

    XML Documentation Comments

    Well, XML documentation comments that may be added to code modules (I'm assuming everyone's familiar with this stuff by now) was one thing that prompted .NET developers to start documenting their code without using HTML.  It's nice to be able to apply a bit of XML structure to our documentation, isn't it?

    Commonly used semantics for describing an API may be expressed in a universal way with XML tags such as summary, remarks and example, and the compiler builds an XML documentation file that contains the code comments found in each module when we build our project.  If you take a look at the contents of this file you may see a repeating pattern - schema - that seems like it could be used by some other tools to do, well, other things with it...

    Compare XML documentation to your legacy HTML help topics and what do you notice?  The XML comments that you add to APIs do not typically contain much layout or formatting, whereas your HTML topics are chock-full of <b>'s, <i>'s, and <u>'s, and a whole mess of other HTML to describe the document's layout and formatting.  Ok, ok, if you've done it correctly then you've made judicious use of CSS - applying class names to all of those <h*>'s, <div>'s, <span>'s, <p>'s, <a>'s, <td>'s, <tr>'s, <ol>'s, <ul>'s, <dl>'s, and certainly many other HTML tags that only add to the confusion when authoring topics (as opposed to designing them).

    Now you might be thinking, "Dave, it's not entirely true that XML documentation is without formatting.  What about the para, code and c elements?".  And to that my reply would be, "Ok, so then what exactly do they look like?".  If you look in the XML documentation files that are produced by your compilers, you'll see the markup exactly as it appears in your code modules.  In other words, no HTML and no CSS - nothing more than semantic usage: paragraph, code block and in-line code.  (If you were thinking something more like, "leading white-space, use pre formatting, code coloring and a fixed font", then you're getting ahead of yourself, so slow down!)

    My point is that the semantics for the aforementioned XML documentation tags are clear (i.e., what the tags represent), but their appearance is not yet defined (i.e., their style and format).  Take a look at the other Recommended Tags for Documentation Comments and you won't find anything out of the ordinary.  Each tag has an obvious reason for its existence - to mark up regions of text that serve a particular purpose in the documentation.  But how do they look?  Nobody knows!  ;)


    Now's probably a good time to introduce Sandcastle.  For those of you that aren't familiar with it yet, Sandcastle is Microsoft's tool set for producing HTML help topics dynamically by inspecting managed assemblies and incorporating the markup from XML documentation.  From the assemblies that you provide to Sandcastle, it automatically infers a table of contents (TOC), various pseudo-topics such as Properties and Methods, and also generates many individual topics to cover the entire API.  The documentation you've written within XML documentation tags, such as summary, remarks and example, is automatically added to the generated topics in the appropriate places.

    The results of running Sandcastle on your assemblies and XML documentation is a set of files that are web-ready HTML help topics for your project.  This is typically referred to as reference documentation, since it provides a reference for developers that use your API.  These topic files can be used as input to a tool such as HTML Help Workshop (Help 1.x) to produce a stand-alone compiled help file (.chm) that may be distributed with your application as an external help module.  The .NET Framework even gets in on the action by providing helpful APIs for integrating context-sensitive help and Help 1.x navigation into your managed applications.  (See the Help class for more information.)

    Presentation Styles

    Sandcastle provides three presentation styles that it can produce for your documentation out-of-the-box.  Each one consists of a set of XSL transformation files that convert XML documentation into XML-based HTML (not XHTML, however).  They also contain resources such as icons and, of course, CSS style sheets.

    For an example of a Sandcastle presentation style, look no further than the documentation for Visual Studio and the .NET Framework on MSDN.  The appearance that MSDN uses is similar to the VS2005 presentation style in Sandcastle.  I believe that Microsoft actually uses a customized version to build their internal documentation, even for Visual Studio 2008.  The other, experimental styles, that ship with Sandcastle are Prototype and Hana.

    For more information about Sandcastle, see my Sandcastle Help article on CodePlex.

    From XML Documentation Comments to Reference Documentation

    So the process is actually quite simple.  As developers we can easily document our source code using XML documentation, which allows us to concentrate more on writing the content instead of having to worry about formatting it with HTML.  When we build our project, the compiler will produce an XML documentation file that can be passed to Sandcastle, which then inspects our assemblies and automatically generates reference documentation that includes the comments that we added to our source code, but in a pretty HTML/CSS-based style that looks very similar to MSDN.  Nice!

    User Documentation

    Sandcastle can automatically generate reference documentation that is useful to other developers, but what about user documentation?  I mean things like How To, Sample, Walk-through, Overview, etc. - stuff that an end-user would want to have.  Well don't expect Sandcastle to know what you're thinking - we still, unfortunately, have to get concepts out of our heads and into help topics manually.  (At least for the time being, until someone invents HAL ;)

    Conceptual documentation (how Sandcastle refers to user documentation) is often much harder to write than XML documentation comments since it requires a more in-depth understanding of the application being documented.  It's easy to look at the source code, notice that an exception is being thrown and then add an exception element to the XML documentation comments for that API.  Or to notice that a particular algorithm is being used and to add a comment in the remarks element that mentions it.  But to understand and be able to express the purpose of different user interface (UI) elements, how to perform various UI-related tasks, and how the individual APIs and components fit into the designs of other high-level processes in an enterprise-level application, is certainly more difficult and typically requires an understanding of many different aspects of the application.  So the bigger the application the harder it is to write conceptual documentation, and not just because it's more time consuming but also because it's more complex.

    So if writing conceptual documentation can be more time consuming and harder to accomplish than writing XML documentation comments, why do people still insist on writing conceptual documentation in HTML?  Maybe the advantages of XML documentation comments can be applied to conceptual documentation as well.

    The Perils of Writing HTML Help

    I started this post by pointing out one very common way of writing help: raw HTML.  We've all done it, and I know that each time I do I end up reinventing the wheel all over again.  A new HTML layout, CSS styles, some new and strange way of cross-referencing, JavaScript for collapsible sections, etc., must all be redeveloped.  (Yea, some companies are too cheap to buy a tool that does this automatically - and so am I. :)

    Creating a new help topic starts with copying an existing HTML file that is used as a template, of which there's usually only one kind containing a header, with style sheet links and scripts, a body that's empty, and a footer.  Writing a help topic requires having to look through the other topics quite often to find out which HTML tags and CSS class names I should be using for various styles.  This is especially annoying when I have a good idea that I simply want to put down quickly and be done with it.  Uh oh, that hyperlink to an HTML topic that I've been copying and pasting throughout my documentation is actually misspelled - time to do a search and replace.  Hmm, I'm not sure that I like the format that I've been using for laying out tables - oh well, it's not worth the effort to fix it now.

    Is There a Better Way?

    Technical writers, I can only assume, take help authoring more seriously than that.  They get paid to worry about things such as structure, readability and maintenance, so it shouldn't surprise us to know that there's a much better way to write help than simply using raw HTML.  As developers, we could probably learn a thing or two from them when writing our own documentation, whether it's for an API or conceptual topics.

    Lucky for us, Microsoft has a huge library of documentation and employs technical writers to write their "official" help, which is then published to the web on MSDN.  (Sorry about that horrible reference for technical writers, but I couldn't find anything better.  I know that I've seen someone from Microsoft, probably Anand, state that they don't use developer code comments internally and instead have professional authors write it.)  This means that over the years they've had to come up with a solution that makes authoring help manageable, which is a huge task for such a large documentation set.  They also needed a way to manage file names and links for cross-referencing help topics (think, See Also section).  Since the look and feel of MSDN changes from time to time, the ability to write documentation that is absolutely independent of any one style or format was imperative as well.

    So we have an invaluable example to which we can aspire.  A whole plethora of documentation written with clarity and precision using standardized techniques.  If you take a look at the documentation on MSDN, you should see a crisp and clean style that, when compared to your raw HTML help topics, probably looks far more professional.  This is nothing new to us though - we've been referencing it for quite a long time now as .NET developers.  Many people, predating .NET, have even watched MSDN documentation improve dramatically over the years, and most developers that need to write their own documentation seem to want to reproduce the same look and feel.  Many tools have even helped us to generate reasonable facsimiles in the past (such as NDoc).

    But have we finally come to the point where we can write our own help topics without having to remember abstract HTML tags and CSS class names?  Can it be transformed automatically into documentation that looks the same as MSDN, or any other style for that matter?  Is there a way to simply specify a unique identifier for another topic and have hyperlinks generated automatically?  What about linking to reference topics?  Is there a way to ensure that topics of a similar nature will all share the same exact structure?

    The answer to all of these questions, of course, is yes.  (But wouldn't it be funny if it was no?  I'd probably take a nap.)

    Microsoft Assistance Markup Language (MAML)

    Microsoft uses Sandcastle internally to generate help topics for the .NET Framework, so it's no wonder that Sandcastle also provides a way to apply structured authoring techniques to conceptual documentation, in much the same way that XML documentation comments are used by developers to write reference documentation.  In Sandcastle, conceptual topics are written in MAML.

    MAML is an XML schema that defines various high-level document types, such as How To, Walkthrough, Sample, Glossary, Whitepaper, Troubleshooting and many others.  These document types provide the structure of a help topic, which doesn't change.  What can change though, is how Sandcastle presents this structure when it generates HTML topics.  This means that, for example, the markup in all of your How To topics will look similar, regardless of the presentation style that you choose.  As a matter of fact, the markup in your How To topics will be similar to mine, even if we choose to produce HTML help output in very different styles.

    The schema also defines various XML elements that mark up text using a semantic approach.  For example, the ui tag is applied to text that corresponds to a user interface element, such as the text on a button.  Another example is alert, which also requires an attribute named, class that indicates the type of alert, such as note, caution, tip, warning, and others.  Another is country, which you may have already guessed, describes a country!  You would surround text with an application element when it represents the name of an application.  I think you get the idea...  By my count there's well over 40 elements that you can choose from.   And with Visual Studio's XML editor you can actually have IntelliSense tell you what they all are and where it's appropriate, within the topic's structure, to use them.

    The beauty of all this is that the Sandcastle presentation style that you choose controls the HTML layout of the MAML document type used by your topic.  It also defines how all of the MAML elements will appear in the HTML.  For example, alert is transformed into an HTML table layout, while ui and application are simply bolded.  Special formatting is not actually applied to text that is specified as being the name of a country, but you could update the transformation to change the HTML markup or possibly just add a CSS rule to apply the formatting that you want, without having to update the actual topic itself.

    A MAML Example

    Here's a small portion of the Glossary help topic that I've written for my Auto-Input Protection (AIP) project.

    <?xml version="1.0" encoding="utf-8"?>
    <topic id="14790228-f45b-42d5-9b3e-f6b4ab932b9e" revisionNumber="0">
      <developerGlossaryDocument xmlns="" 
                An acronym that stands for Auto-Input Protection.
                A user's or bot's response to a challenge.  In AIP, the correct answer is a 
                string of text that matches the text on the CAPTCHA image.  An incorrect 
                answer does not match.
                An acronym that stands for Completely Automated Public Turing test to tell 
                Computers and Humans Apart, trademarked by Carnegie Mellon University according 
                to the following article: <externalLink>
                  <linkText>CAPTCHA. (2008, March 26).</linkText>
                </externalLink> In Wikipedia, The Free Encyclopedia. Retrieved 09:01, March 27, 2008.
                A CAPTCHA image, being displayed on a web page, to which a user must respond 
                with an answer by entering the text that they see on the image.  The result 
                is pass or fail.

    The following image shows the results of the glossary transformation into HTML, built by DocProject (a tool that I've written to automate Sandcastle inside Visual Studio).  The VS2005 presentation style was used for this example.


    And now here's the same exact topic file after being transformed into HTML using the Hana presentation style.


    There are a few things to point out about all of this.

    First of all, notice that the topic that I've written only uses some very basic XML, yet the output obviously contains additional layout and style, which differs depending upon the presentation style that I've chosen.  In the Hana version I've even left in the default header that warns about pre-release documentation.

    You may have also noticed the letter bar and the individual letter sub headers.  Where'd they come from?  These features are not actually part of Sandcastle, but Eric Woodruff and I have added them to the presentation styles by modifying the XSL transformations that convert the MAML Glossary document type into HTML.  The additional behavior automatically detects the glossary terms in the topic and creates the letter bar and headers dynamically.  All of the terms are sorted alphabetically as well (although it's not obvious in my example because they're already in alphabetical order in my topic file).

    Pretty cool, right?  You'll be able to get these Glossary updates from the new Sandcastle Styles project on CodePlex, which should go public within a few days after the next Sandcastle release.  This project was started by Paul Selormey, Eric Woodruff and myself.  In the last week we've been diligently working on preparations for our first release, so please check it out when we go live and let us know what you think :)

    Linking in MAML

    The last thing that I want to point out about the previous example is that it contains a hyperlink to an external web site.  As you can see from my topic, MAML supports an externalLink element that accepts text in a linkText element and a URI in a linkUri element.  It also accepts alternate text in a linkAlternateText element, but that's optional.

    Instead of linking to external URIs, you can also link to any of the other topics being documented.  To do that you would use a very simplified version of the XLink specification on a link element, as in the following example:

    <link xlink:href="37852294-410f-4bb2-9008-c5fa9dfb4347">Part II</link>

    Right, topics are identified by GUIDs.  Currently, Sandcastle also requires that all conceptual topic files are named with a GUID and an .xml extension.  A bit annoying at first, but if you use DocProject it provides a Topic Explorer tool window that makes it easy to find the topic that you're looking for without having to open all of them :)

    Notice that in my example the value in the href does not have an .xml file extension specified.  That's because link doesn't reference files, it references topics.  This is important to realize because it's not the same as the way linking works in HTML - this is actually dynamic.  If Sandcastle cannot find a topic that is associated with the specified GUID, then it doesn't generate a hyperlink at all.

    This is a bit different from what we're used to in HTML, which allows us to link to anything under the sun using only one tag: a.  So why such weirdness in MAML?  I think the answer to that question is actually quite simple, although for some reason it's easy to miss when first starting out with MAML.  The MAML schema defines elements that apply structure and semantics to text, instead of format and style, like HTML.  For this reason, you wouldn't see a tag named simply, a in MAML because it's not descriptive at all.  Link, on the other hand, is very descriptive.  And since an HTML anchor is meant to provide the source point of a diametric link, its use is actually more limited than XLink.  The XLink specification actually provides a way to establish relationships between one or more resources (at least that's my interpretation of it), which would offer much more flexibility.  So MAML provides a mechanism to link to other topics, not just external URIs, and the XLink implementation provides an explicit way to describe links as being special - they must be processed by Sandcastle.  Currently, Sandcastle doesn't actually seem to use any of XLink's features though aside from what has been deemed as "simple" usage, but maybe that'll change in the future.

    But that's not all.  If you want to create a link to an API in your reference documentation, you would use the codeEntityReference element instead.  Yikes!  So now we've got yet another way to link.  But again, keep in mind that MAML is much more expressive than HTML, and that's why we've got different tags for linking to different things.  The benefit being that our intentions are clear when we write our topics so that different styles of linking can be handled differently.

    The following XML snippet illustrates all three approaches to linking in MAML topics.  Each example is a child of the relatedTopics element, which, in the Sandcastle world, will eventually become your topic's See Also section.

      <link xref="home">My Home Page</link>
      <link xref="Contact Us"/>
      <link vref="/related.aspx">Related web page</link>
      <link xlink:href="14790228-f45b-42d5-9b3e-f6b4ab932b9e">Part II</link>

    Notice that there are also two more link types in the example above that I didn't mention previously: link elements with xref and vref attributes.  This type of linking is used instead of externalLink so that only an ID must be specified instead of an entire URL.  The ID is part of an ID-to-URL mapping that is configured elsewhere.  This feature is not actually part of Sandcastle though; it's provided by a custom build component that I've written which, for the next release of DocProject, has been modified to support conceptual builds as well.  The component is called ResolveExternalLinksComponent and it's available as a separate download or as part of DocProject.  Without this build component xref and vref do nothing.


    HTML is out.  MAML is in.

    Well, it's not actually as substantial of a change as I'm implying - HTML is still being used extensively as the final output for compiling help; however, we no longer have to author help topics in HTML, which is a huge benefit.

    So all this stuff might seem really wonderful in print, but I feel that I must warn you: It actually took me a few weeks before I finally started to get rid of that itch to lace my topics with bold and italic phrases where it didn't actually add any value.  When you first start writing MAML it can feel very restrictive, and it is compared to HTML in terms of how quickly you can apply new styles, since to do that you have to leave the actual topic and modify files in the Sandcastle presentation; but it's actually much more expressive in terms of describing information and that's what we should be concentrating on when we write help topics - the information.

    What I've learned from writing topics in MAML is that using elements such as ui, userInput, math, date, and many others, as well as externalLink, codeEntityReference and link for linking, ultimately accomplish the same thing as HTML but in a much better way - no more CSS class names to remember or abstract HTML tags like b and i (or strong and em too).  Instead, I can specify exactly what a phrase represents and continue writing.  The format and style is already defined for me by the presentation style that I choose, even if I haven't chosen it yet!  However, if I've already chosen one that mostly fits my needs but I'm not happy with a particular style, I can apply some HTML and CSS to the different MAML elements without having to update anything in the topics themselves.  By reusing the same common tags throughout my documentation, it looks much more professional, it's easier to manage and it's even portable since it's all XML, so if in the future I want to generate Open XML documents instead of HTML, I won't even have to change anything in my topics.

    Note that if you want to convert all of your existing HTML topics to MAML in a batch process, I've got a tool called DocToMaml.  It's currently in beta, but it does work.  Any feedback on it will be appreciated :)

    For the next version of DocProject 2008 (Beta 3) I'm working on a MAML WYSIWYG editor that is integrated into Visual Studio, so keep your eyes open for that.

    If you have any feedback about how MAML and Sandcastle's conceptual build process can be improved please let the Sandcastle team know by submitting a request to the Sandcastle Issue Tracker on CodePlex.

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