コード例 #1
0
 public ContentGenerator(BuildProcess builder, string gherkinFeaturesPath, CultureInfo gherkinFeaturesLanguage)
 {
     this.builder = builder;
     this.gherkinFeaturesPath = gherkinFeaturesPath;
     this.gherkinFeaturesLanguage = gherkinFeaturesLanguage;
     this.guidsInUse = new HashSet<Guid>();
 }
コード例 #2
0
        /// <summary>
        /// Open the specified collection file and return it as an
        /// <see cref="XmlDocument"/> ready for editing.
        /// </summary>
        /// <param name="file">The file to open</param>
        /// <remarks>The DTD is removed before returning it.</remarks>
        private static XmlDocument OpenCollectionFile(string file)
        {
            XmlDocument doc;
            Encoding    enc     = Encoding.Default;
            string      content = BuildProcess.ReadWithEncoding(file, ref enc);

            // Get rid of the DTD declaration
            content = reRemoveDTD.Replace(content, "$1$3");

            doc = new XmlDocument();
            doc.LoadXml(content);

            return(doc);
        }
コード例 #3
0
        /// <summary>
        /// This is used to extract table of contents information from a file
        /// that will appear in the help file's table of contents.
        /// </summary>
        /// <param name="filename">The file from which to extract the
        /// information</param>
        /// <returns>The table of contents entry</returns>
        internal static TocEntry GetTocInfo(string filename)
        {
            TocEntry tocEntry;
            Encoding enc = Encoding.Default;
            string   content;

            content = BuildProcess.ReadWithEncoding(filename, ref enc);

            tocEntry                = new TocEntry(null);
            tocEntry.IncludePage    = !reTocExclude.IsMatch(content);
            tocEntry.IsDefaultTopic = reIsDefaultTopic.IsMatch(content);

            if (reSplitToc.IsMatch(content))
            {
                tocEntry.ApiParentMode = ApiParentMode.InsertAfter;
            }

            Match m = reSortOrder.Match(content);

            if (m.Success)
            {
                tocEntry.SortOrder = Convert.ToInt32(m.Groups["SortOrder"].Value, CultureInfo.InvariantCulture);
            }

            // Get the page title if possible.  If not found, use the filename
            // without the path or extension as the page title.
            m = rePageTitle.Match(content);
            if (!m.Success)
            {
                tocEntry.Title = Path.GetFileNameWithoutExtension(filename);
            }
            else
            {
                tocEntry.Title = HttpUtility.HtmlDecode(m.Groups["Title"].Value).Replace(
                    "\r", String.Empty).Replace("\n", String.Empty);
            }

            // Since we've got the file loaded, see if there are links
            // that need to be resolved when the file is copied, if it
            // contains <pre> blocks that should be colorized, or if it
            // contains tags or shared content items that need replacing.
            tocEntry.HasLinks        = reResolveLinks.IsMatch(content);
            tocEntry.HasCodeBlocks   = reCodeBlock.IsMatch(content);
            tocEntry.NeedsColorizing = reColorizeCheck.IsMatch(content);
            tocEntry.HasProjectTags  = (reProjectTags.IsMatch(content) || reSharedContent.IsMatch(content));

            return(tocEntry);
        }
コード例 #4
0
        //=====================================================================

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="currentBuild">The current build for which to perform substitution tag replacement</param>
        public SubstitutionTagReplacement(BuildProcess currentBuild)
        {
            this.currentBuild = currentBuild;

            sandcastleProject = currentBuild.CurrentProject;
            msbuildProject = sandcastleProject.MSBuildProject;
            presentationStyle = currentBuild.PresentationStyle;

            replacementValue = new StringBuilder(10240);

            fieldMatchEval = new MatchEvaluator(OnFieldMatch);

            // Get the substitution tag methods so that we can invoke them.  The dictionary keys are the method
            // names and are case-insensitive.  Substitution tag methods take no parameters and return a value
            // that is convertible to a string.
            methodCache = this.GetType().GetMethods(BindingFlags.Instance | BindingFlags.NonPublic).Where(
                m => m.GetCustomAttribute(typeof(SubstitutionTagAttribute)) != null).ToDictionary(
                m => m.Name, m => m, StringComparer.OrdinalIgnoreCase);
        }
コード例 #5
0
 public ContentGenerator(BuildProcess builder, string sourcePath)
 {
     this.builder = builder;
     this.sourcePath = sourcePath;
 }
