示例#1
0
        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="helpFileFormats">The help file formats to which the files apply</param>
        /// <param name="basePath">An alternate base path or null to use the presentation style base path</param>
        /// <param name="sourcePath">The source path</param>
        /// <param name="destination">The destination path</param>
        /// <param name="templateFileExtensions">An enumerable list of file extensions to treat as template files</param>
        public ContentFiles(HelpFileFormats helpFileFormats, string basePath, string sourcePath,
                            string destination, IEnumerable <string> templateFileExtensions)
        {
            if (Path.IsPathRooted(sourcePath))
            {
                throw new InvalidOperationException("Content source path must be relative");
            }

            if (!String.IsNullOrEmpty(destination))
            {
                if (Path.IsPathRooted(destination))
                {
                    throw new InvalidOperationException("Content destination path must be relative");
                }

                if (destination.IndexOfAny(new[] { '*', '?' }) != -1)
                {
                    throw new InvalidOperationException("Content destination must be a path only");
                }
            }

            this.HelpFileFormats        = helpFileFormats;
            this.BasePath               = basePath;
            this.SourcePathWildcard     = sourcePath;
            this.DestinationFolder      = destination;
            this.TemplateFileExtensions = templateFileExtensions.ToList();
        }
示例#2
0
 /// <summary>
 /// This is used to convert the collection to a string and append it
 /// to the specified string builder.
 /// </summary>
 /// <param name="format">The help file format to use</param>
 /// <param name="sb">The string builder to which the information is
 /// appended.</param>
 internal void ConvertToString(HelpFileFormats format, StringBuilder sb)
 {
     foreach (TocEntry te in this)
     {
         te.ConvertToString(format, sb);
     }
 }
示例#3
0
        /// <summary>
        /// Convert the table of contents entry and its children to a string
        /// in the specified help file format.
        /// </summary>
        /// <param name="format">The help file format to use</param>
        /// <returns>The entries in the specified help format</returns>
        public string ToString(HelpFileFormats format)
        {
            StringBuilder sb = new StringBuilder(1024);

            this.ConvertToString(format, sb);
            return(sb.ToString());
        }
示例#4
0
        static void editHtmlFolder(BuildProcess builder, string path, HelpFileFormats format)
        {
            string[] htmlFilesPaths = Directory.GetFiles(path, "*.htm", SearchOption.TopDirectoryOnly);
            // Then we classify the Files into different types
            List <Tuple <string, FileType> > filesWithType = new List <Tuple <string, FileType> >(htmlFilesPaths.Length);

            foreach (string htmlFilePath in htmlFilesPaths)
            {
                string htmlFileName = htmlFilePath.Remove(0, path.Length + 1); // +1 comes from backslash character in the path ending.
                htmlFileName = htmlFileName.Remove(htmlFileName.Length - 4);   // remove the .htm at the end of the string.
                FileType htmlType = findFileType(htmlFileName);
                //if (htmlType != FileType.other)
                //{
                //    Console.WriteLine(htmlFileName + "  |  " + htmlType);
                //}
                Tuple <string, FileType> fileWithType = new Tuple <string, FileType>(htmlFilePath, htmlType);
                filesWithType.Add(fileWithType);
            }
            //edit each html page
            int counter = 0;

            foreach (Tuple <string, FileType> fileWithType in filesWithType)
            {
                string   fileName = fileWithType.Item1;
                FileType filetype = fileWithType.Item2;
                // edit the page itself
                editPage(fileName, filetype);
                // edit all the typeNames on the page
                editForTypeNames(fileWithType.Item1);
                if (format == HelpFileFormats.MSHelpViewer)
                {
                    editFileForMSHV(fileName, filetype);
                }
                else if (format == HelpFileFormats.Website)
                {
                    editWebsiteToc(fileName);
                }
                counter++;
                if (counter % 500 == 0)
                {
                    builder.ReportProgress("   Adjusted {0} pages", counter);
                }
            }
            builder.ReportProgress("   Finished adjusting {0} pages", counter);
            return;
        }
示例#5
0
        static void editHtmlFolder(BuildProcess builder, string path, HelpFileFormats format)
        {
            string[] htmlFilesPaths = Directory.GetFiles(path, "*.htm", SearchOption.TopDirectoryOnly);
            // Then we classify the Files into different types
            var filesWithType = new List <Tuple <string, FileType, string> >(htmlFilesPaths.Length);

            foreach (string htmlFilePath in htmlFilesPaths)
            {
                string htmlFileName = htmlFilePath.Remove(0, path.Length + 1); // +1 comes from backslash character in the path ending.
                htmlFileName = htmlFileName.Remove(htmlFileName.Length - 4);   // remove the .htm at the end of the string.
                FileType htmlType = findFileType(htmlFileName);
                string   strType  = "";
                if (htmlType == FileType.singleField)
                {
                    var contents = File.ReadAllText(htmlFilePath);
                    strType = determineFieldType(contents);
                }
                var fileWithType = new Tuple <string, FileType, string>(htmlFilePath, htmlType, strType);

                filesWithType.Add(fileWithType);
            }
            //edit each html page
            int counter = 0;

            foreach (var fileWithType in filesWithType)
            {
                string   fileName = fileWithType.Item1;
                FileType filetype = fileWithType.Item2;
                // edit the page itself
                editPage(fileName, filetype);
                // edit all the typeNames on the page
                editForTypeNames(fileWithType.Item1);
                if (format == HelpFileFormats.MSHelpViewer)
                {
                    editFileForMSHV(fileName, filetype, fileWithType.Item3);
                }
                counter++;
                if (counter % 500 == 0)
                {
                    builder.ReportProgress("   Adjusted {0} pages", counter);
                }
            }
            builder.ReportProgress("   Finished adjusting {0} pages", counter);
            return;
        }
示例#6
0
        /// <summary>
        /// Update the info provider text and available help file formats when the presentation style changes
        /// </summary>
        /// <param name="sender">The sender of the event</param>
        /// <param name="e">The event arguments</param>
        private void cboPresentationStyle_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            IPresentationStyleMetadata pss;

            if (presentationStyles == null)
            {
                return;
            }

            pss = (IPresentationStyleMetadata)cboPresentationStyle.SelectedItem;

            imgPresentationStyleInfo.ToolTip = String.Format(CultureInfo.InvariantCulture,
                                                             "{0}\r\n\r\nVersion {1}\r\n{2}", pss.Description, pss.Version, pss.Copyright);

            // Filter the help file formats based on what is supported by the presentation style
            HelpFileFormats supportedFormats = HelpFileFormats.HtmlHelp1;

            var style = componentCache.ComponentContainer.GetExports <PresentationStyleSettings,
                                                                      IPresentationStyleMetadata>().FirstOrDefault(s => s.Metadata.Id.Equals(pss.Id, StringComparison.OrdinalIgnoreCase));

            if (style != null)
            {
                supportedFormats = style.Value.SupportedFormats;
            }

            allHelpFileFormats.ForEach(f => f.IsActive = false);

            var styleFormats = allHelpFileFormats.Where(f => (supportedFormats & f.Format) != 0).ToList();

            if (styleFormats.Count != 0 && !styleFormats.Any(f => f.IsSelected))
            {
                styleFormats[0].IsSelected = true;
            }

            styleFormats.ForEach(f => f.IsActive = true);

            lbHelpFileFormat.ItemsSource = styleFormats;

            if (!isBinding)
            {
                this.PropertyChanged?.Invoke(this, e);
            }
        }
        /// <summary>
        /// This is used to copy the presentation style help file content to the given destination folder
        /// </summary>
        /// <param name="format">The help file format for which to copy files</param>
        /// <param name="destinationBasePath">The destination base path to which the files are copied</param>
        /// <param name="progressReporter">An optional action delegate used to report progress</param>
        /// <param name="transformTemplate">A action delegate used to transform a template file (file, source
        /// folder, destination folder)</param>
        public void CopyHelpContent(HelpFileFormats format, string destinationBasePath,
                                    Action <string, object[]> progressReporter, Action <string, string, string> transformTemplate)
        {
            string sourcePath, destPath;

            if (transformTemplate == null)
            {
                throw new ArgumentNullException(nameof(transformTemplate));
            }

            foreach (var content in contentFiles)
            {
                if ((content.HelpFileFormats & format) != 0)
                {
                    if (content.BasePath == null)
                    {
                        sourcePath = this.ResolvePath(content.SourcePathWildcard);
                    }
                    else
                    {
                        sourcePath = this.ResolvePath(Path.Combine(content.BasePath, content.SourcePathWildcard));
                    }

                    if (content.DestinationFolder == null)
                    {
                        destPath = Path.Combine(destinationBasePath,
                                                Path.GetFileName(Path.GetDirectoryName(content.SourcePathWildcard)));
                    }
                    else
                    if (content.DestinationFolder.Length == 0)
                    {
                        destPath = destinationBasePath;
                    }
                    else
                    {
                        destPath = Path.Combine(destinationBasePath, content.DestinationFolder);
                    }

                    RecursiveCopy(sourcePath, destPath, progressReporter, content.TemplateFileExtensions,
                                  transformTemplate);
                }
            }
        }
        /// <summary>
        /// This is used to copy the presentation style help file content to the given destination folder
        /// </summary>
        /// <param name="format">The help file format for which to copy files</param>
        /// <param name="destinationBasePath">The destination base path to which the files are copied</param>
        /// <param name="progressReporter">An optional action delegate used to report progress</param>
        /// <param name="transformTemplate">A action delegate used to transform a template file (file, source
        /// folder, destination folder)</param>
        public void CopyHelpContent(HelpFileFormats format, string destinationBasePath,
          Action<string, object[]> progressReporter, Action<string, string, string> transformTemplate)
        {
            string sourcePath, destPath;

            foreach(var content in contentFiles)
            {
                if((content.HelpFileFormats & format) != 0)
                {
                    if(content.BasePath == null)
                        sourcePath = this.ResolvePath(content.SourcePathWildcard);
                    else
                        sourcePath = this.ResolvePath(Path.Combine(content.BasePath, content.SourcePathWildcard));

                    if(content.DestinationFolder == null)
                        destPath = Path.Combine(destinationBasePath,
                            Path.GetFileName(Path.GetDirectoryName(content.SourcePathWildcard)));
                    else
                        if(content.DestinationFolder.Length == 0)
                            destPath = destinationBasePath;
                        else
                            destPath = Path.Combine(destinationBasePath, content.DestinationFolder);

                    RecursiveCopy(sourcePath, destPath, progressReporter, content.TemplateFileExtensions,
                        transformTemplate);
                }
            }
        }
示例#9
0
        //=====================================================================

        /// <summary>
        /// Call this method to perform the build on the project.
        /// </summary>
        public void Build()
        {
            Project msBuildProject = null;
            ProjectItem projectItem;
            string resolvedPath, helpFile, languageFile, scriptFile, hintPath, message = null;
            SandcastleProject originalProject = null;

            System.Diagnostics.Debug.WriteLine("Build process starting\r\n");

            try
            {
                taskRunner = new TaskRunner(this);

                // If the project isn't using final values suitable for the build, create a copy of the
                // project that is using final values.
                if(!project.UsingFinalValues)
                {
                    originalProject = project;
                    project = new SandcastleProject(originalProject.MSBuildProject);
                }

                Assembly asm = Assembly.GetExecutingAssembly();

                FileVersionInfo fvi = FileVersionInfo.GetVersionInfo(asm.Location);
                this.ReportProgress(BuildStep.Initializing, "[{0}, version {1}]", fvi.ProductName, fvi.ProductVersion);

                buildStart = stepStart = DateTime.Now;

                // The version of MSBuild to use is based on the tools version set in the project
                msBuildExePath = Path.Combine(ProjectCollection.GlobalProjectCollection.Toolsets.First(
                    t => t.ToolsVersion == project.MSBuildProject.ToolsVersion).ToolsPath, "MSBuild.exe");

                // Get the location of the template files
                templateFolder = ComponentUtilities.ToolsFolder + @"Templates\";

                // Make sure we start out in the project's output folder in case the output folder is relative
                // to it.
                projectFolder = Path.GetDirectoryName(originalProjectName);

                if(projectFolder.Length == 0)
                    projectFolder = Directory.GetCurrentDirectory();

                projectFolder += @"\";

                Directory.SetCurrentDirectory(projectFolder);

                this.ReportProgress("Creating output and working folders...");

                outputFolder = project.OutputPath;

                if(String.IsNullOrEmpty(outputFolder))
                    outputFolder = Directory.GetCurrentDirectory();
                else
                    outputFolder = Path.GetFullPath(outputFolder);

                if(!Directory.Exists(outputFolder))
                    Directory.CreateDirectory(outputFolder);

                if(outputFolder[outputFolder.Length - 1] != '\\')
                    outputFolder += @"\";

                // Create the log file.  The log may be in a folder other than the output so make sure it exists
                // too.
                if(!Directory.Exists(Path.GetDirectoryName(this.LogFilename)))
                    Directory.CreateDirectory(Path.GetDirectoryName(this.LogFilename));

                swLog = new StreamWriter(this.LogFilename);

                swLog.WriteLine("<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<shfbBuild product=\"{0}\" " +
                    "version=\"{1}\" projectFile=\"{2}\" started=\"{3}\">\r\n<buildStep step=\"{4}\">",
                    fvi.ProductName, fvi.ProductVersion, originalProjectName, DateTime.Now,
                    BuildStep.Initializing);

                if(project.WorkingPath.Path.Length == 0)
                    workingFolder = outputFolder + @"Working\";
                else
                    workingFolder = project.WorkingPath;

                if((project.HelpFileFormat & HelpFileFormats.Website) != 0)
                    BuildProcess.VerifySafePath("OutputPath", outputFolder, projectFolder);

                // The output folder and the working folder cannot be the same
                if(workingFolder == outputFolder)
                    throw new BuilderException("BE0030", "The OutputPath and WorkingPath properties cannot be " +
                        "set to the same path");

                // Make sure we can find the tools
                this.FindTools();

                // Check for the SHFBROOT environment variable.  It may not be present yet if a reboot hasn't
                // occurred after installation.  In such cases, set it to the proper folder for this process so
                // that projects can be loaded and built.
                if(Environment.GetEnvironmentVariable("SHFBROOT") == null)
                {
                    // We won't issue a warning since it may not be defined in some build environments such as
                    // on a build server.  In such cases, it is passed in as a command line option to MSBuild.
                    // Storing it in the environment here lets the SHFB build projects work as expected.
                    this.ReportProgress("The SHFBROOT system environment variable was not found.  This " +
                        "variable is usually created during installation and may require a reboot.  It has " +
                        "been defined temporarily for this process as: SHFBROOT={0}",
                        ComponentUtilities.ToolsFolder);

                    Environment.SetEnvironmentVariable("SHFBROOT", ComponentUtilities.ToolsFolder);
                }

                this.ReportProgress("Locating components in the following folder(s):");

                if(!String.IsNullOrEmpty(project.ComponentPath))
                    this.ReportProgress("    {0}", project.ComponentPath);

                this.ReportProgress("    {0}", Path.GetDirectoryName(project.Filename));

                this.ReportProgress("    {0}", ComponentUtilities.ComponentsFolder);
                this.ReportProgress("    {0}", ComponentUtilities.ToolsFolder);

                // Get the framework reflection data settings to use for the build
                reflectionDataDictionary = new ReflectionDataSetDictionary(new[] { project.ComponentPath,
                    Path.GetDirectoryName(project.Filename) });
                frameworkReflectionData = reflectionDataDictionary.CoreFrameworkByTitle(project.FrameworkVersion, true);

                if(frameworkReflectionData == null)
                    throw new BuilderException("BE0071", String.Format(CultureInfo.CurrentCulture,
                        "Unable to locate information for the project framework version '{0}' or a suitable " +
                        "redirected version on this system.  See error number help topic for details.",
                        project.FrameworkVersion));

                this.ReportProgress("Framework reflection data location: {0}", this.FrameworkReflectionDataFolder);

                if(!Directory.EnumerateFiles(this.FrameworkReflectionDataFolder, "*.xml").Any())
                    throw new BuilderException("BE0032", "Reflection data files for the selected framework " +
                        "do not exist yet (" + frameworkReflectionData.Title + ").  See help file for " +
                        "details about this error number.");

                // Warn if a different framework is being used for the build
                if(frameworkReflectionData.Title != project.FrameworkVersion)
                    this.ReportWarning("BE0072", "Project framework version '{0}' not found.  It has been " +
                        "redirected and will use '{1}' instead.", project.FrameworkVersion,
                        frameworkReflectionData.Title);

                // Get the composition container used to find build components in the rest of the build process
                componentContainer = ComponentUtilities.CreateComponentContainer(new[] { project.ComponentPath,
                    Path.GetDirectoryName(project.Filename) }, this.CancellationToken);

                syntaxGenerators = componentContainer.GetExports<ISyntaxGeneratorFactory,
                    ISyntaxGeneratorMetadata>().Select(sf => sf.Metadata).ToList();
                buildComponents = componentContainer.GetExports<BuildComponentFactory,
                    IBuildComponentMetadata>().GroupBy(c => c.Metadata.Id).Select(g => g.First()).ToDictionary(
                        key => key.Metadata.Id, value => value.Value);

                // Figure out which presentation style to use
                var style = componentContainer.GetExports<PresentationStyleSettings,
                    IPresentationStyleMetadata>().FirstOrDefault(s => s.Metadata.Id.Equals(
                        project.PresentationStyle, StringComparison.OrdinalIgnoreCase));

                if(style == null)
                    throw new BuilderException("BE0001", "The PresentationStyle property value of '" +
                        project.PresentationStyle + "' is not recognized as a valid presentation style definition");

                presentationStyle = style.Value;

                this.ReportProgress("Using presentation style '{0}' located in '{1}'", style.Metadata.Id,
                    Path.Combine(presentationStyle.Location, presentationStyle.BasePath ?? String.Empty));

                var psErrors = presentationStyle.CheckForErrors();

                if(psErrors.Any())
                    throw new BuilderException("BE0004", String.Format(CultureInfo.CurrentCulture,
                        "The selected presentation style ({0}) is not valid.  Reason(s):\r\n{1}",
                        style.Metadata.Id, String.Join("\r\n", psErrors)));

                // If the presentation style does not support one or more of the selected help file formats,
                // stop now.
                if((project.HelpFileFormat & ~presentationStyle.SupportedFormats) != 0)
                    throw new BuilderException("BE0074", String.Format(CultureInfo.CurrentCulture,
                        "The selected presentation style ({0}) does not support one or more of the selected " +
                        "help file formats.  Supported formats: {1}", style.Metadata.Id,
                        presentationStyle.SupportedFormats));

                // Create the substitution tag replacement handler now as we have everything it needs
                substitutionTags = new SubstitutionTagReplacement(this);

                // Load the plug-ins if necessary
                if(project.PlugInConfigurations.Count != 0 || presentationStyle.PlugInDependencies.Count != 0)
                    this.LoadPlugIns();

                this.ExecutePlugIns(ExecutionBehaviors.After);

                try
                {
                    if(Directory.Exists(workingFolder))
                    {
                        // Clear any data from a prior run
                        this.ReportProgress(BuildStep.ClearWorkFolder, "Clearing working folder...");
                        BuildProcess.VerifySafePath("WorkingPath", workingFolder, projectFolder);

                        if(!this.ExecutePlugIns(ExecutionBehaviors.InsteadOf))
                        {
                            this.ExecutePlugIns(ExecutionBehaviors.Before);

                            try
                            {
                                Directory.Delete(workingFolder, true);
                            }
                            catch(IOException ioEx)
                            {
                                this.ReportProgress("    Not all prior output was removed from '{0}': {1}",
                                    workingFolder, ioEx.Message);
                            }
                            catch(UnauthorizedAccessException uaEx)
                            {
                                this.ReportProgress("    Not all prior output was removed from '{0}': {1}",
                                    workingFolder, uaEx.Message);
                            }

                            this.ExecutePlugIns(ExecutionBehaviors.After);
                        }
                    }

                    // For MS Help Viewer, the HTML Help Name cannot contain periods, ampersands, or pound signs
                    if((project.HelpFileFormat & HelpFileFormats.MSHelpViewer) != 0 &&
                      this.ResolvedHtmlHelpName.IndexOfAny(new[] { '.', '#', '&' }) != -1)
                        throw new BuilderException("BE0075", "For MS Help Viewer builds, the HtmlHelpName property " +
                            "cannot contain periods, ampersands, or pound signs as they are not valid in the " +
                            "help file name.");

                    // If the help file is open, it will fail to build so try to get rid of it now before we
                    // get too far into it.
                    helpFile = outputFolder + this.ResolvedHtmlHelpName + ".chm";

                    if((project.HelpFileFormat & HelpFileFormats.HtmlHelp1) != 0 && File.Exists(helpFile))
                        File.Delete(helpFile);

                    helpFile = Path.ChangeExtension(helpFile, ".mshc");

                    if((project.HelpFileFormat & HelpFileFormats.MSHelpViewer) != 0 && File.Exists(helpFile))
                        File.Delete(helpFile);

                    if((project.HelpFileFormat & HelpFileFormats.Website) != 0)
                    {
                        helpFile = outputFolder + "Index.aspx";

                        if(File.Exists(helpFile))
                            File.Delete(helpFile);

                        helpFile = Path.ChangeExtension(helpFile, ".html");

                        if(File.Exists(helpFile))
                            File.Delete(helpFile);
                    }

                    helpFile = outputFolder + this.ResolvedHtmlHelpName + ".docx";

                    if((project.HelpFileFormat & HelpFileFormats.OpenXml) != 0 && File.Exists(helpFile))
                        File.Delete(helpFile);
                }
                catch(IOException ex)
                {
                    throw new BuilderException("BE0025", "Unable to remove prior build output: " + ex.Message);
                }
                catch
                {
                    throw;
                }

                if((project.HelpFileFormat & (HelpFileFormats.Website | HelpFileFormats.Markdown)) != 0)
                {
                    this.ReportProgress("-------------------------------");
                    this.ReportProgress("Clearing any prior web/markdown output...");

                    // Purge all files and folders from the output path except for the working folder and the
                    // build log.  Read-only and/or hidden files and folders are ignored as they are assumed to
                    // be under source control.
                    foreach(string file in Directory.EnumerateFiles(outputFolder))
                        if(!file.EndsWith(Path.GetFileName(this.LogFilename), StringComparison.Ordinal))
                            if((File.GetAttributes(file) & (FileAttributes.ReadOnly | FileAttributes.Hidden)) == 0)
                                File.Delete(file);
                            else
                                this.ReportProgress("    Ignoring read-only/hidden file {0}", file);

                    foreach(string folder in Directory.EnumerateDirectories(outputFolder))
                        try
                        {
                            // Ignore the working folder in case it wasn't removed above
                            if(!folder.Equals(workingFolder.Substring(0, workingFolder.Length - 1), StringComparison.OrdinalIgnoreCase))
                            {
                                // Some source control providers have a mix of read-only/hidden files within a
                                // folder that isn't read-only/hidden (i.e. Subversion).  In such cases, leave
                                // the folder alone.
                                if(Directory.EnumerateFileSystemEntries(folder, "*", SearchOption.AllDirectories).Any(
                                  f => (File.GetAttributes(f) & (FileAttributes.ReadOnly | FileAttributes.Hidden)) != 0))
                                {
                                    this.ReportProgress("    Did not delete folder '{0}' as it contains " +
                                        "read-only or hidden folders/files", folder);
                                }
                                else
                                    if((File.GetAttributes(folder) & (FileAttributes.ReadOnly | FileAttributes.Hidden)) == 0)
                                        Directory.Delete(folder, true);
                                    else
                                        this.ReportProgress("    Ignoring read-only/hidden folder {0}", folder);
                            }
                        }
                        catch(IOException ioEx)
                        {
                            this.ReportProgress("    Ignoring folder '{0}': {1}", folder, ioEx.Message);
                        }
                        catch(UnauthorizedAccessException uaEx)
                        {
                            this.ReportProgress("    Ignoring folder '{0}': {1}", folder, uaEx.Message);
                        }
                }

                Directory.CreateDirectory(workingFolder);

                // Validate the documentation source information, gather assembly and reference info, and copy
                // XML comments files to the working folder.
                this.ValidateDocumentationSources();

                // Transform the shared builder content files
                language = project.Language;
                languageFile = Path.Combine(presentationStyle.ResolvePath(presentationStyle.ToolResourceItemsPath),
                    language.Name + ".xml");

                this.ReportProgress(BuildStep.GenerateSharedContent, "Generating shared content files ({0}, {1})...",
                    language.Name, language.DisplayName);

                if(!File.Exists(languageFile))
                {
                    languageFile = Path.Combine(presentationStyle.ResolvePath(presentationStyle.ToolResourceItemsPath),
                        "en-US.xml");

                    // Warn the user about the default being used
                    this.ReportWarning("BE0002", "Help file builder content for the '{0}, {1}' language could " +
                        "not be found.  Using 'en-US, English (US)' defaults.", language.Name, language.DisplayName);
                }

                // See if the user has translated the Sandcastle resources.  If not found, default to US English.
                languageFolder = Path.Combine(presentationStyle.ResolvePath(presentationStyle.ResourceItemsPath),
                    language.Name);

                if(Directory.Exists(languageFolder))
                    languageFolder = language.Name + @"\";
                else
                {
                    // Warn the user about the default being used.  The language will still be used for the help
                    // file though.
                    if(language.Name != "en-US")
                        this.ReportWarning("BE0003", "Sandcastle shared content for the '{0}, {1}' language " +
                            "could not be found.  Using 'en-US, English (US)' defaults.", language.Name,
                            language.DisplayName);

                    languageFolder = String.Empty;
                }

                if(!this.ExecutePlugIns(ExecutionBehaviors.InsteadOf))
                {
                    this.ExecutePlugIns(ExecutionBehaviors.Before);

                    substitutionTags.TransformTemplate(Path.GetFileName(languageFile), Path.GetDirectoryName(languageFile),
                        workingFolder);
                    File.Move(workingFolder + Path.GetFileName(languageFile), workingFolder + "SHFBContent.xml");

                    // Copy the stop word list
                    languageFile = Path.Combine(ComponentUtilities.ToolsFolder, @"PresentationStyles\Shared\" +
                        @"StopWordList\" + Path.GetFileNameWithoutExtension(languageFile) +".txt");
                    File.Copy(languageFile, workingFolder + "StopWordList.txt");
                    File.SetAttributes(workingFolder + "StopWordList.txt", FileAttributes.Normal);

                    this.ExecutePlugIns(ExecutionBehaviors.After);
                }

                // Generate the API filter used by MRefBuilder
                this.GenerateApiFilter();

                // Generate the reflection information
                this.ReportProgress(BuildStep.GenerateReflectionInfo, "Generating reflection information...");

                reflectionFile = workingFolder + "reflection.org";

                if(!this.ExecutePlugIns(ExecutionBehaviors.InsteadOf))
                {
                    substitutionTags.TransformTemplate("MRefBuilder.config", templateFolder, workingFolder);
                    scriptFile = substitutionTags.TransformTemplate("GenerateRefInfo.proj", templateFolder, workingFolder);

                    try
                    {
                        msBuildProject = new Project(scriptFile);

                        // Add the references
                        foreach(var r in referenceDictionary.Values)
                        {
                            projectItem = msBuildProject.AddItem(r.Item1, r.Item2, r.Item3)[0];

                            // Make sure hint paths are correct by adding the project folder to any relative
                            // paths.  Skip any containing MSBuild variable references.
                            if(projectItem.HasMetadata(BuildItemMetadata.HintPath))
                            {
                                hintPath = projectItem.GetMetadataValue(BuildItemMetadata.HintPath);

                                if(!Path.IsPathRooted(hintPath) && hintPath.IndexOf("$(",
                                  StringComparison.Ordinal) == -1)
                                {
                                    hintPath = FilePath.GetFullPath(Path.Combine(projectFolder, hintPath));

                                    // If the full path length would exceed the system maximums, make it relative
                                    // to keep it under the maximum lengths.
                                    if(hintPath.Length > 259 || Path.GetDirectoryName(hintPath).Length > 247)
                                        hintPath = FolderPath.AbsoluteToRelativePath(workingFolder, hintPath);

                                    projectItem.SetMetadataValue(BuildItemMetadata.HintPath, hintPath);
                                }
                            }
                        }

                        // Add the assemblies to document
                        foreach(string assemblyName in assembliesList)
                            msBuildProject.AddItem("Assembly", assemblyName);

                        msBuildProject.Save(scriptFile);
                    }
                    finally
                    {
                        // If we loaded it, we must unload it.  If not, it is cached and may cause problems later.
                        if(msBuildProject != null)
                        {
                            ProjectCollection.GlobalProjectCollection.UnloadProject(msBuildProject);
                            ProjectCollection.GlobalProjectCollection.UnloadProject(msBuildProject.Xml);
                        }
                    }

                    this.ExecutePlugIns(ExecutionBehaviors.Before);

                    // Silverlight build targets are only available for 32-bit builds regardless of the framework
                    // version and require the 32-bit version of MSBuild in order to load the target file correctly.
                    if(project.FrameworkVersion.StartsWith("Silverlight", StringComparison.OrdinalIgnoreCase))
                        taskRunner.Run32BitProject("GenerateRefInfo.proj", false);
                    else
                        taskRunner.RunProject("GenerateRefInfo.proj", false);

                    this.ExecutePlugIns(ExecutionBehaviors.After);
                }

                // If this was a partial build used to obtain API information, stop now
                if(this.PartialBuildType == PartialBuildType.GenerateReflectionInfo)
                {
                    commentsFiles.Save();
                    goto AllDone;       // Yeah, I know it's evil but it's quick
                }

                // Transform the reflection output based on the document model and create the topic manifest
                this.ReportProgress(BuildStep.TransformReflectionInfo, "Transforming reflection output...");

                if(!this.ExecutePlugIns(ExecutionBehaviors.InsteadOf))
                {
                    scriptFile = substitutionTags.TransformTemplate("TransformManifest.proj", templateFolder, workingFolder);

                    this.ExecutePlugIns(ExecutionBehaviors.Before);

                    taskRunner.RunProject("TransformManifest.proj", false);

                    // Change the reflection file extension before running the ExecutionBehaviors.After plug-ins
                    // so that the plug-ins (if any) get the correct filename.
                    reflectionFile = Path.ChangeExtension(reflectionFile, ".xml");

                    this.ExecutePlugIns(ExecutionBehaviors.After);
                }
                else
                    reflectionFile = Path.ChangeExtension(reflectionFile, ".xml");

                // If this was a partial build used to obtain information for namespace and namespace group
                // comments, stop now.
                if(this.PartialBuildType == PartialBuildType.TransformReflectionInfo)
                {
                    commentsFiles.Save();
                    goto AllDone;       // Yeah, I know it's evil but it's quick
                }

                // Load the transformed reflection information file
                reflectionFile = workingFolder + "reflection.xml";

                // If there is nothing to document, stop the build
                if(!ComponentUtilities.XmlStreamAxis(reflectionFile, "api").Any())
                    throw new BuilderException("BE0033", "No APIs found to document.  See error topic in " +
                        "help file for details.");

                // Generate namespace summary information
                this.GenerateNamespaceSummaries();

                // Expand <inheritdoc /> tags?
                if(commentsFiles.ContainsInheritedDocumentation)
                {
                    commentsFiles.Save();

                    // Transform the reflection output.
                    this.ReportProgress(BuildStep.GenerateInheritedDocumentation,
                        "Generating inherited documentation...");

                    if(!this.ExecutePlugIns(ExecutionBehaviors.InsteadOf))
                    {
                        substitutionTags.TransformTemplate("GenerateInheritedDocs.config", templateFolder, workingFolder);
                        scriptFile = substitutionTags.TransformTemplate("GenerateInheritedDocs.proj", templateFolder,
                            workingFolder);

                        this.ExecutePlugIns(ExecutionBehaviors.Before);

                        taskRunner.RunProject("GenerateInheritedDocs.proj", true);
                        
                        this.ExecutePlugIns(ExecutionBehaviors.After);
                    }

                    // This should always be last so that it overrides comments in the project XML comments files
                    commentsFiles.Add(new XmlCommentsFile(workingFolder + "_InheritedDocs_.xml"));
                }

                commentsFiles.Save();

                this.EnsureOutputFoldersExist(null);

                // Copy conceptual content files if there are topics or tokens.  Tokens can be replaced in
                // XML comments files so we check for them too.
                if(this.ConceptualContent.ContentLayoutFiles.Count != 0 || this.ConceptualContent.TokenFiles.Count != 0)
                {
                    this.ReportProgress(BuildStep.CopyConceptualContent, "Copying conceptual content...");

                    if(!this.ExecutePlugIns(ExecutionBehaviors.InsteadOf))
                    {
                        this.ExecutePlugIns(ExecutionBehaviors.Before);
                        this.ConceptualContent.CopyContentFiles(this);
                        this.ExecutePlugIns(ExecutionBehaviors.After);
                    }

                    this.ReportProgress(BuildStep.CreateConceptualTopicConfigs,
                        "Creating conceptual topic configuration files...");

                    if(!this.ExecutePlugIns(ExecutionBehaviors.InsteadOf))
                    {
                        this.ExecutePlugIns(ExecutionBehaviors.Before);
                        this.ConceptualContent.CreateConfigurationFiles(this);
                        this.ExecutePlugIns(ExecutionBehaviors.After);
                    }
                }
                else    // Create an empty xmlComp folder required by the build configuration
                    Directory.CreateDirectory(Path.Combine(workingFolder, "xmlComp"));

                // Copy the additional content
                this.CopyAdditionalContent();

                // Merge the conceptual and additional content TOC info
                this.MergeConceptualAndAdditionalContentTocInfo();

                // Generate the intermediate table of contents file.  This
                // must occur prior to running BuildAssembler as the MS Help
                // Viewer build component is dependent on the toc.xml file.
                this.ReportProgress(BuildStep.GenerateIntermediateTableOfContents,
                    "Generating intermediate table of contents file...");

                if(!this.ExecutePlugIns(ExecutionBehaviors.InsteadOf))
                {
                    scriptFile = substitutionTags.TransformTemplate("GenerateIntermediateTOC.proj", templateFolder,
                        workingFolder);

                    this.ExecutePlugIns(ExecutionBehaviors.Before);

                    taskRunner.RunProject("GenerateIntermediateTOC.proj", false);

                    // Determine the API content placement
                    this.DetermineApiContentPlacement();

                    // If there is conceptual content, generate the conceptual intermediate TOC
                    if(toc != null)
                    {
                        this.ReportProgress("Generating conceptual content intermediate TOC file...");

                        toc.SaveToIntermediateTocFile((project.HelpFileFormat & HelpFileFormats.MSHelpViewer) != 0 ?
                            this.RootContentContainerId : null, project.TocOrder, workingFolder + "_ConceptualTOC_.xml");
                    }

                    this.ExecutePlugIns(ExecutionBehaviors.After);
                }

                // Create the Sandcastle configuration file
                this.ReportProgress(BuildStep.CreateBuildAssemblerConfigs, "Creating Sandcastle configuration files...");

                // Add referenced namespaces to the hash set.  These are used to ensure just the needed set of
                // reflection target files are loaded by BuildAssembler and nothing more to save some time and
                // memory.
                var rn = this.ReferencedNamespaces;

                // These are all of the valid namespaces we are interested in.  This prevents the methods below
                // from returning nested types as potential namespaces since they can't tell the difference.
                HashSet<string> validNamespaces = new HashSet<string>(Directory.EnumerateFiles(
                    this.FrameworkReflectionDataFolder, "*.xml", SearchOption.AllDirectories).Select(
                        f => Path.GetFileNameWithoutExtension(f)));

                // Get namespaces referenced in the XML comments of the documentation sources
                foreach(var n in commentsFiles.GetReferencedNamespaces(validNamespaces))
                    rn.Add(n);

                // Get namespaces referenced in the reflection data (plug-ins are responsible for adding
                // additional namespaces if they add other reflection data files).
                foreach(string n in GetReferencedNamespaces(reflectionFile, validNamespaces))
                    rn.Add(n);

                // Get namespaces from the Framework comments files of the referenced namespaces.  This adds
                // references for stuff like designer and support classes not directly referenced anywhere else.
                foreach(string n in frameworkReflectionData.GetReferencedNamespaces(language, rn, validNamespaces).ToList())
                    rn.Add(n);

                // If F# syntax is being generated, add some of the F# namespaces as the syntax sections generate
                // references to types that may not be there in non-F# projects.
                if(ComponentUtilities.SyntaxFiltersFrom(syntaxGenerators, project.SyntaxFilters).Any(
                  f => f.Id == "F#"))
                {
                    rn.Add("Microsoft.FSharp.Core");
                    rn.Add("Microsoft.FSharp.Control");
                }

                // If there are no referenced namespaces, add System as a default to prevent the build components
                // from loading the entire set.
                if(rn.Count == 0)
                    rn.Add("System");

                if(!this.ExecutePlugIns(ExecutionBehaviors.InsteadOf))
                {
                    this.ExecutePlugIns(ExecutionBehaviors.Before);

                    this.ReportProgress("    sandcastle.config");

                    // The configuration varies based on the style.  We'll use a common name (sandcastle.config).
                    resolvedPath = presentationStyle.ResolvePath(presentationStyle.ReferenceBuildConfiguration);
                    substitutionTags.TransformTemplate(Path.GetFileName(resolvedPath), Path.GetDirectoryName(resolvedPath),
                        workingFolder);

                    if(!Path.GetFileName(resolvedPath).Equals("sandcastle.config", StringComparison.OrdinalIgnoreCase))
                        File.Move(workingFolder + Path.GetFileName(resolvedPath), workingFolder + "sandcastle.config");

                    // The conceptual content configuration file is only created if needed.
                    if(this.ConceptualContent.ContentLayoutFiles.Count != 0)
                    {
                        this.ReportProgress("    conceptual.config");

                        resolvedPath = presentationStyle.ResolvePath(presentationStyle.ConceptualBuildConfiguration);

                        substitutionTags.TransformTemplate(Path.GetFileName(resolvedPath), Path.GetDirectoryName(resolvedPath),
                            workingFolder);

                        if(!Path.GetFileName(resolvedPath).Equals("conceptual.config", StringComparison.OrdinalIgnoreCase))
                            File.Move(workingFolder + Path.GetFileName(resolvedPath), workingFolder + "conceptual.config");
                    }

                    this.ExecutePlugIns(ExecutionBehaviors.After);
                }

                // Merge the build component custom configurations
                this.MergeComponentConfigurations();

                commentsFiles = null;

                // Build the conceptual help topics
                if(this.ConceptualContent.ContentLayoutFiles.Count != 0)
                {
                    this.ReportProgress(BuildStep.BuildConceptualTopics, "Building conceptual help topics...");

                    if(!this.ExecutePlugIns(ExecutionBehaviors.InsteadOf))
                    {
                        scriptFile = substitutionTags.TransformTemplate("BuildConceptualTopics.proj", templateFolder,
                            workingFolder);

                        this.ExecutePlugIns(ExecutionBehaviors.Before);

                        taskRunner.RunProject("BuildConceptualTopics.proj", false);
                        
                        this.ExecutePlugIns(ExecutionBehaviors.After);
                    }
                }

                // Build the reference help topics
                this.ReportProgress(BuildStep.BuildReferenceTopics, "Building reference help topics...");

                if(!this.ExecutePlugIns(ExecutionBehaviors.InsteadOf))
                {
                    scriptFile = substitutionTags.TransformTemplate("BuildReferenceTopics.proj", templateFolder,
                        workingFolder);

                    this.ExecutePlugIns(ExecutionBehaviors.Before);
                                        
                    taskRunner.RunProject("BuildReferenceTopics.proj", false);
                    
                    this.ExecutePlugIns(ExecutionBehaviors.After);
                }

                // Combine the conceptual and API intermediate TOC files into one
                this.CombineIntermediateTocFiles();

                // The last part differs based on the help file format
                if((project.HelpFileFormat & (HelpFileFormats.HtmlHelp1 | HelpFileFormats.Website)) != 0)
                {
                    this.ReportProgress(BuildStep.ExtractingHtmlInfo,
                        "Extracting HTML info for HTML Help 1 and/or website...");

                    if(!this.ExecutePlugIns(ExecutionBehaviors.InsteadOf))
                    {
                        scriptFile = substitutionTags.TransformTemplate("ExtractHtmlInfo.proj", templateFolder,
                            workingFolder);

                        this.ExecutePlugIns(ExecutionBehaviors.Before);

                        taskRunner.RunProject("ExtractHtmlInfo.proj", true);

                        this.ExecutePlugIns(ExecutionBehaviors.After);
                    }
                }

                // Copy the standard help file content.  This is done just before compiling the help so that
                // template files from the presentation style can take advantage of tag substitution.  By this
                // point, we should have everything we could possibly need.
                this.CopyStandardHelpContent();

                if((project.HelpFileFormat & HelpFileFormats.HtmlHelp1) != 0)
                {
                    // Generate the table of contents and set the default topic
                    this.ReportProgress(BuildStep.GenerateHelpFormatTableOfContents,
                        "Generating HTML Help 1 table of contents file...");

                    currentFormat = HelpFileFormats.HtmlHelp1;

                    if(!this.ExecutePlugIns(ExecutionBehaviors.InsteadOf))
                    {
                        this.ExecutePlugIns(ExecutionBehaviors.Before);

                        // It got created in the ExtractingHtmlInfo step above
                        // so there is actually nothing to do here.

                        this.ExecutePlugIns(ExecutionBehaviors.After);
                    }

                    // Generate the help file index
                    this.ReportProgress(BuildStep.GenerateHelpFileIndex, "Generating HTML Help 1 index file...");

                    if(!this.ExecutePlugIns(ExecutionBehaviors.InsteadOf))
                    {
                        this.ExecutePlugIns(ExecutionBehaviors.Before);

                        // It got created in the ExtractingHtmlInfo step above
                        // so there is actually nothing to do here.

                        this.ExecutePlugIns(ExecutionBehaviors.After);
                    }

                    // Generate the help project file
                    this.ReportProgress(BuildStep.GenerateHelpProject, "Generating HTML Help 1 project file...");

                    if(!this.ExecutePlugIns(ExecutionBehaviors.InsteadOf))
                    {
                        this.ExecutePlugIns(ExecutionBehaviors.Before);
                        substitutionTags.TransformTemplate("Help1x.hhp", templateFolder, workingFolder);
                        this.ExecutePlugIns(ExecutionBehaviors.After);
                    }

                    // Build the HTML Help 1 help file
                    this.ReportProgress(BuildStep.CompilingHelpFile, "Compiling HTML Help 1 file...");

                    if(!this.ExecutePlugIns(ExecutionBehaviors.InsteadOf))
                    {
                        scriptFile = substitutionTags.TransformTemplate("Build1xHelpFile.proj", templateFolder,
                            workingFolder);

                        this.ExecutePlugIns(ExecutionBehaviors.Before);

                        taskRunner.RunProject("Build1xHelpFile.proj", true);
                        
                        this.GatherBuildOutputFilenames();
                        this.ExecutePlugIns(ExecutionBehaviors.After);
                    }
                }

                if((project.HelpFileFormat & HelpFileFormats.MSHelpViewer) != 0)
                {
                    // The following build steps are executed to allow plug-ins to handle any necessary processing
                    // but nothing actually happens here:
                    //
                    //      BuildStep.GenerateHelpFormatTableOfContents
                    //      BuildStep.GenerateHelpProject
                    //
                    // For the MS Help Viewer format, there is no project file to compile and the TOC layout is
                    // generated when the help file is ultimately installed using metadata within each topic file.
                    // All of the necessary TOC info is stored in the intermediate TOC file generated prior to
                    // building the topics.  The BuildAssembler MSHCComponent inserts the TOC info into each topic
                    // as it is built.

                    this.ReportProgress(BuildStep.GenerateHelpFormatTableOfContents,
                        "Executing informational Generate Table of Contents " +
                        "build step for plug-ins (not used for MS Help Viewer)");

                    currentFormat = HelpFileFormats.MSHelpViewer;

                    if(!this.ExecutePlugIns(ExecutionBehaviors.InsteadOf))
                    {
                        this.ExecutePlugIns(ExecutionBehaviors.Before);
                        this.ExecutePlugIns(ExecutionBehaviors.After);
                    }

                    this.ReportProgress(BuildStep.GenerateHelpProject,
                        "Executing informational Generate Help Project " +
                        "build step for plug-ins (not used for MS Help Viewer)");

                    if(!this.ExecutePlugIns(ExecutionBehaviors.InsteadOf))
                    {
                        this.ExecutePlugIns(ExecutionBehaviors.Before);
                        this.ExecutePlugIns(ExecutionBehaviors.After);
                    }

                    // Build the MS Help Viewer help file
                    this.ReportProgress(BuildStep.CompilingHelpFile, "Generating MS Help Viewer file...");

                    if(!this.ExecutePlugIns(ExecutionBehaviors.InsteadOf))
                    {
                        substitutionTags.TransformTemplate("HelpContentSetup.msha", templateFolder, workingFolder);

                        // Rename the content setup file to use the help filename to keep them related and
                        // so that multiple output files can be sent to the same output folder.
                        File.Move(workingFolder + "HelpContentSetup.msha", workingFolder + this.ResolvedHtmlHelpName + ".msha");

                        // Generate the example install and remove scripts
                        substitutionTags.TransformTemplate("InstallMSHC.bat", templateFolder, workingFolder);
                        File.Move(workingFolder + "InstallMSHC.bat", workingFolder + "Install_" +
                            this.ResolvedHtmlHelpName + ".bat");

                        substitutionTags.TransformTemplate("RemoveMSHC.bat", templateFolder, workingFolder);
                        File.Move(workingFolder + "RemoveMSHC.bat", workingFolder + "Remove_" +
                            this.ResolvedHtmlHelpName + ".bat");

                        // Copy the launcher utility
                        File.Copy(ComponentUtilities.ToolsFolder + "HelpLibraryManagerLauncher.exe",
                            workingFolder + "HelpLibraryManagerLauncher.exe");
                        File.SetAttributes(workingFolder + "HelpLibraryManagerLauncher.exe", FileAttributes.Normal);

                        scriptFile = substitutionTags.TransformTemplate("BuildHelpViewerFile.proj", templateFolder,
                            workingFolder);

                        this.ExecutePlugIns(ExecutionBehaviors.Before);

                        taskRunner.RunProject("BuildHelpViewerFile.proj", true);

                        this.GatherBuildOutputFilenames();
                        this.ExecutePlugIns(ExecutionBehaviors.After);
                    }
                }

                if((project.HelpFileFormat & HelpFileFormats.Website) != 0)
                {
                    // Generate the table of contents and set the default topic
                    this.ReportProgress(BuildStep.GenerateHelpFormatTableOfContents,
                        "Generating website table of contents file...");

                    currentFormat = HelpFileFormats.Website;

                    if(!this.ExecutePlugIns(ExecutionBehaviors.InsteadOf))
                    {
                        this.ExecutePlugIns(ExecutionBehaviors.Before);

                        // It got created in the ExtractingHtmlInfo step above
                        // so there is actually nothing to do here.

                        this.ExecutePlugIns(ExecutionBehaviors.After);
                    }

                    this.GenerateWebsite();
                }

                if((project.HelpFileFormat & HelpFileFormats.OpenXml) != 0)
                {
                    // The following build steps are executed to allow plug-ins to handle any necessary processing
                    // but nothing actually happens here:
                    //
                    //      BuildStep.GenerateHelpFormatTableOfContents
                    //      BuildStep.GenerateHelpProject
                    //
                    // For the Open XML format, there is no project file to compile and the TOC layout is
                    // generated when the document is opened.  All of the necessary TOC info is stored in the
                    // intermediate TOC file generated prior to building the topics.  The process used to merge
                    // the topics into a single document uses it to define the order in which the topics are
                    // combined.

                    this.ReportProgress(BuildStep.GenerateHelpFormatTableOfContents, "Executing informational " +
                        "Generate Table of Contents build step for plug-ins (not used for Open XML)");

                    currentFormat = HelpFileFormats.OpenXml;

                    if(!this.ExecutePlugIns(ExecutionBehaviors.InsteadOf))
                    {
                        this.ExecutePlugIns(ExecutionBehaviors.Before);
                        this.ExecutePlugIns(ExecutionBehaviors.After);
                    }

                    this.ReportProgress(BuildStep.GenerateHelpProject, "Executing informational Generate Help " +
                        "Project build step for plug-ins (not used for Open XML)");

                    if(!this.ExecutePlugIns(ExecutionBehaviors.InsteadOf))
                    {
                        this.ExecutePlugIns(ExecutionBehaviors.Before);
                        this.ExecutePlugIns(ExecutionBehaviors.After);
                    }

                    // Build the Open XML document
                    this.ReportProgress(BuildStep.CompilingHelpFile, "Generating Open XML document file...");

                    if(!this.ExecutePlugIns(ExecutionBehaviors.InsteadOf))
                    {
                        scriptFile = substitutionTags.TransformTemplate("BuildOpenXmlFile.proj", templateFolder,
                            workingFolder);

                        this.ExecutePlugIns(ExecutionBehaviors.Before);

                        taskRunner.RunProject("BuildOpenXmlFile.proj", true);

                        this.GatherBuildOutputFilenames();
                        this.ExecutePlugIns(ExecutionBehaviors.After);
                    }
                }

                if((project.HelpFileFormat & HelpFileFormats.Markdown) != 0)
                {
                    // The following build steps are executed to allow plug-ins to handle any necessary processing
                    // but nothing actually happens here:
                    //
                    //      BuildStep.GenerateHelpFormatTableOfContents
                    //      BuildStep.GenerateHelpProject
                    //
                    // For the Markdown format, there is no project file to compile and the TOC layout is
                    // generated by the build task.  All of the necessary TOC info is stored in the intermediate
                    // TOC file generated prior to building the topics.  The build task uses it to find the
                    // topics to finalize and generate the sidebar TOC file.
                    this.ReportProgress(BuildStep.GenerateHelpFormatTableOfContents, "Executing informational " +
                        "Generate Table of Contents build step for plug-ins (not used for Markdown)");

                    currentFormat = HelpFileFormats.Markdown;

                    if(!this.ExecutePlugIns(ExecutionBehaviors.InsteadOf))
                    {
                        this.ExecutePlugIns(ExecutionBehaviors.Before);
                        this.ExecutePlugIns(ExecutionBehaviors.After);
                    }

                    this.ReportProgress(BuildStep.GenerateHelpProject, "Executing informational Generate Help " +
                        "Project build step for plug-ins (not used for Markdown)");

                    if(!this.ExecutePlugIns(ExecutionBehaviors.InsteadOf))
                    {
                        this.ExecutePlugIns(ExecutionBehaviors.Before);
                        this.ExecutePlugIns(ExecutionBehaviors.After);
                    }

                    // Generate the markdown content
                    this.ReportProgress(BuildStep.CompilingHelpFile, "Generating markdown content...");

                    if(!this.ExecutePlugIns(ExecutionBehaviors.InsteadOf))
                    {
                        scriptFile = substitutionTags.TransformTemplate("GenerateMarkdownContent.proj",
                            templateFolder, workingFolder);

                        this.ExecutePlugIns(ExecutionBehaviors.Before);

                        taskRunner.RunProject("GenerateMarkdownContent.proj", true);

                        this.GatherBuildOutputFilenames();
                        this.ExecutePlugIns(ExecutionBehaviors.After);
                    }
                }

                // All done
                if(project.CleanIntermediates)
                {
                    this.ReportProgress(BuildStep.CleanIntermediates, "Removing intermediate files...");

                    if(!this.ExecutePlugIns(ExecutionBehaviors.InsteadOf))
                    {
                        this.ExecutePlugIns(ExecutionBehaviors.Before);

                        try
                        {
                            Directory.Delete(workingFolder, true);
                        }
                        catch(IOException ioEx)
                        {
                            this.ReportProgress("    Not all build output was removed from '{0}': {1}",
                                workingFolder, ioEx.Message);
                        }
                        catch(UnauthorizedAccessException uaEx)
                        {
                            this.ReportProgress("    Not all build output was removed from '{0}': {1}",
                                workingFolder, uaEx.Message);
                        }

                        this.ExecutePlugIns(ExecutionBehaviors.After);
                    }
                }
AllDone:
                TimeSpan runtime = DateTime.Now - buildStart;

                this.ReportProgress(BuildStep.Completed, "\r\nBuild completed successfully at {0}.  " +
                    "Total time: {1:00}:{2:00}:{3:00.0000}\r\n", DateTime.Now, Math.Floor(runtime.TotalSeconds / 3600),
                    Math.Floor((runtime.TotalSeconds % 3600) / 60), (runtime.TotalSeconds % 60));

                System.Diagnostics.Debug.WriteLine("Build process finished successfully\r\n");
            }
            catch(OperationCanceledException )
            {
                buildCancelling = true;

                this.ReportError(BuildStep.Canceled, "BE0064", "BUILD CANCELLED BY USER");

                System.Diagnostics.Debug.WriteLine("Build process aborted\r\n");
            }
            catch(Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(ex);

                var agEx = ex as AggregateException;

                if(agEx != null)
                    foreach(var inEx in agEx.InnerExceptions)
                    {
                        if(message != null)
                            message += "\r\n\r\n";

                        message += inEx.Message + "\r\n" + inEx.StackTrace;
                    }

                var bex = ex as BuilderException;

                do
                {
                    if(message != null)
                        message += "\r\n\r\n";

                    message += ex.Message + "\r\n" + ex.StackTrace;
                    ex = ex.InnerException;

                } while(ex != null);

                // NOTE: Message may contain format markers so pass it as a format argument
                if(bex != null)
                    this.ReportError(BuildStep.Failed, bex.ErrorCode, "{0}", message);
                else
                    this.ReportError(BuildStep.Failed, "BE0065", "BUILD FAILED: {0}", message);

                System.Diagnostics.Debug.WriteLine("Build process failed\r\n");
            }
            finally
            {
                try
                {
                    this.ExecutePlugIns(ExecutionBehaviors.Before);
                }
                catch(Exception ex)
                {
                    // Not much we can do at this point...
                    this.ReportProgress(ex.ToString());
                }

                try
                {
                    this.ExecutePlugIns(ExecutionBehaviors.After);

                    if(componentContainer != null)
                        componentContainer.Dispose();
                }
                catch(Exception ex)
                {
                    // Not much we can do at this point...
                    this.ReportProgress(ex.ToString());
                }
                finally
                {
                    if(swLog != null)
                    {
                        swLog.WriteLine("</buildStep>\r\n</shfbBuild>");
                        swLog.Close();
                        swLog = null;
                    }

                    // If we created a copy of the project, dispose of it and return to the original
                    if(originalProject != null)
                    {
                        project.Dispose();
                        project = originalProject;
                    }

                    if(this.CurrentBuildStep == BuildStep.Completed && !project.KeepLogFile)
                        File.Delete(this.LogFilename);
                }
            }
        }
示例#10
0
        static internal void Convert(BuildProcess builder, HelpFileFormats format)
        {
            // Check which modes all need to be compiled
            string basePath         = builder.WorkingFolder;
            string htmlHelp1Path    = @"Output\HtmlHelp1";
            string MsHelpViewerPath = @"Output\MsHelpViewer";
            string websitePath      = @"Output\Website";
            string htmlPath         = "html";

            if (format == HelpFileFormats.HtmlHelp1)
            {
                builder.ReportProgress("Editing htmlHelp1 files...");
                string   htmlFolderPath = Path.Combine(basePath, htmlHelp1Path, htmlPath);
                string[] hhcPaths       = Directory.GetFiles(basePath, "*.hhc", SearchOption.TopDirectoryOnly);
                string[] hhkPaths       = Directory.GetFiles(basePath, "*.hhk", SearchOption.TopDirectoryOnly);

                if (Directory.Exists(htmlFolderPath))
                {
                    builder.ReportProgress("  Editing html topic pages...");
                    XSharpDocChanger.editHtmlFolder(builder, htmlFolderPath, format);
                }
                else
                {
                    builder.ReportProgress("  Could not find html folder!");
                }
                if (hhcPaths.Length > 0)
                {
                    builder.ReportProgress("  Editing {0} TOC's for HtmlHelp1...", hhcPaths.Length);
                    foreach (string hhc in hhcPaths)
                    {
                        XSharpDocChanger.editHhc(hhc);
                        XSharpDocChanger.editForTypeNames(hhc);
                    }
                }
                else
                {
                    builder.ReportProgress("   Found no TOC for HtmlHelp1");
                }

                if (hhkPaths.Length > 0)
                {
                    builder.ReportProgress("  Editing {0} index file(s) for HtmlHelp1...", hhkPaths.Length);
                    foreach (string hhk in hhkPaths)
                    {
                        XSharpDocChanger.editHhk(hhk);
                        XSharpDocChanger.editForTypeNames(hhk);
                    }
                }
                else
                {
                    builder.ReportProgress("  Found no index file for HtmlHelp1");
                }
            }
            if (format == HelpFileFormats.MSHelpViewer)
            {
                builder.ReportProgress("Editing MsHelpViewer files...");
                string htmlFolderPath = Path.Combine(basePath, MsHelpViewerPath, htmlPath);
                if (Directory.Exists(htmlFolderPath))
                {
                    builder.ReportProgress("  Editing html topic pages...");
                    XSharpDocChanger.editHtmlFolder(builder, htmlFolderPath, format);
                    // builder.ReportProgress("   Editing TOC and index");
                    //XSharpDocChanger.editHtmlFolderForMSHV(builder, htmlFolderPath);
                }
                else
                {
                    builder.ReportProgress("  Could not find html folder!");
                }
            }
            if (format == HelpFileFormats.Website)
            {
                builder.ReportProgress("Editing Website files...");
                string htmlFolderPath = Path.Combine(basePath, websitePath, htmlPath);
                if (Directory.Exists(htmlFolderPath))
                {
                    builder.ReportProgress("  Editing html topic pages...");
                    XSharpDocChanger.editHtmlFolder(builder, htmlFolderPath, format);
                    //XSharpDocChanger.editForWebsiteFolder(builder,htmlFolderPath);
                }
            }
        }
示例#11
0
        //=====================================================================

        /// <summary>
        /// This returns a complete list of files for inclusion in the compiled help file
        /// </summary>
        /// <param name="folder">The folder to expand</param>
        /// <param name="format">The HTML help file format</param>
        /// <returns>The full list of all files for the help project</returns>
        /// <remarks>The help file list is expanded to ensure that we get all additional content including all
        /// nested subfolders.  The <paramref name="format"/> parameter determines the format of the returned
        /// file list.  For HTML Help 1, it returns a list of the filenames.  For MS Help 2, it returns the list
        /// formatted with the necessary XML markup.</remarks>
        private string HelpProjectFileList(string folder, HelpFileFormats format)
        {
            StringBuilder sb = new StringBuilder(10240);
            string        itemFormat, filename, checkName, sourceFolder = folder;
            bool          encode;

            if (folder == null)
            {
                throw new ArgumentNullException("folder");
            }

            if (folder.Length != 0 && folder[folder.Length - 1] != '\\')
            {
                folder += @"\";
            }

            if ((format & HelpFileFormats.HtmlHelp1) != 0)
            {
                if (folder.IndexOf(',') != -1 || folder.IndexOf(".h", StringComparison.OrdinalIgnoreCase) != -1)
                {
                    this.ReportWarning("BE0060", "The file path '{0}' contains a comma or '.h' which may " +
                                       "cause the Help 1 compiler to fail.", folder);
                }

                if (this.ResolvedHtmlHelpName.IndexOf(',') != -1 ||
                    this.ResolvedHtmlHelpName.IndexOf(".h", StringComparison.OrdinalIgnoreCase) != -1)
                {
                    this.ReportWarning("BE0060", "The HtmlHelpName property value '{0}' contains a comma " +
                                       "or '.h' which may cause the Help 1 compiler to fail.", this.ResolvedHtmlHelpName);
                }

                itemFormat = "{0}\r\n";
                encode     = false;
            }
            else
            {
                itemFormat = "	<File Url=\"{0}\" />\r\n";
                encode     = true;
            }

            foreach (string name in Directory.EnumerateFiles(sourceFolder, "*.*", SearchOption.AllDirectories))
            {
                if (!encode)
                {
                    filename = checkName = name.Replace(folder, String.Empty);

                    if (checkName.EndsWith(".htm", StringComparison.OrdinalIgnoreCase) ||
                        checkName.EndsWith(".html", StringComparison.OrdinalIgnoreCase))
                    {
                        checkName = checkName.Substring(0, checkName.LastIndexOf(".htm",
                                                                                 StringComparison.OrdinalIgnoreCase));
                    }

                    if (checkName.IndexOf(',') != -1 || checkName.IndexOf(".h",
                                                                          StringComparison.OrdinalIgnoreCase) != -1)
                    {
                        this.ReportWarning("BE0060", "The filename '{0}' " +
                                           "contains a comma or '.h' which may cause the " +
                                           "Help 1 compiler to fail.", filename);
                    }

                    sb.AppendFormat(itemFormat, filename);
                }
                else
                {
                    sb.AppendFormat(itemFormat, HttpUtility.HtmlEncode(name.Replace(folder, String.Empty)));
                }
            }

            return(sb.ToString());
        }
示例#12
0
        /// <summary>
        /// This is used to convert the collection to a string and append it
        /// to the specified string builder.
        /// </summary>
        /// <param name="format">The help file format to use</param>
        /// <param name="sb">The string builder to which the information is
        /// appended.</param>
        internal void ConvertToString(HelpFileFormats format, StringBuilder sb)
        {
            string guid, url, orderAttr, titleAttr;

            switch (format)
            {
            case HelpFileFormats.HtmlHelp1:
                if (children.Count == 0)
                {
                    sb.AppendFormat("<LI><OBJECT type=\"text/sitemap\">\r\n" +
                                    "<param name=\"Name\" value=\"{0}\">\r\n" +
                                    "<param name=\"Local\" value=\"{1}\">\r\n" +
                                    "</OBJECT></LI>\r\n", WebUtility.HtmlEncode(this.Title),
                                    WebUtility.HtmlEncode(this.DestinationFile));
                }
                else
                {
                    if (String.IsNullOrEmpty(this.DestinationFile))
                    {
                        sb.AppendFormat("<LI><OBJECT type=\"text/sitemap\">\r\n" +
                                        "<param name=\"Name\" value=\"{0}\">\r\n" +
                                        "</OBJECT></LI>\r\n",
                                        WebUtility.HtmlEncode(this.Title));
                    }
                    else
                    {
                        sb.AppendFormat("<LI><OBJECT type=\"text/sitemap\">\r\n" +
                                        "<param name=\"Name\" value=\"{0}\">\r\n" +
                                        "<param name=\"Local\" value=\"{1}\">\r\n" +
                                        "</OBJECT></LI>\r\n",
                                        WebUtility.HtmlEncode(this.Title),
                                        WebUtility.HtmlEncode(this.DestinationFile));
                    }

                    sb.Append("<UL>\r\n");
                    children.ConvertToString(format, sb);
                    sb.Append("</UL>\r\n");
                }
                break;

            case HelpFileFormats.MSHelp2:
            case HelpFileFormats.Website:
            case HelpFileFormats.OpenXml:
                if (!String.IsNullOrEmpty(this.DestinationFile) && format == HelpFileFormats.Website)
                {
                    url = this.DestinationFile.Replace('\\', '/');
                }
                else
                {
                    url = this.DestinationFile;
                }

                if (children.Count == 0)
                {
                    sb.AppendFormat("<HelpTOCNode Url=\"{0}\" Title=\"{1}\" />\r\n",
                                    WebUtility.HtmlEncode(url), WebUtility.HtmlEncode(this.Title));
                }
                else
                {
                    // Use a GUID to uniquely identify the entries with
                    // children.  This allows the ASP.NET web page to find
                    // them to load the child nodes dynamically.
                    guid = Guid.NewGuid().ToString();

                    // If there is no file for the root node, define the title
                    // property instead.
                    if (String.IsNullOrEmpty(url))
                    {
                        sb.AppendFormat("<HelpTOCNode Id=\"{0}\" Title=\"{1}\">\r\n",
                                        guid, WebUtility.HtmlEncode(this.Title));
                    }
                    else
                    {
                        sb.AppendFormat("<HelpTOCNode Id=\"{0}\" Url=\"{1}\" Title=\"{2}\">\r\n",
                                        guid, url, WebUtility.HtmlEncode(this.Title));
                    }

                    children.ConvertToString(format, sb);
                    sb.Append("</HelpTOCNode>\r\n");
                }
                break;

            case HelpFileFormats.MSHelpViewer:
                if (String.IsNullOrEmpty(this.DestinationFile))
                {
                    url       = WebUtility.HtmlEncode(this.Id);
                    titleAttr = String.Format(CultureInfo.InvariantCulture, " title=\"{0}\"",
                                              WebUtility.HtmlEncode(this.Title));
                }
                else
                {
                    url       = WebUtility.HtmlEncode(Path.GetFileNameWithoutExtension(this.DestinationFile));
                    titleAttr = String.Empty;
                }

                if (this.SortOrder != -1)
                {
                    orderAttr = String.Format(CultureInfo.InvariantCulture, " sortOrder=\"{0}\"", this.SortOrder);
                }
                else
                {
                    orderAttr = String.Empty;
                }

                if (children.Count == 0)
                {
                    sb.AppendFormat("<topic id=\"{0}\" file=\"{0}\"{1}{2} />\r\n", url, orderAttr, titleAttr);
                }
                else
                {
                    sb.AppendFormat("<topic id=\"{0}\" file=\"{0}\"{1}{2}>\r\n", url, orderAttr, titleAttr);

                    children.ConvertToString(format, sb);
                    sb.Append("</topic>\r\n");
                }
                break;

            default:
                throw new InvalidOperationException("Unknown TOC help format: " + format.ToString());
            }
        }
示例#13
0
 /// <summary>
 /// Constructor
 /// </summary>
 /// <param name="helpFileFormats">The help file formats to which the files apply</param>
 /// <param name="sourcePath">The source path</param>
 /// <param name="destination">The destination path to use in the build output</param>
 public ContentFiles(HelpFileFormats helpFileFormats, string sourcePath, string destination) :
   this(helpFileFormats, null, sourcePath, destination, Enumerable.Empty<string>())
 {
 }
示例#14
0
        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="helpFileFormats">The help file formats to which the files apply</param>
        /// <param name="basePath">An alternate base path or null to use the presentation style base path</param>
        /// <param name="sourcePath">The source path</param>
        /// <param name="destination">The destination path</param>
        /// <param name="templateFileExtensions">An enumerable list of file extensions to treat as template files</param>
        public ContentFiles(HelpFileFormats helpFileFormats, string basePath, string sourcePath,
          string destination, IEnumerable<string> templateFileExtensions)
        {
            if(Path.IsPathRooted(sourcePath))
                throw new InvalidOperationException("Content source path must be relative");

            if(!String.IsNullOrEmpty(destination))
            {
                if(Path.IsPathRooted(destination))
                    throw new InvalidOperationException("Content destination path must be relative");

                if(destination.IndexOfAny(new[] { '*', '?' }) != -1)
                    throw new InvalidOperationException("Content destination must be a path only");
            }

            this.HelpFileFormats = helpFileFormats;
            this.BasePath = basePath;
            this.SourcePathWildcard = sourcePath;
            this.DestinationFolder = destination;
            this.TemplateFileExtensions = templateFileExtensions.ToList();
        }
示例#15
0
 /// <summary>
 /// Constructor
 /// </summary>
 /// <param name="helpFileFormats">The help file formats to which the files apply</param>
 /// <param name="sourcePath">The source path</param>
 /// <param name="destination">The destination path to use in the build output</param>
 public ContentFiles(HelpFileFormats helpFileFormats, string sourcePath, string destination) :
     this(helpFileFormats, null, sourcePath, destination, Enumerable.Empty <string>())
 {
 }
        /// <summary>
        /// This returns a complete list of files for inclusion in the compiled help file
        /// </summary>
        /// <param name="folder">The folder to expand</param>
        /// <param name="format">The help file format</param>
        /// <returns>The full list of all files for the help project</returns>
        /// <remarks>The help file list is expanded to ensure that we get all additional content including all
        /// nested subfolders.  The <paramref name="format"/> parameter determines the format of the returned
        /// file list.  For HTML Help 1, it returns a list of the filenames.  For all others, it returns the list
        /// formatted with the necessary XML markup.</remarks>
        private string HelpProjectFileList(string folder, HelpFileFormats format)
        {
            string itemFormat, filename, checkName, sourceFolder = folder;
            bool encode;

            if(folder == null)
                throw new ArgumentNullException("folder");

            if(folder.Length != 0 && folder[folder.Length - 1] != '\\')
                folder += @"\";

            if((format & HelpFileFormats.HtmlHelp1) != 0)
            {
                if(folder.IndexOf(',') != -1 || folder.IndexOf(".h", StringComparison.OrdinalIgnoreCase) != -1)
                    currentBuild.ReportWarning("BE0060", "The file path '{0}' contains a comma or '.h' which may " +
                        "cause the Help 1 compiler to fail.", folder);

                if(currentBuild.ResolvedHtmlHelpName.IndexOf(',') != -1 ||
                  currentBuild.ResolvedHtmlHelpName.IndexOf(".h", StringComparison.OrdinalIgnoreCase) != -1)
                    currentBuild.ReportWarning("BE0060", "The HtmlHelpName property value '{0}' contains a comma " +
                        "or '.h' which may cause the Help 1 compiler to fail.", currentBuild.ResolvedHtmlHelpName);

                itemFormat = "{0}\r\n";
                encode = false;
            }
            else
            {
                itemFormat = "	<File Url=\"{0}\" />\r\n";
                encode = true;
            }

            replacementValue.Clear();

            foreach(string name in Directory.EnumerateFiles(sourceFolder, "*.*", SearchOption.AllDirectories))
                if(!encode)
                {
                    filename = checkName = name.Replace(folder, String.Empty);

                    if(checkName.EndsWith(".htm", StringComparison.OrdinalIgnoreCase) ||
                      checkName.EndsWith(".html", StringComparison.OrdinalIgnoreCase))
                        checkName = checkName.Substring(0, checkName.LastIndexOf(".htm", StringComparison.OrdinalIgnoreCase));

                    if(checkName.IndexOf(',') != -1 || checkName.IndexOf(".h", StringComparison.OrdinalIgnoreCase) != -1)
                        currentBuild.ReportWarning("BE0060", "The filename '{0}' contains a comma or '.h' " +
                            "which may cause the Help 1 compiler to fail.", filename);

                    replacementValue.AppendFormat(itemFormat, filename);
                }
                else
                    replacementValue.AppendFormat(itemFormat, WebUtility.HtmlEncode(name.Replace(folder, String.Empty)));

            return replacementValue.ToString();
        }
        //=====================================================================

        /// <summary>
        /// This is used to set the state of a menu command on the View Help menu
        /// </summary>
        /// <param name="command">The command object</param>
        /// <param name="format">The help file format</param>
        private static void SetViewHelpCommandState(OleMenuCommand command, HelpFileFormats? format)
        {
            Array activeProjects = null;
            DTE dte = Utility.GetServiceFromPackage<DTE, DTE>(false);
            bool visible = false, enabled = false;

            if(dte != null)
            {
                Solution s = dte.Solution;

                // Hide the menu option if a SHFB project is not loaded
                if(s != null)
                {
                    visible = s.Projects.Cast<Project>().Any(
                        p => p.UniqueName.EndsWith(".shfbproj", StringComparison.OrdinalIgnoreCase));

                    // Check the active project for the specified help format if visible
                    if(visible)
                    {
                        try
                        {
                            activeProjects = dte.ActiveSolutionProjects as Array;
                        }
                        catch
                        {
                            // The above can throw an exception while the project is loading which
                            // we should ignore.
                        }

                        if(activeProjects != null && activeProjects.Length > 0)
                        {
                            Project p = activeProjects.GetValue(0) as Project;

                            if(p != null && p.Object != null && p.UniqueName.EndsWith(".shfbproj",
                              StringComparison.OrdinalIgnoreCase))
                            {
                                SandcastleBuilderProjectNode pn = (SandcastleBuilderProjectNode)p.Object;
                                string projectHelpFormat = (pn.GetProjectProperty("HelpFileFormat") ??
                                    HelpFileFormats.HtmlHelp1.ToString());

                                enabled = (!pn.BuildInProgress && (format == null || projectHelpFormat.IndexOf(
                                    format.ToString(), StringComparison.OrdinalIgnoreCase) != -1));
                            }
                        }
                    }
                }
            }

            command.Visible = visible;
            command.Enabled = enabled;
        }
示例#18
0
        //=====================================================================

        /// <summary>
        /// Constructor
        /// </summary>
        /// <overloads>There are five overloads for the constructor</overloads>
        protected SandcastleProject()
        {
            characterMatchEval = new MatchEvaluator(this.OnCharacterMatch);
            buildVarMatchEval = new MatchEvaluator(this.OnBuildVarMatch);

            docSources = new DocumentationSourceCollection(this);
            docSources.ListChanged += docSources_ListChanged;

            namespaceSummaries = new NamespaceSummaryItemCollection(this);
            namespaceSummaries.ListChanged += ItemList_ListChanged;

            references = new ReferenceItemCollection(this);
            references.ListChanged += ItemList_ListChanged;

            componentConfigs = new ComponentConfigurationDictionary(this);
            plugInConfigs = new PlugInConfigurationDictionary(this);

            apiFilter = new ApiFilterCollection(this);
            apiFilter.ListChanged += ItemList_ListChanged;

            helpAttributes = new MSHelpAttrCollection(this);
            helpAttributes.ListChanged += ItemList_ListChanged;

            try
            {
                loadingProperties = removeProjectWhenDisposed = true;

                contentPlacement = ContentPlacement.AboveNamespaces;
                cleanIntermediates = keepLogFile = binaryTOC = includeStopWordList = true;

                this.BuildLogFile = null;

                missingTags = MissingTags.Summary | MissingTags.Parameter | MissingTags.TypeParameter |
                    MissingTags.Returns | MissingTags.AutoDocumentCtors | MissingTags.Namespace |
                    MissingTags.AutoDocumentDispose;

                visibleItems = VisibleItems.InheritedFrameworkMembers | VisibleItems.InheritedMembers |
                    VisibleItems.Protected | VisibleItems.ProtectedInternalAsProtected;

                buildAssemblerVerbosity = BuildAssemblerVerbosity.OnlyWarningsAndErrors;
                helpFileFormat = HelpFileFormats.HtmlHelp1;
                htmlSdkLinkType = websiteSdkLinkType = HtmlSdkLinkType.Msdn;
                help2SdkLinkType = MSHelp2SdkLinkType.Msdn;
                helpViewerSdkLinkType = MSHelpViewerSdkLinkType.Msdn;
                sdkLinkTarget = SdkLinkTarget.Blank;
                presentationStyle = Constants.DefaultPresentationStyle;
                namingMethod = NamingMethod.Guid;
                syntaxFilters = ComponentUtilities.DefaultSyntaxFilter;
                collectionTocStyle = CollectionTocStyle.Hierarchical;
                helpFileVersion = "1.0.0.0";
                tocOrder = -1;
                maximumGroupParts = 2;

                this.OutputPath = null;
                this.HtmlHelp1xCompilerPath = this.HtmlHelp2xCompilerPath = this.WorkingPath =
                    this.ComponentPath = null;

                this.HelpTitle = this.HtmlHelpName = this.CopyrightHref = this.CopyrightText =
                    this.FeedbackEMailAddress = this.FeedbackEMailLinkText = this.HeaderText = this.FooterText =
                    this.ProjectSummary = this.RootNamespaceTitle = this.PlugInNamespaces = this.TopicVersion =
                    this.TocParentId = this.TocParentVersion = this.CatalogProductId = this.CatalogVersion =
                    this.CatalogName = null;
                this.FrameworkVersion = null;

                language = new CultureInfo("en-US");
            }
            finally
            {
                loadingProperties = false;
            }
        }