コード例 #6
0
ファイル: MainForm.cs プロジェクト: armin-bauer/SHFB
        /// <summary>
        /// View the last build help output
        /// </summary>
        /// <param name="sender">The sender of the event</param>
        /// <param name="e">The event arguments</param>
        private void miViewBuiltHelpFile_Click(object sender, EventArgs e)
        {
            // Make sure we start out in the project's output folder in case the output folder is relative to it
            Directory.SetCurrentDirectory(Path.GetDirectoryName(Path.GetFullPath(project.Filename)));

            string outputPath = project.OutputPath;

            // If the output path contains MSBuild variables, get the evaluated value from the project
            if(outputPath.IndexOf("$(", StringComparison.Ordinal) != -1)
                outputPath = project.MSBuildProject.GetProperty("OutputPath").EvaluatedValue;

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

            if(sender == miViewHtmlHelp1)
                outputPath += project.HtmlHelpName + ".chm";
            else
                if(sender == miViewOpenXml)
                    outputPath += project.HtmlHelpName + ".docx";
                else
                    if(sender == miViewHelpFile)
                        outputPath += "_Sidebar.md";
                    else
                        outputPath += "Index.html";

            // If there are substitution tags present, have a go at resolving them
            if(outputPath.IndexOf("{@", StringComparison.Ordinal) != -1)
            {
                try
                {
                    var bp = new BuildProcess(project);
                    outputPath = bp.SubstitutionTags.TransformText(outputPath);
                }
                catch
                {
                    // Ignore errors
                    MessageBox.Show("The help filename appears to contain substitution tags but they could " +
                        "not be resolved to determine the actual file to open for viewing.  Building " +
                        "website output and viewing it can be used to work around this issue.",
                        Constants.AppName, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                    return;
                }
            }

            if(!File.Exists(outputPath))
            {
                MessageBox.Show("A copy of the help file does not appear to exist yet.  It may need to be built.",
                    Constants.AppName, MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }

            try
            {
                System.Diagnostics.Process.Start(outputPath);
            }
            catch(Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(ex.ToString());
                MessageBox.Show(String.Format(CultureInfo.CurrentCulture, "Unable to open help file '{0}'\r\nReason: {1}",
                    outputPath, ex.Message), Constants.AppName, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
            }
        }
コード例 #7
0
ファイル: Topic.cs プロジェクト: aeagle/SHFB
        /// <summary>
        /// Write out the <strong>BuildAssembler</strong> manifest entry
        /// </summary>
        /// <param name="writer">The XML writer to which the entry is written</param>
        /// <param name="builder">The build process</param>
        /// <remarks>This will recursively write out entries for sub-topics as well</remarks>
        internal void WriteManifest(XmlWriter writer, BuildProcess builder)
        {
            // MS Help Viewer doesn't support empty place holders so we automatically generate a dummy place
            // holder file for them.
            if(!noFile || (builder.CurrentProject.HelpFileFormat & HelpFileFormats.MSHelpViewer) != 0)
            {
                writer.WriteStartElement("topic");
                writer.WriteAttributeString("id", this.Id);
                writer.WriteAttributeString("type", "MAML");
                writer.WriteEndElement();
            }

            foreach(Topic t in subtopics)
                t.WriteManifest(writer, builder);
        }
コード例 #8
0
        /// <summary>
        /// This method is used to initialize the plug-in at the start of the build process
        /// </summary>
        /// <param name="buildProcess">A reference to the current build process</param>
        /// <param name="configuration">The configuration data that the plug-in should use to initialize itself</param>
        /// <exception cref="BuilderException">This is thrown if the plug-in configuration is not valid</exception>
        public void Initialize(BuildProcess buildProcess, XPathNavigator configuration)
        {
            XPathNavigator root, node;
            string value;

            builder = buildProcess;
            attachLogOnSuccess = false;
            attachLogOnFailure = true;
            smtpServer = successEMailAddress = failureEMailAddress = xslTransformFile = String.Empty;
            credentials = new UserCredentials();
            smtpPort = 25;

            var metadata = (HelpFileBuilderPlugInExportAttribute)this.GetType().GetCustomAttributes(
                typeof(HelpFileBuilderPlugInExportAttribute), false).First();

            builder.ReportProgress("{0} Version {1}\r\n{2}", metadata.Id, metadata.Version, metadata.Copyright);

            root = configuration.SelectSingleNode("configuration");

            if(root.IsEmptyElement)
                throw new BuilderException("CNP0001", "The Completion Notification plug-in has not been " +
                    "configured yet");

            node = root.SelectSingleNode("smtpServer");

            if(node != null)
            {
                smtpServer = node.GetAttribute("host", String.Empty).Trim();
                value = node.GetAttribute("port", String.Empty);

                if(!Int32.TryParse(value, out smtpPort))
                    smtpPort = 25;
            }

            credentials = UserCredentials.FromXPathNavigator(root);

            node = root.SelectSingleNode("fromEMail");

            if(node != null)
                fromEMailAddress = node.GetAttribute("address", String.Empty).Trim();

            node = root.SelectSingleNode("successEMail");

            if(node != null)
            {
                successEMailAddress = node.GetAttribute("address", String.Empty).Trim();
                attachLogOnSuccess = Convert.ToBoolean(node.GetAttribute("attachLog", String.Empty),
                    CultureInfo.InvariantCulture);
            }

            node = root.SelectSingleNode("failureEMail");

            if(node != null)
            {
                failureEMailAddress = node.GetAttribute("address", String.Empty).Trim();
                attachLogOnFailure = Convert.ToBoolean(node.GetAttribute("attachLog", String.Empty),
                    CultureInfo.InvariantCulture);
            }

            node = root.SelectSingleNode("xslTransform");

            if(node != null)
                xslTransformFile = builder.TransformText(node.GetAttribute("filename", String.Empty).Trim());

            if((!credentials.UseDefaultCredentials && (credentials.UserName.Length == 0 ||
              credentials.Password.Length == 0)) || failureEMailAddress.Length == 0)
                throw new BuilderException("CNP0002", "The Completion Notification plug-in has an invalid " +
                    "configuration");
        }
コード例 #9
0
ファイル: TaskRunner.cs プロジェクト: hlonib/EWSoftware
        //=====================================================================

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="currentBuild">The current build for which to execute tasks</param>
        public TaskRunner(BuildProcess currentBuild)
        {
            this.currentBuild = currentBuild;
        }
コード例 #10
0
ファイル: Topic.cs プロジェクト: codemonster234/scbuilder
        /// <summary>
        /// Write out the topic metadata
        /// </summary>
        /// <param name="writer">The writer to which the metadata is written</param>
        /// <param name="builder">The build process</param>
        /// <remarks>This will recursively write out metadata for sub-topics
        /// as well.</remarks>
        internal void WriteMetadata(XmlWriter writer, BuildProcess builder)
        {
            // MS Help Viewer doesn't support empty place holders so we automatically
            // generate a dummy place holder file for them.
            if(!noFile || (builder.CurrentProject.HelpFileFormat & HelpFileFormat.MSHelpViewer) != 0)
            {
                writer.WriteStartElement("topic");
                writer.WriteAttributeString("id", this.Id);
                writer.WriteAttributeString("revisionNumber",
                    this.RevisionNumber.ToString(CultureInfo.InvariantCulture));

                // Write out the help file version project property value
                writer.WriteStartElement("item");
                writer.WriteAttributeString("id", "PBM_FileVersion");
                writer.WriteValue(builder.TransformText(builder.CurrentProject.HelpFileVersion));
                writer.WriteEndElement();

                // If no title is specified, use the display title
                writer.WriteStartElement("title");

                if(!String.IsNullOrEmpty(title))
                    writer.WriteString(title);
                else
                    writer.WriteString(this.DisplayTitle);

                writer.WriteEndElement();

                // TOC title is optional
                if(!String.IsNullOrEmpty(tocTitle))
                    writer.WriteElementString("tableOfContentsTitle", tocTitle);

                // The running header text ID is set to "runningHeaderText"
                // so that it pulls in the shared content item by that name.
                // This will equate to the project's HTML encoded HelpTitle
                // property value.
                writer.WriteStartElement("runningHeaderText");
                writer.WriteAttributeString("uscid", "runningHeaderText");
                writer.WriteEndElement();

                // Each topic includes the project-level help attributes
                foreach(MSHelpAttr attr in builder.CurrentProject.HelpAttributes)
                {
                    writer.WriteStartElement("attribute");
                    writer.WriteAttributeString("name", attr.AttributeName);

                    // Replace tags with their project property value
                    writer.WriteValue(builder.TransformText(attr.AttributeValue));

                    writer.WriteEndElement();
                }

                // Add topic-specific attributes
                foreach(MSHelpAttr attr in helpAttributes)
                {
                    writer.WriteStartElement("attribute");
                    writer.WriteAttributeString("name", attr.AttributeName);

                    // Replace tags with their project property value
                    writer.WriteValue(builder.TransformText(attr.AttributeValue));

                    writer.WriteEndElement();
                }

                // Add topic-specific index keywords
                foreach(MSHelpKeyword kw in keywords)
                {
                    writer.WriteStartElement("keyword");
                    writer.WriteAttributeString("index", kw.Index);

                    // Replace tags with their project property value
                    writer.WriteValue(builder.TransformText(kw.Term));

                    writer.WriteEndElement();
                }

                // If this is the default topic and the NamedUrlIndex keywords
                // for DefaultPage and/or HomePage are not present, add them.
                if(this.IsDefaultTopic)
                {
                    if(!keywords.Contains(new MSHelpKeyword("NamedUrlIndex", "DefaultPage")))
                    {
                        writer.WriteStartElement("keyword");
                        writer.WriteAttributeString("index", "NamedUrlIndex");
                        writer.WriteValue("DefaultPage");
                        writer.WriteEndElement();
                    }

                    if(!keywords.Contains(new MSHelpKeyword("NamedUrlIndex", "HomePage")))
                    {
                        writer.WriteStartElement("keyword");
                        writer.WriteAttributeString("index", "NamedUrlIndex");
                        writer.WriteValue("HomePage");
                        writer.WriteEndElement();
                    }
                }

                writer.WriteEndElement();   // </topic>
            }

            // Write metadata for sub-topics too
            foreach(Topic t in subtopics)
                t.WriteMetadata(writer, builder);
        }
コード例 #11
0
        /// <summary>
        /// This is called to load an additional content file, resolve links to namespace content and copy it to
        /// the output folder.
        /// </summary>
        /// <param name="sourceFile">The source filename to copy</param>
        /// <param name="destFile">The destination filename</param>
        /// <param name="entry">The entry being resolved.</param>
        internal void ResolveLinksAndCopy(string sourceFile, string destFile, TocEntry entry)
        {
            Encoding enc = Encoding.Default;
            string   content, script, syntaxFile;
            int      pos;

            // For topics, change the extension back to ".topic".  It's ".html" in the TOC as that's what it ends
            // up as after transformation.
            if (sourceFile.EndsWith(".topic", StringComparison.OrdinalIgnoreCase))
            {
                destFile = Path.ChangeExtension(destFile, ".topic");
            }

            this.ReportProgress("{0} -> {1}", sourceFile, destFile);

            // When reading the file, use the default encoding but detect the encoding if byte order marks are
            // present.
            content = BuildProcess.ReadWithEncoding(sourceFile, ref enc);

            // Expand <code> tags if necessary
            if (entry.HasCodeBlocks)
            {
                content = reCodeBlock.Replace(content, codeBlockMatchEval);
            }

            // Colorize <pre> tags if necessary
            if (entry.NeedsColorizing || entry.HasCodeBlocks)
            {
                // Initialize code colorizer on first use
                if (codeColorizer == null)
                {
                    codeColorizer = new CodeColorizer(ComponentUtilities.ToolsFolder +
                                                      @"PresentationStyles\Colorizer\highlight.xml", ComponentUtilities.ToolsFolder +
                                                      @"PresentationStyles\Colorizer\highlight.xsl");
                }

                // Set the path the "Copy" image
                codeColorizer.CopyImageUrl = pathToRoot + "icons/CopyCode.gif";

                // Colorize it and replace the "Copy" literal text with the shared content include item so that
                // it gets localized.
                content = codeColorizer.ProcessAndHighlightText(content);
                content = content.Replace(codeColorizer.CopyText + "</span", "<include item=\"copyCode\"/></span");
                entry.HasProjectTags = true;

                // Add the links to the colorizer style sheet and script files unless it's going to be
                // transformed.  In which case, the links should be in the XSL style sheet.
                if (!sourceFile.EndsWith(".topic", StringComparison.OrdinalIgnoreCase) &&
                    !sourceFile.EndsWith(".xsl", StringComparison.OrdinalIgnoreCase))
                {
                    script = String.Format(CultureInfo.InvariantCulture,
                                           "<link type='text/css' rel='stylesheet' href='{0}styles/highlight.css' />" +
                                           "<script type='text/javascript' src='{0}scripts/highlight_ac.js'></script>", pathToRoot);

                    pos = content.IndexOf("</head>", StringComparison.Ordinal);

                    // Create a <head> section if one doesn't exist
                    if (pos == -1)
                    {
                        script = "<head>" + script + "</head>";
                        pos    = content.IndexOf("<html>", StringComparison.Ordinal);

                        if (pos != -1)
                        {
                            pos += 6;
                        }
                        else
                        {
                            pos = 0;
                        }
                    }

                    content = content.Insert(pos, script);
                }

                // Copy the colorizer files if not already there
                this.EnsureOutputFoldersExist("icons");
                this.EnsureOutputFoldersExist("styles");
                this.EnsureOutputFoldersExist("scripts");

                foreach (string baseFolder in this.HelpFormatOutputFolders)
                {
                    if (!File.Exists(baseFolder + @"styles\highlight.css"))
                    {
                        syntaxFile = baseFolder + @"styles\highlight.css";
                        File.Copy(ComponentUtilities.ToolsFolder + @"PresentationStyles\Colorizer\highlight.css",
                                  syntaxFile);
                        File.SetAttributes(syntaxFile, FileAttributes.Normal);

                        syntaxFile = baseFolder + @"scripts\highlight_ac.js";
                        File.Copy(ComponentUtilities.ToolsFolder + @"PresentationStyles\Colorizer\highlight_ac.js",
                                  syntaxFile);
                        File.SetAttributes(syntaxFile, FileAttributes.Normal);

                        // Always copy the image files, they may be different.  Also, delete the destination file
                        // first if it exists as the filename casing may be different.
                        syntaxFile = baseFolder + @"icons\CopyCode.gif";

                        if (File.Exists(syntaxFile))
                        {
                            File.SetAttributes(syntaxFile, FileAttributes.Normal);
                            File.Delete(syntaxFile);
                        }

                        File.Copy(ComponentUtilities.ToolsFolder + @"PresentationStyles\Colorizer\CopyCode.gif",
                                  syntaxFile);
                        File.SetAttributes(syntaxFile, FileAttributes.Normal);

                        syntaxFile = baseFolder + @"icons\CopyCode_h.gif";

                        if (File.Exists(syntaxFile))
                        {
                            File.SetAttributes(syntaxFile, FileAttributes.Normal);
                            File.Delete(syntaxFile);
                        }

                        File.Copy(ComponentUtilities.ToolsFolder + @"PresentationStyles\Colorizer\CopyCode_h.gif",
                                  syntaxFile);
                        File.SetAttributes(syntaxFile, FileAttributes.Normal);
                    }
                }
            }

            // Use a regular expression to find and replace all tags with cref attributes with a link to the help
            // file content.  This needs to happen after the code block processing as they may contain <see> tags
            // that need to be resolved.
            if (entry.HasLinks || entry.HasCodeBlocks)
            {
                content = reResolveLinks.Replace(content, linkMatchEval);
            }

            // Replace project option tags with project option values
            if (entry.HasProjectTags)
            {
                // Project tags can be nested
                while (reProjectTags.IsMatch(content))
                {
                    content = reProjectTags.Replace(content, fieldMatchEval);
                }

                // Shared content items can be nested
                while (reSharedContent.IsMatch(content))
                {
                    content = reSharedContent.Replace(content, contentMatchEval);
                }
            }

            // Write the file back out with the appropriate encoding
            using (StreamWriter sw = new StreamWriter(destFile, false, enc))
            {
                sw.Write(content);
            }

            // Transform .topic files into .html files
            if (sourceFile.EndsWith(".topic", StringComparison.OrdinalIgnoreCase))
            {
                this.XslTransform(destFile);
            }
        }
コード例 #12
0
        /// <summary>
        /// This is used to merge destination file information into the site
        /// map TOC.
        /// </summary>
        /// <param name="site">The site entry to update</param>
        /// <remarks>In addition, files in the site map that do not exist in
        /// the TOC built from the defined content will be processed and
        /// copied to the root folder.</remarks>
        private void MergeTocInfo(TocEntry site)
        {
            TocEntry match;
            string   source, filename;

            if (site.SourceFile.Path.Length != 0)
            {
                match = toc.Find(site.SourceFile);

                if (match != null)
                {
                    site.DestinationFile = match.DestinationFile;
                }
                else
                {
                    source = site.SourceFile;
                    site.DestinationFile = Path.GetFileName(source);
                    filename             = site.DestinationFile;

                    // .topic files get transformed into .html files
                    if (source.EndsWith(".topic", StringComparison.OrdinalIgnoreCase))
                    {
                        site.DestinationFile = Path.ChangeExtension(site.DestinationFile, ".html");
                    }

                    // Check to see if anything needs resolving
                    if (source.EndsWith(".htm", StringComparison.OrdinalIgnoreCase) ||
                        source.EndsWith(".html", StringComparison.OrdinalIgnoreCase) ||
                        source.EndsWith(".topic", StringComparison.OrdinalIgnoreCase))
                    {
                        match = BuildProcess.GetTocInfo(source);
                    }

                    foreach (string baseFolder in this.HelpFormatOutputFolders)
                    {
                        // If the file contains items that need to be resolved, it is handled separately
                        if (match != null && (match.HasLinks || match.HasCodeBlocks ||
                                              match.NeedsColorizing || match.HasProjectTags ||
                                              source.EndsWith(".topic", StringComparison.OrdinalIgnoreCase)))
                        {
                            // Files are always copied to the root
                            pathToRoot = String.Empty;

                            this.ResolveLinksAndCopy(source, baseFolder + filename, match);
                        }
                        else
                        {
                            this.ReportProgress("{0} -> {1}{2}", source, baseFolder, filename);

                            // All attributes are turned off so that we can delete it later
                            File.Copy(source, baseFolder + filename, true);
                            File.SetAttributes(baseFolder + filename, FileAttributes.Normal);
                        }
                    }
                }
            }

            if (site.Children.Count != 0)
            {
                foreach (TocEntry entry in site.Children)
                {
                    this.MergeTocInfo(entry);
                }
            }
        }
コード例 #13
0
        /// <summary>
        /// This is called to copy the additional content files and build a list of them for the help file
        /// project.
        /// </summary>
        /// <remarks>Note that for wildcard content items, the folders are copied recursively.</remarks>
        private void CopyAdditionalContent()
        {
            Dictionary <string, TocEntryCollection> tocItems = new Dictionary <string, TocEntryCollection>();
            TocEntryCollection parentToc;
            TocEntry           tocEntry, tocFolder;
            FileItemCollection contentItems;
            string             projectPath, source, filename, dirName;

            string[] parts;
            int      part;

            this.ReportProgress(BuildStep.CopyAdditionalContent, "Copying additional content files...");

            if (this.ExecutePlugIns(ExecutionBehaviors.InsteadOf))
            {
                return;
            }

            // A plug-in might add or remove additional content so call
            // them before checking to see if there is anything to copy.
            this.ExecutePlugIns(ExecutionBehaviors.Before);

            if (!project.HasItems(BuildAction.Content) && !project.HasItems(BuildAction.SiteMap))
            {
                this.ReportProgress("No additional content to copy");
                this.ExecutePlugIns(ExecutionBehaviors.After);
                return;
            }

            toc = new TocEntryCollection();
            tocItems.Add(String.Empty, toc);

            // Now copy the content files
            contentItems = new FileItemCollection(project, BuildAction.Content);
            projectPath  = FolderPath.TerminatePath(Path.GetDirectoryName(originalProjectName));

            foreach (FileItem fileItem in contentItems)
            {
                source   = fileItem.Include;
                dirName  = Path.GetDirectoryName(fileItem.Link.ToString().Substring(projectPath.Length));
                filename = Path.Combine(dirName, Path.GetFileName(source));

                if (source.EndsWith(".htm", StringComparison.OrdinalIgnoreCase) ||
                    source.EndsWith(".html", StringComparison.OrdinalIgnoreCase) ||
                    source.EndsWith(".topic", StringComparison.OrdinalIgnoreCase))
                {
                    tocEntry = BuildProcess.GetTocInfo(source);

                    // Exclude the page if so indicated via the item metadata
                    if (fileItem.ExcludeFromToc)
                    {
                        tocEntry.IncludePage = false;
                    }

                    // .topic files get transformed into .html files
                    if (source.EndsWith(".topic", StringComparison.OrdinalIgnoreCase))
                    {
                        filename = Path.ChangeExtension(filename, ".html");
                    }

                    tocEntry.SourceFile      = new FilePath(source, project);
                    tocEntry.DestinationFile = filename;

                    // Figure out where to add the entry
                    parts      = tocEntry.DestinationFile.Split('\\');
                    pathToRoot = String.Empty;
                    parentToc  = toc;

                    for (part = 0; part < parts.Length - 1; part++)
                    {
                        pathToRoot += parts[part] + @"\";

                        // Create place holders if necessary
                        if (!tocItems.TryGetValue(pathToRoot, out parentToc))
                        {
                            tocFolder       = new TocEntry(project);
                            tocFolder.Title = parts[part];

                            if (part == 0)
                            {
                                toc.Add(tocFolder);
                            }
                            else
                            {
                                tocItems[String.Join(@"\", parts, 0, part) + @"\"].Add(tocFolder);
                            }

                            parentToc = tocFolder.Children;
                            tocItems.Add(pathToRoot, parentToc);
                        }
                    }

                    parentToc.Add(tocEntry);

                    if (tocEntry.IncludePage && tocEntry.IsDefaultTopic)
                    {
                        defaultTopic = tocEntry.DestinationFile;
                    }
                }
                else
                {
                    tocEntry = null;
                }

                this.EnsureOutputFoldersExist(dirName);

                foreach (string baseFolder in this.HelpFormatOutputFolders)
                {
                    // If the file contains items that need to be resolved,
                    // it is handled separately.
                    if (tocEntry != null &&
                        (tocEntry.HasLinks || tocEntry.HasCodeBlocks ||
                         tocEntry.NeedsColorizing || tocEntry.HasProjectTags ||
                         source.EndsWith(".topic", StringComparison.OrdinalIgnoreCase)))
                    {
                        // Figure out the path to the root if needed
                        parts      = tocEntry.DestinationFile.Split('\\');
                        pathToRoot = String.Empty;

                        for (part = 0; part < parts.Length - 1; part++)
                        {
                            pathToRoot += "../";
                        }

                        this.ResolveLinksAndCopy(source, baseFolder + filename, tocEntry);
                    }
                    else
                    {
                        this.ReportProgress("{0} -> {1}{2}", source, baseFolder, filename);

                        // All attributes are turned off so that we can delete it later
                        File.Copy(source, baseFolder + filename, true);
                        File.SetAttributes(baseFolder + filename, FileAttributes.Normal);
                    }
                }
            }

            // Remove excluded nodes, merge folder item info into the root
            // nodes, and sort the items.  If a site map isn't defined, this
            // will define the layout of the items.
            toc.RemoveExcludedNodes(null);
            toc.Sort();

            codeColorizer = null;
            sharedContent = null;

            this.ExecutePlugIns(ExecutionBehaviors.After);
        }
コード例 #14
0
        //=====================================================================

        /// <summary>
        /// Create a full-text index from web pages found in the specified file path
        /// </summary>
        /// <param name="filePath">The path containing the files to index</param>
        /// <remarks>Words in the exclusion list, those that are less than three characters long, and anything
        /// starting with a digit will not appear in the index.</remarks>
        public void CreateFullTextIndex(string filePath)
        {
            Dictionary <string, int> wordCounts = new Dictionary <string, int>();

            Encoding enc = Encoding.Default;
            Match    m;

            string content, fileInfo, title;

            string[] words;
            int      rootPathLength;

            if (filePath[filePath.Length - 1] == '\\')
            {
                rootPathLength = filePath.Length;
            }
            else
            {
                rootPathLength = filePath.Length + 1;
            }

            foreach (string name in Directory.EnumerateFiles(filePath, "*.htm?", SearchOption.AllDirectories))
            {
                content = BuildProcess.ReadWithEncoding(name, ref enc);

                // Extract the page title
                m = rePageTitle.Match(content);

                if (!m.Success)
                {
                    title = Path.GetFileNameWithoutExtension(name);
                }
                else
                {
                    title = m.Groups["Title"].Value.Trim();
                }

                // Put some space between tags
                content = content.Replace("><", "> <");

                // Remove script, style sheet, and head blocks as they won't contain any usable keywords.  Pre
                // tags contain code which may or may not be useful but we'll leave them alone for now.
                content = reStripScriptStyleHead.Replace(content, " ");

                // Remove all HTML tags
                content = reStripTags.Replace(content, " ");

                // Decode the text
                content = HttpUtility.HtmlDecode(content);

                // Strip apostrophe suffixes
                content = reStripApos.Replace(content, String.Empty);

                // Condense all runs of whitespace to a single space
                content = reCondenseWS.Replace(content, " ");

                // Convert to lowercase and split text on non-word boundaries
                words = reSplitWords.Split(content.ToLower(lang));

                // We're going to use simple types for the index structure so that we don't have to deploy an
                // assembly to deserialize it.  As such, concatenate the title, filename, and its word count
                // into a string separated by nulls.  Note that file paths are assumed to be relative to the
                // root folder.
                fileInfo = String.Join("\x0", new string[] { title,
                                                             name.Substring(rootPathLength).Replace('\\', '/'),
                                                             words.Length.ToString(CultureInfo.InvariantCulture) });

                wordCounts.Clear();

                // Get a list of all unique words and the number of time that they appear in this file.
                // Exclude words that are less than three characters in length, start with a digit, or
                // are in the common words exclusion list.
                foreach (string word in words)
                {
                    if (word.Length < 3 || Char.IsDigit(word[0]) || exclusionWords.Contains(word))
                    {
                        continue;
                    }

                    // The number of times it occurs helps determine the ranking of the search results
                    if (wordCounts.ContainsKey(word))
                    {
                        wordCounts[word] += 1;
                    }
                    else
                    {
                        wordCounts.Add(word, 1);
                    }
                }

                // Shouldn't happen but just in case, ignore files with no usable words
                if (wordCounts.Keys.Count != 0)
                {
                    fileList.Add(fileInfo);

                    // Add the index information to the word dictionary
                    foreach (string word in wordCounts.Keys)
                    {
                        // For each unique word, we'll track the files in which it occurs and the number
                        // of times it occurs in each file.
                        if (!wordDictionary.ContainsKey(word))
                        {
                            wordDictionary.Add(word, new List <long>());
                        }

                        // Store the file index in the upper part of a 64-bit integer and the word count
                        // in the lower 16-bits.  More room is given to the file count as some builds
                        // contain a large number of topics.
                        wordDictionary[word].Add(((long)(fileList.Count - 1) << 16) +
                                                 (long)(wordCounts[word] & 0xFFFF));
                    }
                }
            }
        }
コード例 #15
0
        /// <summary>
        /// This is used to clean up the MS Help 2 collection files so that
        /// they are ready for use in registering the collection.
        /// </summary>
        private void CleanUpCollectionFiles()
        {
            XmlDocument document;
            XmlNode     node;
            string      extension, toc, iniFile;

            this.ReportProgress("Cleaning up collection files...");

            foreach (string file in Directory.GetFiles(outputFolder,
                                                       project.HtmlHelpName + "*.Hx?"))
            {
                extension = Path.GetExtension(file).ToLower(
                    CultureInfo.InvariantCulture);

                switch (extension)
                {
                case ".hxc":
                    document = BuildProcess.OpenCollectionFile(file);

                    // Remove the compiler options
                    node = document.SelectSingleNode(
                        "HelpCollection/CompilerOptions");
                    if (node != null)
                    {
                        node.ParentNode.RemoveChild(node);
                    }
                    break;

                case ".hxt":
                    // We don't need the whole TOC so recreate it from
                    // this string.
                    toc = this.TransformText(
                        "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n" +
                        "<!DOCTYPE HelpTOC>\r\n" +
                        "<HelpTOC DTDVersion=\"1.0\" LangId=\"{@LangId}\" " +
                        "PluginStyle=\"{@CollectionTocStyle}\" " +
                        "PluginTitle=\"{@HtmlEncHelpTitle}\">\r\n" +
                        "    <HelpTOCNode NodeType=\"TOC\" " +
                        "Url=\"{@HTMLEncHelpName}\" />\r\n" +
                        "</HelpTOC>\r\n");

                    document = new XmlDocument();
                    document.LoadXml(toc);
                    break;

                case ".hxk":
                    document = BuildProcess.OpenCollectionFile(file);
                    break;

                default:
                    // Ignore it (i.e. .HXS)
                    document = null;
                    break;
                }

                if (document != null)
                {
                    document.Save(file);
                }
            }

            this.ReportProgress("Creating H2Reg.ini file...");

            iniFile = outputFolder + project.HtmlHelpName + "_H2Reg.ini";

            if (File.Exists(iniFile))
            {
                File.Delete(iniFile);
            }

            this.TransformTemplate("Help2x_H2Reg.ini", templateFolder,
                                   outputFolder);
            File.Move(outputFolder + "Help2x_H2Reg.ini", iniFile);
        }
コード例 #16
0
        //=====================================================================

        /// <summary>
        /// This performs the requested task
        /// </summary>
        /// <param name="sender">The sender of the event</param>
        /// <param name="e">The event arguments</param>
        private void actionThread_DoWork(object sender, DoWorkEventArgs e)
        {
            ThreadAction action = (ThreadAction)e.Argument;
            string arguments, contentSetupFile;
            int errorCode;

            runningThread = Thread.CurrentThread;

            try
            {
                HelpLibraryManager hlm = new HelpLibraryManager(viewerVersion);

                // Remove old content.  We'll remove it if installing to be sure that the latest copy is
                // installed.
                if(action == ThreadAction.Install || action == ThreadAction.Remove)
                {
                    if(action == ThreadAction.Install)
                        actionThread.ReportProgress(0, (int)ThreadState.RemovingOldContent);
                    else
                        actionThread.ReportProgress(0, (int)ThreadState.RemovingContent);

                    if(viewerVersion.Major == 1)
                        arguments = String.Format(CultureInfo.InvariantCulture,
                            "/product \"{0}\" /version \"{1}\" /locale {2} /uninstall /silent /vendor " +
                            "\"{3}\" /productName \"{4}\" /mediaBookList \"{5}\"",
                            project.CatalogProductId, project.CatalogVersion, project.Language.Name,
                            !String.IsNullOrEmpty(project.VendorName) ? project.VendorName : "Vendor Name",
                            !String.IsNullOrEmpty(project.ProductTitle) ? project.ProductTitle : project.HelpTitle,
                            project.HelpTitle);
                    else
                        arguments = String.Format(CultureInfo.InvariantCulture,
                            "/catalogName \"{0}\" /locale {1} /wait 0 /operation uninstall /vendor \"{2}\" " +
                            "/productName \"{3}\" /bookList \"{4}\" ", catalogName, project.Language.Name,
                            !String.IsNullOrEmpty(project.VendorName) ? project.VendorName : "Vendor Name",
                            !String.IsNullOrEmpty(project.ProductTitle) ? project.ProductTitle : project.HelpTitle,
                            project.HelpTitle);

                    // If there are substitution tags present, have a go at resolving them
                    if(arguments.IndexOf("{@", StringComparison.Ordinal) != -1)
                    {
                        try
                        {
                            var bp = new BuildProcess(project);
                            arguments = bp.SubstitutionTags.TransformText(arguments);
                        }
                        catch(Exception ex)
                        {
                            throw new InvalidOperationException("Unable to transform substitution tags: " +
                                ex.Message, ex);
                        }
                    }

                    // This doesn't have to run as an administrator
                    errorCode = hlm.RunAsNormalUser(arguments, ProcessWindowStyle.Minimized);

                    // Ignore it if not found and we are installing
                    if(errorCode != HelpLibraryManagerException.Success &&
                      (errorCode != HelpLibraryManagerException.NoBooksToInstall || action == ThreadAction.Remove))
                        throw new HelpLibraryManagerException(viewerVersion, errorCode);
                }

                if(action == ThreadAction.Install)
                {
                    // Install the new content
                    actionThread.ReportProgress(0, (int)ThreadState.InstallingContent);

                    // Copy the MSHA file to the required name
                    contentSetupFile = Path.Combine(Path.GetDirectoryName(setupFile), "HelpContentSetup.msha");
                    File.Copy(setupFile, contentSetupFile, true);

                    if(viewerVersion.Major == 1)
                        arguments = String.Format(CultureInfo.InvariantCulture, "/product \"{0}\" " +
                            "/version \"{1}\" /locale {2} /sourceMedia \"{3}\"", project.CatalogProductId,
                            project.CatalogVersion, project.Language.Name, contentSetupFile);
                    else
                        arguments = String.Format(CultureInfo.InvariantCulture, "/catalogName \"{0}\" " +
                            "/locale {1} /wait 0 /operation install /sourceUri \"{2}\"", catalogName,
                            project.Language.Name, contentSetupFile);

                    // Always interactive and must run as administrator.  We can't run silently as we don't have
                    // a signed cabinet file.
                    errorCode = hlm.RunAsAdministrator(arguments, ProcessWindowStyle.Normal);

                    if(errorCode != HelpLibraryManagerException.Success)
                        throw new HelpLibraryManagerException(viewerVersion, errorCode);

                    // Open it if installed successfully
                    action = ThreadAction.OpenCurrent;
                }

                if(action == ThreadAction.OpenCurrent)
                {
                    arguments = null;

                    if(msHelpViewer == null)
                    {
                        msHelpViewer = hlm.HelpViewerPath;

                        if(msHelpViewer == null)
                            msHelpViewer = "ms-xhelp:///?method=page&id=-1";
                        else
                            if(viewerVersion.Major == 2)
                                arguments = "/catalogname \"" + catalogName + "\"";
                    }

                    actionThread.ReportProgress(0, (int)ThreadState.OpeningContent);
                    System.Diagnostics.Process.Start(msHelpViewer, arguments);
                }

                if(action == ThreadAction.OpenContentManager)
                {
                    actionThread.ReportProgress(0, (int)ThreadState.OpeningContentManager);

                    // Can't do anything if the Help Library Manager is not installed
                    if(hlm.HelpLibraryManagerPath == null)
                        throw new HelpLibraryManagerException(viewerVersion,
                            HelpLibraryManagerException.HelpLibraryManagerNotFound);

                    if(viewerVersion.Major == 1)
                        hlm.LaunchInteractive(String.Format(CultureInfo.InvariantCulture,
                            "/product \"{0}\" /version \"{1}\" /locale {2}", project.CatalogProductId,
                            project.CatalogVersion, project.Language.Name));
                    else
                        hlm.LaunchInteractive(String.Format(CultureInfo.InvariantCulture,
                            "/catalogName \"{0}\" /locale {1} /manage", catalogName, project.Language.Name));
                }
            }
            catch(ThreadAbortException)
            {
                // Ignore thread abort exceptions
            }
        }
コード例 #17
0
ファイル: Topic.cs プロジェクト: codemonster234/scbuilder
        /// <summary>
        /// This is used to create the companion file used by the build
        /// component that resolves conceptual links.
        /// </summary>
        /// <param name="folder">The folder in which to place the file</param>
        /// <param name="builder">The build process</param>
        /// <remarks>The file will be named using the ID and a ".xml"
        /// extension.</remarks>
        internal void WriteCompanionFile(string folder, BuildProcess builder)
        {
            string linkElement = String.Empty;

            // MS Help Viewer doesn't support empty place holders so we automatically
            // generate a dummy place holder file for them.
            if(!noFile || (builder.CurrentProject.HelpFileFormat & HelpFileFormat.MSHelpViewer) != 0)
            {
                // Link text is optional
                if(!String.IsNullOrEmpty(linkText))
                    linkElement = String.Format(CultureInfo.InvariantCulture,
                        "    <linkText>{0}</linkText>\r\n", HttpUtility.HtmlEncode(linkText));

                // It's small enough that we'll just write it out as a string
                // rather than using an XML writer.
                using(StreamWriter sw = new StreamWriter(Path.Combine(folder, this.Id + ".cmp.xml"),
                  false, Encoding.UTF8))
                {
                    sw.WriteLine(
                        "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n" +
                        "<metadata>\r\n" +
                        "  <topic id=\"{0}\">\r\n" +
                        "    <title>{1}</title>\r\n" +
                        "{2}" +
                        "  </topic>\r\n" +
                        "</metadata>\r\n", this.Id, HttpUtility.HtmlEncode(this.DisplayTitle), linkElement);
                }
            }

            foreach(Topic t in subtopics)
                t.WriteCompanionFile(folder, builder);
        }
コード例 #18
0
        /// <summary>
        /// This is used to transform a *.topic file into a *.html file using an XSLT transformation based on the
        /// presentation style.
        /// </summary>
        /// <param name="sourceFile">The source topic filename</param>
        private void XslTransform(string sourceFile)
        {
            TocEntry           tocInfo;
            XmlReader          reader = null;
            XmlWriter          writer = null;
            XsltSettings       settings;
            XmlReaderSettings  readerSettings;
            XmlWriterSettings  writerSettings;
            Encoding           enc = Encoding.Default;
            FileItemCollection transforms;
            string             content;

            string sourceStylesheet, destFile = Path.ChangeExtension(sourceFile, ".html");

            try
            {
                readerSettings               = new XmlReaderSettings();
                readerSettings.CloseInput    = true;
                readerSettings.DtdProcessing = DtdProcessing.Parse;

                // Create the transform on first use
                if (xslTransform == null)
                {
                    transforms = new FileItemCollection(project, BuildAction.TopicTransform);

                    if (transforms.Count != 0)
                    {
                        if (transforms.Count > 1)
                        {
                            this.ReportWarning("BE0011", "Multiple topic transformations found.  Using '{0}'",
                                               transforms[0].FullPath);
                        }

                        sourceStylesheet = transforms[0].FullPath;
                    }
                    else
                    {
                        sourceStylesheet = templateFolder + project.PresentationStyle + ".xsl";
                    }

                    xslStylesheet = workingFolder + Path.GetFileName(sourceStylesheet);
                    tocInfo       = BuildProcess.GetTocInfo(sourceStylesheet);

                    // The style sheet may contain shared content items so we must resolve it this way rather
                    // than using TransformTemplate.
                    this.ResolveLinksAndCopy(sourceStylesheet, xslStylesheet, tocInfo);

                    xslTransform = new XslCompiledTransform();
                    settings     = new XsltSettings(true, true);
                    xslArguments = new XsltArgumentList();

                    xslTransform.Load(XmlReader.Create(xslStylesheet, readerSettings), settings,
                                      new XmlUrlResolver());
                }

                this.ReportProgress("Applying XSL transformation '{0}' to '{1}'.", xslStylesheet, sourceFile);

                reader                     = XmlReader.Create(sourceFile, readerSettings);
                writerSettings             = xslTransform.OutputSettings.Clone();
                writerSettings.CloseOutput = true;
                writerSettings.Indent      = false;

                writer = XmlWriter.Create(destFile, writerSettings);

                xslArguments.Clear();
                xslArguments.AddParam("pathToRoot", String.Empty, pathToRoot);
                xslTransform.Transform(reader, xslArguments, writer);
            }
            catch (Exception ex)
            {
                throw new BuilderException("BE0017", String.Format(CultureInfo.CurrentCulture,
                                                                   "Unexpected error using '{0}' to transform additional content file '{1}' to '{2}'.  The " +
                                                                   "error is: {3}\r\n{4}", xslStylesheet, sourceFile, destFile, ex.Message,
                                                                   (ex.InnerException == null) ? String.Empty : ex.InnerException.Message));
            }
            finally
            {
                if (reader != null)
                {
                    reader.Close();
                }

                if (writer != null)
                {
                    writer.Flush();
                    writer.Close();
                }
            }

            // The source topic file is deleted as the transformed file takes its place
            File.Delete(sourceFile);

            // <span> and <script> tags cannot be self-closing if empty.  The template may contain them correctly
            // but when written out as XML, they get converted to self-closing tags which breaks them.  To fix
            // them, convert them to full start and close tags.
            content = BuildProcess.ReadWithEncoding(destFile, ref enc);
            content = reSpanScript.Replace(content, "<$1$2></$1>");

            // An XSL transform might have added tags and include items that need replacing so run it through
            // those options if needed.
            tocInfo = BuildProcess.GetTocInfo(destFile);

            // Expand <code> tags if necessary
            if (tocInfo.HasCodeBlocks)
            {
                content = reCodeBlock.Replace(content, codeBlockMatchEval);
            }

            // Colorize <pre> tags if necessary
            if (tocInfo.NeedsColorizing || tocInfo.HasCodeBlocks)
            {
                // Initialize code colorizer on first use
                if (codeColorizer == null)
                {
                    codeColorizer = new CodeColorizer(ComponentUtilities.ToolsFolder +
                                                      @"PresentationStyles\Colorizer\highlight.xml", ComponentUtilities.ToolsFolder +
                                                      @"PresentationStyles\Colorizer\highlight.xsl");
                }

                // Set the path the "Copy" image
                codeColorizer.CopyImageUrl = pathToRoot + "icons/CopyCode.gif";

                // Colorize it and replace the "Copy" literal text with the shared content include item so that
                // it gets localized.
                content = codeColorizer.ProcessAndHighlightText(content);
                content = content.Replace(codeColorizer.CopyText + "</span", "<include item=\"copyCode\"/></span");
                tocInfo.HasProjectTags = true;
            }

            // Use a regular expression to find and replace all tags with cref attributes with a link to the help
            // file content.  This needs to happen after the code block processing as they may contain <see> tags
            // that need to be resolved.
            if (tocInfo.HasLinks || tocInfo.HasCodeBlocks)
            {
                content = reResolveLinks.Replace(content, linkMatchEval);
            }

            // Replace project option tags with project option values
            if (tocInfo.HasProjectTags)
            {
                // Project tags can be nested
                while (reProjectTags.IsMatch(content))
                {
                    content = reProjectTags.Replace(content, fieldMatchEval);
                }

                // Shared content items can be nested
                while (reSharedContent.IsMatch(content))
                {
                    content = reSharedContent.Replace(content, contentMatchEval);
                }
            }

            // Write the file back out with the appropriate encoding
            using (StreamWriter sw = new StreamWriter(destFile, false, enc))
            {
                sw.Write(content);
            }
        }
コード例 #19
0
        /// <summary>
        /// This method is used to initialize the plug-in at the start of the
        /// build process.
        /// </summary>
        /// <param name="buildProcess">A reference to the current build
        /// process.</param>
        /// <param name="configuration">The configuration data that the plug-in
        /// should use to initialize itself.</param>
        public void Initialize(BuildProcess buildProcess, XPathNavigator configuration)
        {
            builder = buildProcess;

            builder.ReportProgress("{0} Version {1}\r\n{2}", this.Name, this.Version, this.Copyright);

            exclusionList = new List<string>();
        }
コード例 #20
0
        //=====================================================================
        /// <summary>
        /// This is used to start the background build process from which
        /// we will get the information to load the tree view.
        /// </summary>
        /// <param name="sender">The sender of the event</param>
        /// <param name="e">The event arguments</param>
        private void ApiFilterEditorDlg_Load(object sender, EventArgs e)
        {
            string tempPath;

            tvApiList.Enabled = splitContainer.Panel2.Enabled =
                btnReset.Enabled = false;

            try
            {
                // Clone the project for the build and adjust its properties
                // for our needs.
                tempProject = new SandcastleProject(apiFilter.Project, true);

                // The temporary project resides in the same folder as the
                // current project (by filename only, it isn't saved) to
                // maintain relative paths.  However, build output is stored
                // in a temporary folder and it keeps the intermediate files.
                tempProject.CleanIntermediates = false;
                tempPath = Path.GetTempFileName();

                File.Delete(tempPath);
                tempPath = Path.Combine(Path.GetDirectoryName(tempPath),
                    "SHFBPartialBuild");

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

                tempProject.OutputPath = tempPath;

                buildProcess = new BuildProcess(tempProject, true);

                // We must suppress the current API filter for this build
                buildProcess.SuppressApiFilter = true;

                buildProcess.BuildStepChanged +=
                    new EventHandler<BuildProgressEventArgs>(
                    buildProcess_BuildStepChanged);
                buildProcess.BuildProgress +=
                    new EventHandler<BuildProgressEventArgs>(
                    buildProcess_BuildProgress);

                buildThread = new Thread(new ThreadStart(buildProcess.Build));
                buildThread.Name = "API fitler partial build thread";
                buildThread.IsBackground = true;
                buildThread.Start();
            }
            catch(Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(ex.ToString());
                MessageBox.Show("Unable to build project to obtain " +
                    "API information.  Error: " + ex.Message,
                    Constants.AppName, MessageBoxButtons.OK,
                    MessageBoxIcon.Error);
            }
        }
コード例 #21
0
        /// <inheritdoc/>
        public void Initialize(BuildProcess buildProcess, XPathNavigator configuration)
        {
            builder = buildProcess;

            var metadata = (HelpFileBuilderPlugInExportAttribute)this.GetType().GetCustomAttributes(
                typeof(HelpFileBuilderPlugInExportAttribute), false).First();

            builder.ReportProgress("{0} Version {1}\r\n{2}", metadata.Id, metadata.Version, metadata.Copyright);
        }
コード例 #22
0
ファイル: DbcsFixPlugIn.cs プロジェクト: modulexcite/SHFB-1
        /// <summary>
        /// This method is used to initialize the plug-in at the start of the build process
        /// </summary>
        /// <param name="buildProcess">A reference to the current build process</param>
        /// <param name="configuration">The configuration data that the plug-in should use to initialize itself</param>
        public void Initialize(BuildProcess buildProcess, XPathNavigator configuration)
        {
            XPathNavigator root, node;

            builder = buildProcess;

            var metadata = (HelpFileBuilderPlugInExportAttribute)this.GetType().GetCustomAttributes(
                typeof(HelpFileBuilderPlugInExportAttribute), false).First();

            builder.ReportProgress("{0} Version {1}\r\n{2}", metadata.Id, metadata.Version, metadata.Copyright);

            root = configuration.SelectSingleNode("configuration");

            if(root.IsEmptyElement)
                throw new BuilderException("DFP0001", "The DBCS Fix plug-in has not been configured yet");

            node = root.SelectSingleNode("sbAppLocale");

            if(node != null)
                sbAppLocalePath = node.GetAttribute("path", String.Empty).Trim();

            if(String.IsNullOrWhiteSpace(sbAppLocalePath))
            {
                builder.ReportWarning("DFP0002", "A path to the Steel Bytes App Locale tool was not specified " +
                    "and it will not be used for this build.");
            }
            else
            {
                // If relative, the path is relative to the project folder
                sbAppLocalePath = FilePath.RelativeToAbsolutePath(builder.ProjectFolder,
                    builder.TransformText(sbAppLocalePath));

                if(!File.Exists(sbAppLocalePath))
                    throw new BuilderException("DFP0003", "Unable to locate SBAppLocale tool at " + sbAppLocalePath);
            }

            // If not building HTML Help 1, there's nothing to do
            if((builder.CurrentProject.HelpFileFormat & HelpFileFormats.HtmlHelp1) == 0)
            {
                executionPoints.Clear();
                builder.ReportWarning("DFP0007", "An HTML Help 1 file is not being built.  This plug-in will " +
                    "not be ran.");
            }
        }
コード例 #23
0
        /// <summary>
        /// This method is used to initialize the plug-in at the start of the build process
        /// </summary>
        /// <param name="buildProcess">A reference to the current build process</param>
        /// <param name="configuration">The configuration data that the plug-in should use to initialize itself</param>
        /// <exception cref="BuilderException">This is thrown if the plug-in configuration is not valid</exception>
        public void Initialize(BuildProcess buildProcess, XPathNavigator configuration)
        {
            XPathNavigator root, msHelpViewer;
            string value;

            builder = buildProcess;

            var metadata = (HelpFileBuilderPlugInExportAttribute)this.GetType().GetCustomAttributes(
                typeof(HelpFileBuilderPlugInExportAttribute), false).First();

            builder.ReportProgress("{0} Version {1}\r\n{2}", metadata.Id, metadata.Version, metadata.Copyright);

            root = configuration.SelectSingleNode("configuration");
            value = root.GetAttribute("deleteAfterDeploy", String.Empty);

            if(!String.IsNullOrEmpty(value))
                deleteAfterDeploy = Convert.ToBoolean(value, CultureInfo.InvariantCulture);

            if(root.IsEmptyElement)
                throw new BuilderException("ODP0001", "The Output Deployment plug-in has not been " +
                    "configured yet");

            deployHelp1 = DeploymentLocation.FromXPathNavigator(root, "help1x");
            deployHelp2 = DeploymentLocation.FromXPathNavigator(root, "help2x");
            deployHelpViewer = DeploymentLocation.FromXPathNavigator(root, "helpViewer");
            deployWebsite = DeploymentLocation.FromXPathNavigator(root, "website");
            deployOpenXml = DeploymentLocation.FromXPathNavigator(root, "openXml");

            msHelpViewer = root.SelectSingleNode("deploymentLocation[@id='helpViewer']");

            if(msHelpViewer == null || !Boolean.TryParse(msHelpViewer.GetAttribute("renameMSHA",
              String.Empty).Trim(), out renameMSHA))
                renameMSHA = false;

            // At least one deployment location must be defined
            if(deployHelp1.Location == null && deployHelp2.Location == null &&
              deployHelpViewer.Location == null && deployWebsite.Location == null && deployOpenXml.Location == null)
                throw new BuilderException("ODP0002", "The output deployment plug-in must have at least " +
                    "one configured deployment location");

            // Issue a warning if the deployment location is null and the associated help file format is active
            if(deployHelp1.Location == null &&
              (builder.CurrentProject.HelpFileFormat & HelpFileFormats.HtmlHelp1) != 0)
                builder.ReportWarning("ODP0003", "HTML Help 1 will be generated but not deployed due to " +
                    "missing deployment location information");

            if(deployHelp2.Location == null &&
              (builder.CurrentProject.HelpFileFormat & HelpFileFormats.MSHelp2) != 0)
                builder.ReportWarning("ODP0003", "MS Help 2 will be generated but not deployed due to " +
                    "missing deployment location information");

            if(deployHelpViewer.Location == null &&
              (builder.CurrentProject.HelpFileFormat & HelpFileFormats.MSHelpViewer) != 0)
                builder.ReportWarning("ODP0003", "MS Help Viewer will be generated but not deployed due " +
                    "to missing deployment location information");

            if(deployWebsite.Location == null &&
              (builder.CurrentProject.HelpFileFormat & HelpFileFormats.Website) != 0)
                builder.ReportWarning("ODP0003", "Website will be generated but not deployed due to " +
                    "missing deployment location information");

            if(deployOpenXml.Location == null &&
              (builder.CurrentProject.HelpFileFormat & HelpFileFormats.OpenXml) != 0)
                builder.ReportWarning("ODP0003", "Open XML will be generated but not deployed due to " +
                    "missing deployment location information");
        }
コード例 #24
0
        //=====================================================================

        /// <summary>
        /// This is used to copy the additional content token, image, and topic files to the build folder
        /// </summary>
        /// <param name="builder">The build process</param>
        /// <remarks>This will copy the code snippet file if specified, save token information to a shared
        /// content file called <strong>_Tokens_.xml</strong> in the build process's working folder, copy the
        /// image files to the <strong>.\media</strong> folder in the build process's working folder, save the
        /// media map to a file called <strong>_MediaContent_.xml</strong> in the build process's working folder,
        /// and save the topic files to the <strong>.\ddueXml</strong> folder in the build process's working
        /// folder.  The topic files will have their content wrapped in a <c>&lt;topic&gt;</c> tag if needed and
        /// will be named using their <see cref="Topic.Id" /> value.</remarks>
        public void CopyContentFiles(BuildProcess builder)
        {
            string folder;
            bool missingFile = false;

            builder.ReportProgress("Copying standard token shared content file...");
            builder.SubstitutionTags.TransformTemplate("HelpFileBuilderTokens.tokens", builder.TemplateFolder,
                builder.WorkingFolder);

            builder.ReportProgress("Checking for other token files...");

            foreach(var tokenFile in this.tokenFiles)
                if(!File.Exists(tokenFile.FullPath))
                {
                    missingFile = true;
                    builder.ReportProgress("    Missing token file: {0}", tokenFile.FullPath);
                }
                else
                {
                    builder.ReportProgress("    {0} -> {1}", tokenFile.FullPath,
                        Path.Combine(builder.WorkingFolder, Path.GetFileName(tokenFile.FullPath)));
                    builder.SubstitutionTags.TransformTemplate(Path.GetFileName(tokenFile.FullPath),
                        Path.GetDirectoryName(tokenFile.FullPath), builder.WorkingFolder);
                }

            if(missingFile)
                throw new BuilderException("BE0052", "One or more token files could not be found");

            builder.ReportProgress("Checking for code snippets files...");

            foreach(var snippetsFile in this.codeSnippetFiles)
                if(!File.Exists(snippetsFile.FullPath))
                {
                    missingFile = true;
                    builder.ReportProgress("    Missing code snippets file: {0}", snippetsFile.FullPath);
                }
                else
                    builder.ReportProgress("    Found {0}", snippetsFile.FullPath);

            if(missingFile)
                throw new BuilderException("BE0053", "One or more code snippets files could not be found");

            // Save the image info to a shared content file and copy the image files to the working folder
            folder = builder.WorkingFolder + "media";

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

            // Create the build process's help format output folders too if needed
            builder.EnsureOutputFoldersExist("media");

            builder.ReportProgress("Copying images and creating the media map file...");

            // Copy all image project items and create the content file
            this.SaveImageSharedContent(builder.WorkingFolder + "_MediaContent_.xml", folder, builder);

            // Copy the topic files
            folder = builder.WorkingFolder + "ddueXml";

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

            builder.ReportProgress("Generating conceptual topic files");

            // Get the list of valid framework namespaces for the referenced namespace search in each topic
            HashSet<string> validNamespaces = new HashSet<string>(Directory.EnumerateFiles(builder.FrameworkReflectionDataFolder,
                "*.xml", SearchOption.AllDirectories).Select(f => Path.GetFileNameWithoutExtension(f)));

            // Create topic files
            foreach(TopicCollection tc in topics)
            {
                tc.Load();
                tc.GenerateConceptualTopics(folder, builder, validNamespaces);
            }
        }
コード例 #25
0
ファイル: Topic.cs プロジェクト: aeagle/SHFB
        /// <summary>
        /// Write out the topic metadata
        /// </summary>
        /// <param name="writer">The writer to which the metadata is written</param>
        /// <param name="builder">The build process</param>
        /// <remarks>This will recursively write out metadata for sub-topics
        /// as well.</remarks>
        internal void WriteMetadata(XmlWriter writer, BuildProcess builder)
        {
            // MS Help Viewer doesn't support empty place holders so we automatically generate a dummy place
            // holder file for them.
            if(!noFile || (builder.CurrentProject.HelpFileFormat & HelpFileFormats.MSHelpViewer) != 0)
            {
                writer.WriteStartElement("topic");
                writer.WriteAttributeString("id", this.Id);
                writer.WriteAttributeString("revisionNumber",
                    this.RevisionNumber.ToString(CultureInfo.InvariantCulture));

                // Write out the help file version project property value
                writer.WriteStartElement("item");
                writer.WriteAttributeString("id", "PBM_FileVersion");
                writer.WriteValue(builder.SubstitutionTags.TransformText(builder.CurrentProject.HelpFileVersion));
                writer.WriteEndElement();

                // If no title is specified, use the display title
                writer.WriteStartElement("title");

                if(!String.IsNullOrEmpty(title))
                    writer.WriteString(title);
                else
                    writer.WriteString(this.DisplayTitle);

                writer.WriteEndElement();

                // TOC title is optional
                if(!String.IsNullOrEmpty(tocTitle))
                    writer.WriteElementString("tableOfContentsTitle", tocTitle);

                // Add topic-specific index keywords
                foreach(MSHelpKeyword kw in keywords)
                {
                    writer.WriteStartElement("keyword");
                    writer.WriteAttributeString("index", kw.Index);

                    // Replace tags with their project property value
                    writer.WriteValue(builder.SubstitutionTags.TransformText(kw.Term));

                    writer.WriteEndElement();
                }

                writer.WriteEndElement();   // </topic>
            }

            // Write metadata for sub-topics too
            foreach(Topic t in subtopics)
                t.WriteMetadata(writer, builder);
        }
コード例 #26
0
        /// <summary>
        /// Write the image reference collection to a map file ready for use by <strong>BuildAssembler</strong>
        /// </summary>
        /// <param name="filename">The file to which the image reference collection is saved</param>
        /// <param name="imagePath">The path to which the image files should be copied</param>
        /// <param name="builder">The build process</param>
        /// <remarks>Images with their <see cref="ImageReference.CopyToMedia" /> property set to true are copied
        /// to the media folder immediately.</remarks>
        public void SaveImageSharedContent(string filename, string imagePath, BuildProcess builder)
        {
            XmlWriterSettings settings = new XmlWriterSettings();
            XmlWriter writer = null;
            string destFile;

            builder.EnsureOutputFoldersExist("media");

            try
            {
                settings.Indent = true;
                settings.CloseOutput = true;
                writer = XmlWriter.Create(filename, settings);

                writer.WriteStartDocument();

                // There are normally some attributes on this element but they aren't used by Sandcastle so we'll
                // ignore them.
                writer.WriteStartElement("stockSharedContentDefinitions");

                foreach(var ir in imageFiles)
                {
                    writer.WriteStartElement("item");
                    writer.WriteAttributeString("id", ir.Id);
                    writer.WriteStartElement("image");

                    // The art build component assumes everything is in a single, common folder.  The build
                    // process will ensure that happens.  As such, we only need the filename here.
                    writer.WriteAttributeString("file", ir.Filename);

                    if(!String.IsNullOrEmpty(ir.AlternateText))
                    {
                        writer.WriteStartElement("altText");
                        writer.WriteValue(ir.AlternateText);
                        writer.WriteEndElement();
                    }

                    writer.WriteEndElement();   // </image>
                    writer.WriteEndElement();   // </item>

                    destFile = Path.Combine(imagePath, ir.Filename);

                    if(File.Exists(destFile))
                        builder.ReportWarning("BE0010", "Image file '{0}' already exists.  It will be replaced " +
                            "by '{1}'.", destFile, ir.FullPath);

                    builder.ReportProgress("    {0} -> {1}", ir.FullPath, destFile);

                    // The attributes are set to Normal so that it can be deleted after the build
                    File.Copy(ir.FullPath, destFile, true);
                    File.SetAttributes(destFile, FileAttributes.Normal);

                    // Copy it to the output media folders if CopyToMedia is true
                    if(ir.CopyToMedia)
                        foreach(string baseFolder in builder.HelpFormatOutputFolders)
                        {
                            destFile = Path.Combine(baseFolder + "media", ir.Filename);

                            builder.ReportProgress("    {0} -> {1} (Always copied)", ir.FullPath, destFile);

                            File.Copy(ir.FullPath, destFile, true);
                            File.SetAttributes(destFile, FileAttributes.Normal);
                        }
                }

                writer.WriteEndElement();   // </stockSharedContentDefinitions>
                writer.WriteEndDocument();
            }
            finally
            {
                if(writer != null)
                    writer.Close();
            }
        }
コード例 #27
0
ファイル: MainForm.cs プロジェクト: armin-bauer/SHFB
        /// <summary>
        /// Build the help file using the current project settings
        /// </summary>
        /// <param name="sender">The sender of the event</param>
        /// <param name="e">The event arguments</param>
        private async void miBuildProject_Click(object sender, EventArgs e)
        {
            if(project == null || !this.SaveBeforeBuild())
                return;

            miClearOutput_Click(miBuildProject, e);
            this.SetUIEnabledState(false);
            Application.DoEvents();

            StatusBarTextProvider.InitializeProgressBar(0, (int)BuildStep.Completed, "Building help file");

            try
            {
                cancellationTokenSource = new CancellationTokenSource();

                buildProcess = new BuildProcess(project)
                {
                    ProgressReportProvider = new Progress<BuildProgressEventArgs>(buildProcess_ReportProgress),
                    CancellationToken = cancellationTokenSource.Token,
                };

                await Task.Run(() => buildProcess.Build(), cancellationTokenSource.Token);
            }
            finally
            {
                if(cancellationTokenSource != null)
                {
                    cancellationTokenSource.Dispose();
                    cancellationTokenSource = null;
                }

                StatusBarTextProvider.ResetProgressBar();
                this.SetUIEnabledState(true);
                outputWindow.LogFile = buildProcess.LogFilename;

                if(buildProcess.CurrentBuildStep == BuildStep.Completed && Settings.Default.OpenHelpAfterBuild)
                    miViewHelpFile.PerformClick();

                buildProcess = null;
            }
        }
コード例 #28
0
 /// <summary>
 /// This is used to create the conceptual content build configuration files
 /// </summary>
 /// <param name="builder">The build process</param>
 /// <remarks>This will create the companion files used to resolve conceptual links and the
 /// <strong>_ContentMetadata_.xml</strong> configuration file.  It will also merge the conceptual topics
 /// into the BuildAssembler manifest file.</remarks>
 public void CreateConfigurationFiles(BuildProcess builder)
 {
     this.CreateCompanionFiles(builder);
     this.CreateContentMetadata(builder);
     this.MergeConceptualManifest(builder);
 }
コード例 #29
0
        /// <summary>
        /// This method is used to initialize the plug-in at the start of the build process
        /// </summary>
        /// <param name="buildProcess">A reference to the current build process</param>
        /// <param name="configuration">The configuration data that the plug-in should use to initialize itself</param>
        public void Initialize(BuildProcess buildProcess, XPathNavigator configuration)
        {
            builder = buildProcess;

            var metadata = (HelpFileBuilderPlugInExportAttribute)this.GetType().GetCustomAttributes(
                typeof(HelpFileBuilderPlugInExportAttribute), false).First();

            builder.ReportProgress("{0} Version {1}\r\n{2}\r\n    This build will only include additional " +
                "content items.", metadata.Id, metadata.Version, metadata.Copyright);

            if(!builder.CurrentProject.HasItems(BuildAction.ContentLayout) &&
              !builder.CurrentProject.HasItems(BuildAction.SiteMap) &&
              !builder.CurrentProject.HasItems(BuildAction.Content))
                throw new BuilderException("ACP0001", "The Additional Content Only plug-in requires a " +
                    "conceptual content layout file, a site map file, or content items in the project.");
        }
コード例 #30
0
        /// <summary>
        /// This is used to create the companion files used to resolve conceptual links
        /// </summary>
        /// <param name="builder">The build process</param>
        private void CreateCompanionFiles(BuildProcess builder)
        {
            string destFolder = builder.WorkingFolder + "xmlComp\\";

            builder.ReportProgress("    Companion files");

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

            foreach(TopicCollection tc in topics)
                foreach(Topic t in tc)
                    t.WriteCompanionFile(destFolder, builder);
        }
コード例 #31
0
        /// <summary>
        /// This method is used to initialize the plug-in at the start of the
        /// build process.
        /// </summary>
        /// <param name="buildProcess">A reference to the current build
        /// process.</param>
        /// <param name="configuration">The configuration data that the plug-in
        /// should use to initialize itself.</param>
        public void Initialize(BuildProcess buildProcess,
          XPathNavigator configuration)
        {
            builder = buildProcess;

            builder.ReportProgress("{0} Version {1}\r\n{2}\r\n",
                this.Name, this.Version, this.Copyright);

            expressions = new List<string>();

            foreach(XPathNavigator nav in configuration.Select(
              "configuration/expressions/expression"))
                expressions.Add(nav.InnerXml);

            if(expressions.Count == 0)
                throw new BuilderException("XRF0001", "No queries have been " +
                    "defined for the XPath Reflection File Filter plug-in");
        }
コード例 #32
0
        /// <summary>
        /// Create the content metadata file
        /// </summary>
        /// <param name="builder">The build process</param>
        /// <remarks>The content metadata file contains metadata information for each topic such as its title,
        /// table of contents title, help attributes, and index keywords.  Help attributes are a combination
        /// of the project-level help attributes and any parsed from the topic file.  Any replacement tags in
        /// the token values will be replaced with the appropriate project values.
        /// 
        /// <p/>A true MAML version of this file contains several extra attributes.  Since Sandcastle doesn't use
        /// them, I'm not going to waste time adding them.  The only stuff written is what is required by
        /// Sandcastle.  In addition, I'm putting the <c>title</c> and <c>PBM_FileVersion</c> item elements in
        /// here rather than use the separate companion files.  They all end up in the metadata section of the
        /// topic being built so this saves having two extra components in the configuration that do the same
        /// thing with different files.</remarks>
        private void CreateContentMetadata(BuildProcess builder)
        {
            XmlWriterSettings settings = new XmlWriterSettings();
            XmlWriter writer = null;

            builder.ReportProgress("    _ContentMetadata_.xml");

            try
            {
                settings.Indent = true;
                settings.CloseOutput = true;
                writer = XmlWriter.Create(builder.WorkingFolder + "_ContentMetadata_.xml", settings);

                writer.WriteStartDocument();
                writer.WriteStartElement("metadata");

                // Write out each topic and all of its sub-topics
                foreach(TopicCollection tc in topics)
                    foreach(Topic t in tc)
                        t.WriteMetadata(writer, builder);

                writer.WriteEndElement();   // </metadata>
                writer.WriteEndDocument();
            }
            finally
            {
                if(writer != null)
                    writer.Close();
            }
        }
コード例 #33
0
        /// <summary>
        /// This is used to determine the state of the help content and set the form options when a help viewer
        /// version is selected.
        /// </summary>
        /// <param name="sender">The sender of the event</param>
        /// <param name="e">The event arguments</param>
        private void cboHelpViewerVersion_SelectedIndexChanged(object sender, EventArgs e)
        {
            txtInfo.Text = null;

            grpOptions.Enabled = rbInstall.Enabled = true;
            lastVersionSelected = cboHelpViewerVersion.SelectedIndex;

            // If there are substitution tags present, have a go at resolving them
            if(helpFilePath.IndexOf("{@", StringComparison.Ordinal) != -1)
            {
                try
                {
                    var bp = new SandcastleBuilder.Utils.BuildEngine.BuildProcess(project);
                    helpFilePath = bp.SubstitutionTags.TransformText(helpFilePath);
                    setupFile = Path.ChangeExtension(helpFilePath, ".msha");
                }
                catch
                {
                    // Ignore errors
                    txtInfo.AppendText("The help filename appears to contain substitution tags but they could " +
                        "not be resolved to determine the actual file to use for installation.  Building " +
                        "website output and viewing it can be used to work around this issue.\r\n\r\n");
                    rbInstall.Enabled = false;
                }
            }

            if(rbInstall.Enabled && (!File.Exists(helpFilePath) || !File.Exists(setupFile)))
            {
                txtInfo.AppendText("A copy of the help file does not appear to exist yet.  It may need to be built.\r\n\r\n");
                rbInstall.Enabled = false;
            }

            try
            {
                viewerVersion = new Version((string)cboHelpViewerVersion.SelectedItem);

                HelpLibraryManager hlm = new HelpLibraryManager(viewerVersion);

                // Can't do anything if the Help Library Manager is not installed
                if(hlm.HelpLibraryManagerPath == null)
                    throw new HelpLibraryManagerException(viewerVersion,
                        HelpLibraryManagerException.HelpLibraryManagerNotFound);

                // Can't do anything if the Help Library Manager is already running
                if(Process.GetProcessesByName(Path.GetFileNameWithoutExtension(hlm.HelpLibraryManagerPath)).Length > 0)
                    throw new HelpLibraryManagerException(viewerVersion,
                        HelpLibraryManagerException.HelpLibraryManagerAlreadyRunning);

                // Can't do anything if the local store is not initialized
                if(!hlm.LocalStoreInitialized)
                    throw new HelpLibraryManagerException(viewerVersion,
                        HelpLibraryManagerException.LocalStoreNotInitialized);

                if(hlm.HelpContentFileInstalled(helpFilePath))
                    rbOpenCurrent.Enabled = rbRemove.Enabled = true;
                else
                {
                    txtInfo.AppendText("The help file does not appear to be installed yet.\r\n");
                    rbOpenCurrent.Enabled = rbRemove.Enabled = false;
                }
            }
            catch(Exception ex)
            {
                txtInfo.AppendText("Problem: " + ex.Message + "\r\n");
                rbOpenCurrent.Enabled = rbRemove.Enabled = false;
            }

            if(rbOpenCurrent.Enabled)
                rbOpenCurrent.Checked = true;
            else
                if(rbInstall.Enabled)
                    rbInstall.Checked = true;
                else
                    rbLaunchContentManager.Checked = true;

            if(!rbOpenCurrent.Enabled && !rbInstall.Enabled && !rbRemove.Enabled)
                txtInfo.AppendText("\r\nNo action can be taken with the help content.");

            // Determine the catalog name here as it's used in a lot of places and varies by version if not
            // defined in the project.
            catalogName = !String.IsNullOrWhiteSpace(project.CatalogName) ? project.CatalogName :
                HelpLibraryManager.DefaultCatalogName(viewerVersion);

            // If it looks like a default value, warn the user if it doesn't match.  It may need to be cleared.
            if(!String.IsNullOrWhiteSpace(project.CatalogName) && project.CatalogName.StartsWith("VisualStudio",
              StringComparison.Ordinal) && project.CatalogName != HelpLibraryManager.DefaultCatalogName(viewerVersion))
                txtInfo.AppendText("\r\n\r\nWARNING:  The project's catalog name property is set to '" +
                    project.CatalogName + "' which does not match the default catalog name for the selected " +
                    "version of the help viewer.  If necessary, clear the catalog name property value.");
        }
コード例 #34
0
        /// <summary>
        /// Merge the conceptual topic IDs into the BuildAssembler manifest file.
        /// </summary>
        /// <param name="builder">The build process</param>
        private void MergeConceptualManifest(BuildProcess builder)
        {
            XmlWriterSettings settings = new XmlWriterSettings();
            XmlWriter writer = null;
            string conceptualManifest = builder.WorkingFolder + "ConceptualManifest.xml",
                referenceManifest = builder.WorkingFolder + "manifest.xml";

            builder.ReportProgress("    Merging topic IDs into manifest.xml");

            try
            {
                settings.Indent = true;
                settings.CloseOutput = true;
                writer = XmlWriter.Create(conceptualManifest, settings);

                writer.WriteStartDocument();
                writer.WriteStartElement("topics");

                foreach(TopicCollection tc in topics)
                    foreach(Topic t in tc)
                        t.WriteManifest(writer, builder);

                if(File.Exists(referenceManifest))
                    foreach(var topic in ComponentUtilities.XmlStreamAxis(referenceManifest, "topic"))
                    {
                        writer.WriteStartElement("topic");

                        foreach(var attr in topic.Attributes())
                            writer.WriteAttributeString(attr.Name.LocalName, attr.Value);

                        writer.WriteEndElement();
                    }

                writer.WriteEndElement();   // </topics>
                writer.WriteEndDocument();
            }
            finally
            {
                if(writer != null)
                    writer.Close();

                if(File.Exists(referenceManifest))
                    File.Copy(referenceManifest, Path.ChangeExtension(referenceManifest, "old"), true);

                File.Copy(conceptualManifest, referenceManifest, true);
                File.Delete(conceptualManifest);
            }
        }
コード例 #35
0
ファイル: Topic.cs プロジェクト: codemonster234/scbuilder
        /// <summary>
        /// Write out the <b>BuildAssembler</b> manifest entry
        /// </summary>
        /// <param name="writer">The XML writer to which the entry is written</param>
        /// <param name="builder">The build process</param>
        /// <remarks>This will recursively write out entries for sub-topics
        /// as well.</remarks>
        internal void WriteManifest(XmlWriter writer, BuildProcess builder)
        {
            // MS Help Viewer doesn't support empty place holders so we automatically
            // generate a dummy place holder file for them.  Don't add an entry for
            // raw HTML files.
            if((!noFile && topicFile.DocumentType != DocumentType.Html) ||
              (noFile && (builder.CurrentProject.HelpFileFormat & HelpFileFormat.MSHelpViewer) != 0))
            {
                writer.WriteStartElement("topic");
                writer.WriteAttributeString("id", this.Id);
                writer.WriteEndElement();
            }

            foreach(Topic t in subtopics)
                t.WriteManifest(writer, builder);
        }
コード例 #36
0
        /// <summary>
        /// This method is used to initialize the plug-in at the start of the
        /// build process.
        /// </summary>
        /// <param name="buildProcess">A reference to the current build
        /// process.</param>
        /// <param name="configuration">The configuration data that the plug-in
        /// should use to initialize itself.</param>
        public void Initialize(BuildProcess buildProcess, XPathNavigator configuration)
        {
            this.builder = buildProcess;

            XPathNavigator configRoot = configuration.SelectSingleNode("configuration");
            if (configRoot != null)
            {
                XPathNavigator node = configRoot.SelectSingleNode("targetLanguage");
                if (node != null)
                {
                    targetLanguage = node.InnerXml.Trim();
                }
            }
        }
コード例 #37
0
        //=====================================================================

        /// <summary>
        /// This is used to start the background build process from which we will get the information to load the
        /// tree view.
        /// </summary>
        /// <param name="sender">The sender of the event</param>
        /// <param name="e">The event arguments</param>
        private async void ApiFilterEditorDlg_Load(object sender, EventArgs e)
        {
            string tempPath;

            tvApiList.Enabled = splitContainer.Panel2.Enabled = btnReset.Enabled = false;

            try
            {
                // Clone the project for the build and adjust its properties for our needs
                tempProject = new SandcastleProject(apiFilter.Project.MSBuildProject);

                // Build output is stored in a temporary folder and it keeps the intermediate files
                tempProject.CleanIntermediates = false;
                tempPath = Path.GetTempFileName();

                File.Delete(tempPath);
                tempPath = Path.Combine(Path.GetDirectoryName(tempPath), "SHFBPartialBuild");

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

                tempProject.OutputPath = tempPath;

                cancellationTokenSource = new CancellationTokenSource();

                buildProcess = new BuildProcess(tempProject, PartialBuildType.GenerateReflectionInfo)
                {
                    ProgressReportProvider = new Progress<BuildProgressEventArgs>(buildProcess_ReportProgress),
                    CancellationToken = cancellationTokenSource.Token,
                    SuppressApiFilter = true        // We must suppress the current API filter for this build
                };

                await Task.Run(() => buildProcess.Build(), cancellationTokenSource.Token);

                if(!cancellationTokenSource.IsCancellationRequested)
                {
                    // Restore the current project's base path
                    Directory.SetCurrentDirectory(Path.GetDirectoryName(apiFilter.Project.Filename));

                    // If successful, load the namespace nodes, and enable the UI
                    if(buildProcess.CurrentBuildStep == BuildStep.Completed)
                    {
                        reflectionFile = buildProcess.ReflectionInfoFilename;

                        // Convert the build API filter to a dictionary to make it easier to find entries
                        buildFilterEntries = new Dictionary<string, ApiFilter>();

                        this.ConvertApiFilter(buildProcess.CurrentProject.ApiFilter);
                        this.LoadNamespaces();

                        tvApiList.Enabled = splitContainer.Panel2.Enabled = btnReset.Enabled = true;
                    }
                    else
                        MessageBox.Show("Unable to build project to obtain API information.  Please perform a " +
                            "normal build to identify and correct the problem.", Constants.AppName,
                            MessageBoxButtons.OK, MessageBoxIcon.Error);

                    pbWait.Visible = lblLoading.Visible = false;
                }
                else
                {
                    this.DialogResult = DialogResult.Cancel;
                    this.Close();
                }

                buildProcess = null;
            }
            catch(Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(ex.ToString());
                MessageBox.Show("Unable to build project to obtain API information.  Error: " +
                    ex.Message, Constants.AppName, MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            finally
            {
                if(cancellationTokenSource != null)
                {
                    cancellationTokenSource.Dispose();
                    cancellationTokenSource = null;
                }
            }
        }
コード例 #38
0
        /// <summary>
        /// This method is used to initialize the plug-in at the start of the build process
        /// </summary>
        /// <param name="buildProcess">A reference to the current build process</param>
        /// <param name="configuration">The configuration data that the plug-in should use to initialize itself</param>
        public void Initialize(BuildProcess buildProcess, XPathNavigator configuration)
        {
            builder = buildProcess;

            var metadata = (HelpFileBuilderPlugInExportAttribute)this.GetType().GetCustomAttributes(
                typeof(HelpFileBuilderPlugInExportAttribute), false).First();

            builder.ReportProgress("{0} Version {1}\r\n{2}", metadata.Id, metadata.Version, metadata.Copyright);

            expressions = new List<MemberIdMatchExpression>();

            foreach(XPathNavigator nav in configuration.Select("configuration/expressions/expression"))
                expressions.Add(new MemberIdMatchExpression
                {
                    MatchExpression = nav.GetAttribute("matchExpression", String.Empty),
                    ReplacementValue = nav.GetAttribute("replacementValue", String.Empty),
                    MatchAsRegEx = Convert.ToBoolean(nav.GetAttribute("matchAsRegEx", String.Empty))
                });

            if(expressions.Count == 0)
                throw new BuilderException("MNF0001", "No fix-up expressions have been defined for the Member " +
                    "Name Fix-Up plug-in");
        }
コード例 #39
0
        /// <summary>
        /// This method is used to initialize the plug-in at the start of the
        /// build process.
        /// </summary>
        /// <param name="buildProcess">A reference to the current build
        /// process.</param>
        /// <param name="configuration">The configuration data that the plug-in
        /// should use to initialize itself.</param>
        /// <exception cref="BuilderException">This is thrown if the plug-in
        /// configuration is not valid.</exception>
        public void Initialize(BuildProcess buildProcess,
          XPathNavigator configuration)
        {
            XPathNavigator root, node;

            builder = buildProcess;
            ajaxDocUrl = projectName = String.Empty;
            userCreds = new UserCredentials();
            proxyCreds = new ProxyCredentials();

            builder.ReportProgress("{0} Version {1}\r\n{2}",
                this.Name, this.Version, this.Copyright);

            root = configuration.SelectSingleNode("configuration");

            if(root.IsEmptyElement)
                throw new BuilderException("ADP0001", "The AjaxDoc plug-in " +
                    "has not been configured yet");

            node = root.SelectSingleNode("ajaxDoc");
            if(node != null)
            {
                ajaxDocUrl = node.GetAttribute("url", String.Empty).Trim();
                projectName = node.GetAttribute("project", String.Empty).Trim();
                regenerateFiles = Convert.ToBoolean(node.GetAttribute(
                    "regenerate", String.Empty), CultureInfo.InvariantCulture);
            }

            userCreds = UserCredentials.FromXPathNavigator(root);
            proxyCreds = ProxyCredentials.FromXPathNavigator(root);

            if(ajaxDocUrl.Length == 0 || projectName.Length == 0 ||
              (!userCreds.UseDefaultCredentials &&
              (userCreds.UserName.Length == 0 ||
              userCreds.Password.Length == 0)) ||
              (proxyCreds.UseProxyServer &&
              (proxyCreds.ProxyServer == null ||
              (!proxyCreds.Credentials.UseDefaultCredentials &&
              (proxyCreds.Credentials.UserName.Length == 0 ||
              proxyCreds.Credentials.Password.Length == 0)))))
                throw new BuilderException("ADP0002", "The AjaxDoc plug-in " +
                    "has an invalid configuration");
        }
コード例 #40
0
        /// <summary>
        /// This is used to determine the state of the help content and set the form options when a help viewer
        /// version is selected.
        /// </summary>
        /// <param name="sender">The sender of the event</param>
        /// <param name="e">The event arguments</param>
        private void cboHelpViewerVersion_SelectedIndexChanged(object sender, EventArgs e)
        {
            txtInfo.Text = null;

            grpOptions.Enabled  = rbInstall.Enabled = true;
            lastVersionSelected = cboHelpViewerVersion.SelectedIndex;

            // If there are substitution tags present, have a go at resolving them
            if (helpFilePath.IndexOf("{@", StringComparison.Ordinal) != -1)
            {
                try
                {
                    var bp = new SandcastleBuilder.Utils.BuildEngine.BuildProcess(project);
                    helpFilePath = bp.SubstitutionTags.TransformText(helpFilePath);
                    setupFile    = Path.ChangeExtension(helpFilePath, ".msha");
                }
                catch
                {
                    // Ignore errors
                    txtInfo.AppendText("The help filename appears to contain substitution tags but they could " +
                                       "not be resolved to determine the actual file to use for installation.  Building " +
                                       "website output and viewing it can be used to work around this issue.\r\n\r\n");
                    rbInstall.Enabled = false;
                }
            }

            if (rbInstall.Enabled && (!File.Exists(helpFilePath) || !File.Exists(setupFile)))
            {
                txtInfo.AppendText("A copy of the help file does not appear to exist yet.  It may need to be built.\r\n\r\n");
                rbInstall.Enabled = false;
            }

            try
            {
                viewerVersion = new Version((string)cboHelpViewerVersion.SelectedItem);

                HelpLibraryManager hlm = new HelpLibraryManager(viewerVersion);

                // Can't do anything if the Help Library Manager is not installed
                if (hlm.HelpLibraryManagerPath == null)
                {
                    throw new HelpLibraryManagerException(viewerVersion,
                                                          HelpLibraryManagerException.HelpLibraryManagerNotFound);
                }

                // Can't do anything if the Help Library Manager is already running
                if (Process.GetProcessesByName(Path.GetFileNameWithoutExtension(hlm.HelpLibraryManagerPath)).Length > 0)
                {
                    throw new HelpLibraryManagerException(viewerVersion,
                                                          HelpLibraryManagerException.HelpLibraryManagerAlreadyRunning);
                }

                // Can't do anything if the local store is not initialized
                if (!hlm.LocalStoreInitialized)
                {
                    throw new HelpLibraryManagerException(viewerVersion,
                                                          HelpLibraryManagerException.LocalStoreNotInitialized);
                }

                if (hlm.HelpContentFileInstalled(helpFilePath))
                {
                    rbOpenCurrent.Enabled = rbRemove.Enabled = true;
                }
                else
                {
                    txtInfo.AppendText("The help file does not appear to be installed yet.\r\n");
                    rbOpenCurrent.Enabled = rbRemove.Enabled = false;
                }
            }
            catch (Exception ex)
            {
                txtInfo.AppendText("Problem: " + ex.Message + "\r\n");
                rbOpenCurrent.Enabled = rbRemove.Enabled = false;
            }

            if (rbOpenCurrent.Enabled)
            {
                rbOpenCurrent.Checked = true;
            }
            else
            if (rbInstall.Enabled)
            {
                rbInstall.Checked = true;
            }
            else
            {
                rbLaunchContentManager.Checked = true;
            }

            if (!rbOpenCurrent.Enabled && !rbInstall.Enabled && !rbRemove.Enabled)
            {
                txtInfo.AppendText("\r\nNo action can be taken with the help content.");
            }

            // Determine the catalog name here as it's used in a lot of places and varies by version if not
            // defined in the project.
            catalogName = !String.IsNullOrWhiteSpace(project.CatalogName) ? project.CatalogName :
                          HelpLibraryManager.DefaultCatalogName(viewerVersion);

            // If it looks like a default value, warn the user if it doesn't match.  It may need to be cleared.
            if (!String.IsNullOrWhiteSpace(project.CatalogName) && project.CatalogName.StartsWith("VisualStudio",
                                                                                                  StringComparison.Ordinal) && project.CatalogName != HelpLibraryManager.DefaultCatalogName(viewerVersion))
            {
                txtInfo.AppendText("\r\n\r\nWARNING:  The project's catalog name property is set to '" +
                                   project.CatalogName + "' which does not match the default catalog name for the selected " +
                                   "version of the help viewer.  If necessary, clear the catalog name property value.");
            }
        }