/// <summary> /// Create a content layout file for the conceptual topics /// </summary> private void CreateContentLayoutFile() { string filename = Path.Combine(base.ProjectFolder, "ContentLayout.content"); XmlWriterSettings settings = new XmlWriterSettings(); int topicsAdded = 0; try { settings.Indent = true; settings.CloseOutput = true; using(var writer = XmlWriter.Create(filename, settings)) { writer.WriteStartDocument(); writer.WriteStartElement("Topics"); using(var reader = new XmlTextReader(new StreamReader(topicLayoutFilename))) { reader.MoveToContent(); while(!reader.EOF && reader.NodeType != XmlNodeType.EndElement) { if(reader.NodeType == XmlNodeType.Element && reader.Name == "topics" && !reader.IsEmptyElement) { while(!reader.EOF && reader.NodeType != XmlNodeType.EndElement) { if(reader.NodeType == XmlNodeType.Element && reader.Name == "topic") { this.ConvertTopic(reader, writer); topicsAdded++; } reader.Read(); } } reader.Read(); } } writer.WriteEndElement(); // </Topics> writer.WriteEndDocument(); } } catch(Exception ex) { throw new BuilderException("CVT0006", String.Format(CultureInfo.CurrentCulture, "Error converting content layout file ({0}):\r\n{1}", topicLayoutFilename, ex.Message), ex); } if(topicsAdded != 0) project.AddFileToProject(filename, filename); else this.CreateDefaultContentLayoutFile(); }
//===================================================================== /// <summary> /// This is used to perform the actual conversion /// </summary> /// <returns>The new project filename on success. An exception is thrown if the conversion fails.</returns> public override string ConvertProject() { SandcastleProject project = base.Project; FileItem fileItem; List <string> syntaxFilters = new List <string> { "C#", "Visual Basic", "Managed C++" }; string option, lastProperty = null, value; int pos; try { project.HelpTitle = project.HtmlHelpName = Path.GetFileNameWithoutExtension(base.OldProjectFile); using (StreamReader sr = new StreamReader(base.OldProjectFile)) while (!sr.EndOfStream) { option = sr.ReadLine(); if (String.IsNullOrEmpty(option)) { continue; } pos = option.IndexOf('='); if (pos == -1) { continue; } lastProperty = option.Substring(0, pos).Trim().ToLowerInvariant(); value = option.Substring(pos + 1).Trim(); switch (lastProperty) { case "copyright": project.CopyrightText = value; break; case "productname": project.HelpTitle = value; break; case "assemblydir": project.DocumentationSources.Add(Path.Combine(value, "*.*"), null, null, false); break; case "docdir": this.ConvertAdditionalContent(value); break; case "logo": fileItem = project.AddFileToProject(value, Path.Combine(base.ProjectFolder, Path.GetFileName(value))); // The transform arguments category of properties will need to be set to include // the logo in the XSL transformations. The build action must be content. It // will also need to be moved to the .\Icons folder in the project. fileItem.BuildAction = BuildAction.Content; break; case "msdnlinks": if (String.Compare(value, "false", StringComparison.OrdinalIgnoreCase) == 0) { project.HtmlSdkLinkType = project.WebsiteSdkLinkType = HtmlSdkLinkType.None; project.MSHelp2SdkLinkType = MSHelp2SdkLinkType.Index; project.MSHelpViewerSdkLinkType = MSHelpViewerSdkLinkType.Id; } break; case "outputtype": if (value.IndexOf("website", StringComparison.OrdinalIgnoreCase) != -1) { project.HelpFileFormat = HelpFileFormats.HtmlHelp1 | HelpFileFormats.Website; } break; case "friendlyfilenames": if (String.Compare(value, "true", StringComparison.OrdinalIgnoreCase) == 0) { project.NamingMethod = NamingMethod.MemberName; } break; case "template": project.PresentationStyle = value; break; case "internals": if (String.Compare(value, "true", StringComparison.OrdinalIgnoreCase) == 0) { project.DocumentPrivates = project.DocumentInternals = true; } break; case "cssyntaxdeclaration": if (String.Compare(value, "false", StringComparison.OrdinalIgnoreCase) == 0) { syntaxFilters.Remove("C#"); } break; case "vbsyntaxdeclaration": if (String.Compare(value, "false", StringComparison.OrdinalIgnoreCase) == 0) { syntaxFilters.Remove("Visual Basic"); } break; case "cppsyntaxdeclaration": if (String.Compare(value, "false", StringComparison.OrdinalIgnoreCase) == 0) { syntaxFilters.Remove("Managed C++"); } break; case "javascriptsyntaxdeclaration": if (String.Compare(value, "true", StringComparison.OrdinalIgnoreCase) == 0) { syntaxFilters.Add("JavaScript"); } break; default: // Ignored break; } } // Set the syntax filters project.SyntaxFilters = String.Join(", ", syntaxFilters.ToArray()); base.CreateFolderItems(); project.SaveProject(project.Filename); } catch (Exception ex) { throw new BuilderException("CVT0005", String.Format(CultureInfo.CurrentCulture, "Error reading project from '{0}' (last property = {1}):\r\n{2}", base.OldProjectFile, lastProperty, ex.Message), ex); } return(project.Filename); }
//===================================================================== /// <summary> /// This is used to perform the actual conversion /// </summary> /// <returns>The new project filename on success. An exception is /// thrown if the conversion fails.</returns> public override string ConvertProject() { XPathDocument sourceFile; XPathNavigator navNDoc; SearchOption searchOpts; SandcastleProject project = base.Project; FileItem fileItem; List <string> syntaxFilters = new List <string> { "C#", "Visual Basic", "Managed C++" }; string assemblyName, commentsName, folderName, value, destFile, propName = null; string[] list; try { sourceFile = new XPathDocument(base.OldProjectFile); navNDoc = sourceFile.CreateNavigator(); // Add the assemblies foreach (XPathNavigator assembly in navNDoc.Select( "project/assemblies/assembly")) { assemblyName = this.FullPath( assembly.GetAttribute("location", String.Empty)); commentsName = this.FullPath( assembly.GetAttribute("documentation", String.Empty)); if (!String.IsNullOrEmpty(assemblyName)) { project.DocumentationSources.Add(assemblyName, null, null, false); } if (!String.IsNullOrEmpty(commentsName)) { project.DocumentationSources.Add(commentsName, null, null, false); } } // Add reference paths foreach (XPathNavigator reference in navNDoc.Select( "project/referencePaths/referencePath")) { folderName = this.FullPath(reference.GetAttribute( "path", String.Empty)); if (folderName.EndsWith("\\**", StringComparison.Ordinal)) { searchOpts = SearchOption.AllDirectories; folderName = folderName.Substring(0, folderName.Length - 3); } else { searchOpts = SearchOption.TopDirectoryOnly; } foreach (string refFile in Directory.EnumerateFiles(folderName, "*.dll", searchOpts)) { Project.References.AddReference(Path.GetFileNameWithoutExtension(refFile), refFile); } } // Add the namespace summaries foreach (XPathNavigator ns in navNDoc.Select( "project/namespaces/namespace")) { if (!String.IsNullOrEmpty(ns.InnerXml)) { project.NamespaceSummaries.Add(ns.GetAttribute("name", String.Empty), false, true, ns.InnerXml); } } // Add one for the global namespace if it isn't there if (project.NamespaceSummaries[String.Empty] == null) { project.NamespaceSummaries.Add(String.Empty, false, false, String.Empty); } project.NamespaceSummaries.Sort(); // Add options from the MSDN documenters. This will be a // merger of all the documenters present in the file since // we can't tell which one is the active one. The file can // be edited by hand to delete unwanted documenters or // properties before converting it. foreach (XPathNavigator node in navNDoc.Select( "project/documenters/documenter[@name=\"MSDN\" or " + "@name=\"MSDN-CHM\" or @name=\"VS.NET 2003\" or " + "@name=\"MSDN 2003\"]")) { foreach (XPathNavigator child in node.Select("*")) { propName = child.GetAttribute("name", String.Empty); switch (propName) { case "AdditionalContentResourceDirectory": this.ConvertAdditionalContent(child.GetAttribute( "value", String.Empty)); break; case "BinaryTOC": project.BinaryTOC = Convert.ToBoolean( child.GetAttribute("value", String.Empty), CultureInfo.InvariantCulture); break; case "CleanIntermediates": project.CleanIntermediates = Convert.ToBoolean( child.GetAttribute("value", String.Empty), CultureInfo.InvariantCulture); break; case "CopyrightHref": project.CopyrightHref = child.GetAttribute( "value", String.Empty); break; case "CopyrightText": project.CopyrightText = child.GetAttribute( "value", String.Empty); break; case "DocumentAttributes": project.DocumentAttributes = Convert.ToBoolean( child.GetAttribute("value", String.Empty), CultureInfo.InvariantCulture); break; case "DocumentExplicitInterfaceImplementations": project.DocumentExplicitInterfaceImplementations = Convert.ToBoolean(child.GetAttribute( "value", String.Empty), CultureInfo.InvariantCulture); break; case "DocumentInheritedMembers": project.DocumentInheritedMembers = Convert.ToBoolean(child.GetAttribute( "value", String.Empty), CultureInfo.InvariantCulture); break; case "DocumentInheritedFrameworkMembers": project.DocumentInheritedFrameworkMembers = Convert.ToBoolean(child.GetAttribute( "value", String.Empty), CultureInfo.InvariantCulture); break; case "DocumentInternals": project.DocumentInternals = Convert.ToBoolean( child.GetAttribute("value", String.Empty), CultureInfo.InvariantCulture); break; case "DocumentPrivates": project.DocumentPrivates = Convert.ToBoolean( child.GetAttribute("value", String.Empty), CultureInfo.InvariantCulture); break; case "DocumentProtected": project.DocumentProtected = Convert.ToBoolean( child.GetAttribute("value", String.Empty), CultureInfo.InvariantCulture); break; case "DocumentProtectedInternalAsProtected": project.DocumentProtectedInternalAsProtected = Convert.ToBoolean(child.GetAttribute( "value", String.Empty), CultureInfo.InvariantCulture); break; case "DocumentSealedProtected": project.DocumentSealedProtected = Convert.ToBoolean(child.GetAttribute( "value", String.Empty), CultureInfo.InvariantCulture); break; case "FeedbackEmailAddress": project.FeedbackEMailAddress = child.GetAttribute("value", String.Empty); break; case "HtmlHelpName": project.HtmlHelpName = child.GetAttribute( "value", String.Empty); break; case "IncludeFavorites": project.IncludeFavorites = Convert.ToBoolean( child.GetAttribute("value", String.Empty), CultureInfo.InvariantCulture); break; case "OutputDirectory": folderName = child.GetAttribute("value", String.Empty); if (folderName != @".\doc\") { project.OutputPath = new FolderPath( folderName, project); } break; case "Preliminary": project.Preliminary = Convert.ToBoolean( child.GetAttribute("value", String.Empty), CultureInfo.InvariantCulture); break; case "Title": value = child.GetAttribute("value", String.Empty); if (value != "An NDoc Documented Class Library" && value != "An NDoc documented library") { project.HelpTitle = value; } break; case "RootPageContainsNamespaces": project.RootNamespaceContainer = Convert.ToBoolean(child.GetAttribute( "value", String.Empty), CultureInfo.InvariantCulture); break; case "RootPageFileName": value = this.FullPath(child.GetAttribute( "value", String.Empty)); destFile = Path.Combine(base.ProjectFolder, Path.GetFileName(value)); project.AddFileToProject(value, destFile); break; case "RootPageTOCName": project.RootNamespaceTitle = child.GetAttribute( "value", String.Empty); break; case "FilesToInclude": foreach (string filename in child.GetAttribute( "value", String.Empty).Split(new char[] { '|' })) { value = this.FullPath(filename.Trim()); destFile = Path.Combine(base.ProjectFolder, Path.GetFileName(value)); project.AddFileToProject(value, destFile); } break; case "AutoDocumentConstructors": project.AutoDocumentConstructors = Convert.ToBoolean(child.GetAttribute( "value", String.Empty), CultureInfo.InvariantCulture); break; case "ShowMissingSummaries": project.ShowMissingSummaries = Convert.ToBoolean(child.GetAttribute( "value", String.Empty), CultureInfo.InvariantCulture); break; case "ShowMissingRemarks": project.ShowMissingRemarks = Convert.ToBoolean(child.GetAttribute( "value", String.Empty), CultureInfo.InvariantCulture); break; case "ShowMissingParams": project.ShowMissingParams = Convert.ToBoolean(child.GetAttribute( "value", String.Empty), CultureInfo.InvariantCulture); break; case "ShowMissingReturns": project.ShowMissingReturns = Convert.ToBoolean(child.GetAttribute( "value", String.Empty), CultureInfo.InvariantCulture); break; case "ShowMissingValues": project.ShowMissingValues = Convert.ToBoolean(child.GetAttribute( "value", String.Empty), CultureInfo.InvariantCulture); break; case "ShowVisualBasic": if (child.GetAttribute("value", String.Empty) == "False") { syntaxFilters.Remove("Visual Basic"); } break; case "AboutPageIconPage": case "AboutPageInfo": case "EmptyIndexTermPage": case "IntroductionPage": case "NavFailPage": value = this.FullPath(child.GetAttribute( "value", String.Empty)); destFile = Path.Combine(base.ProjectFolder, Path.GetFileName(value)); fileItem = project.AddFileToProject(value, destFile); fileItem.ExcludeFromToc = true; break; case "CollectionTOCStyle": project.CollectionTocStyle = (CollectionTocStyle)Enum.Parse( typeof(CollectionTocStyle), child.GetAttribute("value", String.Empty), true); break; case "DocSetList": list = child.GetAttribute("value", String.Empty).Split(','); foreach (string docSet in list) { project.HelpAttributes.Add("DocSet", docSet.Trim()); } break; case "IncludeDefaultStopWordList": project.IncludeStopWordList = Convert.ToBoolean( child.GetAttribute("value", String.Empty), CultureInfo.InvariantCulture); break; case "Version": project.HelpFileVersion = child.GetAttribute( "value", String.Empty); break; case "OutputTarget": value = child.GetAttribute("value", String.Empty); if (value == "HtmlHelp") { project.HelpFileFormat = HelpFileFormats.HtmlHelp1; } else if (value == "Web") { project.HelpFileFormat = HelpFileFormats.Website; } else { project.HelpFileFormat = HelpFileFormats.HtmlHelp1 | HelpFileFormats.Website; } break; case "SdkDocLanguage": project.Language = new CultureInfo( child.GetAttribute("value", String.Empty)); break; case "SdkDocVersion": value = child.GetAttribute("value", String.Empty).Substring(5).Replace('_', '.'); project.FrameworkVersion = Utility.ConvertFromOldValue(value); break; case "SdkLinksOnWeb": if (child.GetAttribute("value", String.Empty) == "True") { project.HtmlSdkLinkType = project.WebsiteSdkLinkType = HtmlSdkLinkType.Msdn; project.MSHelp2SdkLinkType = MSHelp2SdkLinkType.Msdn; project.MSHelpViewerSdkLinkType = MSHelpViewerSdkLinkType.Msdn; } else { project.HtmlSdkLinkType = project.WebsiteSdkLinkType = HtmlSdkLinkType.None; project.MSHelp2SdkLinkType = MSHelp2SdkLinkType.Index; project.MSHelpViewerSdkLinkType = MSHelpViewerSdkLinkType.Id; } break; default: break; } } } // Set the syntax filters project.SyntaxFilters = String.Join(", ", syntaxFilters.ToArray()); base.CreateFolderItems(); project.SaveProject(project.Filename); } catch (Exception ex) { throw new BuilderException("CVT0005", String.Format( CultureInfo.CurrentCulture, "Error reading project " + "from '{0}' (last property = {1}):\r\n{2}", base.OldProjectFile, propName, ex.Message), ex); } return(project.Filename); }
//===================================================================== /// <summary> /// Add all topics from the specified folder recursively to the collection and to the given project file /// </summary> /// <param name="folder">The folder from which to get the files</param> /// <param name="basePath">The base path to remove from files copied from another folder into the project /// folder. On the first call, this should match the <paramref name="folder"/> value.</param> /// <param name="project">The project to which the files are added</param> /// <remarks>Only actual conceptual content topic files are added. They must have a ".aml" extension and /// must be one of the valid <see cref="DocumentType">document types</see>. Folders will be added as /// sub-topics recursively. If a file with the same name as the folder exists, it will be associated /// with the container node. If no such file exists, an empty container node is created.</remarks> public void AddTopicsFromFolder(string folder, string basePath, SandcastleProject project) { if (basePath == null) { throw new ArgumentNullException(nameof(basePath)); } if (project == null) { throw new ArgumentNullException(nameof(project)); } FileItem newItem; Topic topic, removeTopic; string name, newPath, projectPath = Path.GetDirectoryName(project.Filename); if (basePath.Length != 0 && basePath[basePath.Length - 1] != '\\') { basePath += "\\"; } // Add files foreach (string file in Directory.EnumerateFiles(folder, "*.aml")) { try { // The file must reside under the project path if (Path.GetDirectoryName(file).StartsWith(projectPath, StringComparison.OrdinalIgnoreCase)) { newPath = file; } else { newPath = Path.Combine(projectPath, file.Substring(basePath.Length)); } // Add the file to the project newItem = project.AddFileToProject(file, newPath); topic = new Topic { TopicFile = new TopicFile(newItem.ToContentFile()) }; if (topic.DocumentType > DocumentType.Invalid) { this.Add(topic); } } catch { // Ignore invalid files } } // Add folders recursively foreach (string folderName in Directory.EnumerateDirectories(folder)) { topic = new Topic { Title = name = Path.GetFileName(folderName) }; topic.Subtopics.AddTopicsFromFolder(folderName, basePath, project); // Ignore empty folders if (topic.Subtopics.Count == 0) { continue; } this.Add(topic); // Look for a file with the same name as the folder removeTopic = null; foreach (Topic t in topic.Subtopics) { if (t.TopicFile != null && Path.GetFileNameWithoutExtension(t.TopicFile.FullPath) == name) { // If found, remove it as it represents the container node topic.Title = null; topic.TopicFile = t.TopicFile; removeTopic = t; break; } } if (removeTopic != null) { topic.Subtopics.Remove(removeTopic); } } }
//===================================================================== /// <summary> /// Add all topics from the specified folder recursively to the collection and to the given project file /// </summary> /// <param name="folder">The folder from which to get the files</param> /// <param name="basePath">The base path to remove from files copied from another folder into the project /// folder. On the first call, this should match the <paramref name="folder"/> value.</param> /// <param name="project">The project to which the files are added</param> /// <remarks>Only actual HTML and markdown content topic files are added. They must have a ".htm?" or /// "*.md" extension. Folders will be added as sub-topics recursively. If a file with the same name as /// the folder exists, it will be associated with the container node. If no such file exists, an empty /// container node is created.</remarks> public void AddTopicsFromFolder(string folder, string basePath, SandcastleProject project) { if (basePath == null) { throw new ArgumentNullException(nameof(project)); } if (project == null) { throw new ArgumentNullException(nameof(project)); } TocEntry topic, removeTopic; string name, newPath, projectPath = Path.GetDirectoryName(project.Filename); if (basePath.Length != 0 && basePath[basePath.Length - 1] != '\\') { basePath += "\\"; } // Add files foreach (string file in Directory.EnumerateFiles(folder, "*.htm?").Concat( Directory.EnumerateFiles(folder, "*.md"))) { // The file must reside under the project path if (Path.GetDirectoryName(file).StartsWith(projectPath, StringComparison.OrdinalIgnoreCase)) { newPath = file; } else { newPath = Path.Combine(projectPath, file.Substring(basePath.Length)); } // Add the file to the project project.AddFileToProject(file, newPath); topic = new TocEntry(project) { SourceFile = new FilePath(newPath, project), Title = Path.GetFileNameWithoutExtension(newPath) }; this.Add(topic); } // Add folders recursively foreach (string folderName in Directory.EnumerateDirectories(folder)) { topic = new TocEntry(project) { Title = name = Path.GetFileName(folderName) }; topic.Children.AddTopicsFromFolder(folderName, basePath, project); // Ignore empty folders if (topic.Children.Count == 0) { continue; } this.Add(topic); // Look for a file with the same name as the folder removeTopic = null; foreach (TocEntry t in topic.Children) { if (Path.GetFileNameWithoutExtension(t.SourceFile) == name) { // If found, remove it as it represents the container node topic.Title = name; topic.SourceFile = t.SourceFile; removeTopic = t; break; } } if (removeTopic != null) { topic.Children.Remove(removeTopic); } } }
/// <summary> /// Convert a conceptual content topic and all of its children /// </summary> /// <param name="xr">The XML reader containing the topics</param> /// <param name="xw">The XML writer to which they are written</param> /// <param name="project">The project to which the files are added</param> private void ConvertTopic(XmlReader xr, XmlWriter xw, SandcastleProject project) { FileItem newFile = null; string id, file, title, tocTitle, linkText, destFile, ext, name, value, oldFolder = converter.OldFolder, projectFolder = converter.ProjectFolder; bool visible; int revision; id = xr.GetAttribute("id"); // If not set, an ID will be created when needed if (id == null || id.Trim().Length == 0) { id = new Guid(id).ToString(); } file = xr.GetAttribute("file"); title = xr.GetAttribute("title"); tocTitle = xr.GetAttribute("tocTitle"); linkText = xr.GetAttribute("linkText"); if (!Int32.TryParse(xr.GetAttribute("revision"), out revision) || revision < 1) { revision = 1; } if (!Boolean.TryParse(xr.GetAttribute("visible"), out visible)) { visible = true; } // Add the topic to the content file and the project xw.WriteStartElement("Topic"); xw.WriteAttributeString("id", id); if (file != null && file.Trim().Length > 0) { file = converter.FullPath(file); // Maintain any additional path info beyond the old base // project folder. if (file.StartsWith(oldFolder, StringComparison.OrdinalIgnoreCase)) { destFile = projectFolder + file.Substring(oldFolder.Length); } else { destFile = Path.Combine(projectFolder, Path.GetFileName(file)); } ext = Path.GetExtension(destFile).ToLower( CultureInfo.InvariantCulture); // Change the extension on .xml files to .aml and add the // root topic element. if (ext == ".xml") { destFile = Path.ChangeExtension(destFile, ".aml"); ConvertTopic(file, destFile, id, revision); file = destFile; } // Add meta elements for the ID and revision number if (ext == ".htm" || ext == ".html" || ext == ".topic") { ConvertTopic(file, destFile, id, revision); file = destFile; } newFile = project.AddFileToProject(file, destFile); newFile.BuildAction = BuildAction.None; } else { xw.WriteAttributeString("noFile", "True"); } if (title != null) { xw.WriteAttributeString("title", title); } if (tocTitle != null) { xw.WriteAttributeString("tocTitle", tocTitle); } if (linkText != null) { xw.WriteAttributeString("linkText", linkText); } xw.WriteAttributeString("visible", visible.ToString(CultureInfo.InvariantCulture)); // Add child elements, if any if (!xr.IsEmptyElement) { while (!xr.EOF) { xr.Read(); if (xr.NodeType == XmlNodeType.EndElement && xr.Name == "topic") { break; } if (xr.NodeType == XmlNodeType.Element) { if (xr.Name == "helpAttributes") { xw.WriteStartElement("HelpAttributes"); while (!xr.EOF && xr.NodeType != XmlNodeType.EndElement) { if (xr.NodeType == XmlNodeType.Element && xr.Name == "helpAttribute") { name = xr.GetAttribute("name"); value = xr.GetAttribute("value"); if (!String.IsNullOrEmpty(name)) { xw.WriteStartElement("HelpAttribute"); xw.WriteAttributeString("name", name); xw.WriteAttributeString("value", value); xw.WriteEndElement(); } } xr.Read(); } xw.WriteEndElement(); } else if (xr.Name == "helpKeywords") { xw.WriteStartElement("HelpKeywords"); while (!xr.EOF && xr.NodeType != XmlNodeType.EndElement) { if (xr.NodeType == XmlNodeType.Element && xr.Name == "helpKeyword") { name = xr.GetAttribute("index"); value = xr.GetAttribute("term"); if (!String.IsNullOrEmpty(name)) { xw.WriteStartElement("HelpKeyword"); xw.WriteAttributeString("index", name); xw.WriteAttributeString("term", value); xw.WriteEndElement(); } } xr.Read(); } xw.WriteEndElement(); } else if (xr.Name == "topic") { this.ConvertTopic(xr, xw, project); } } } } xw.WriteEndElement(); }
/// <summary> /// This adds all image files to the project /// </summary> private void AddImageFiles() { XmlReader xr = converter.Reader; SandcastleProject project = converter.Project; FileItem fileItem; string sourceFile, id, altText, destFile, oldFolder = converter.OldFolder, projectFolder = converter.ProjectFolder; bool alwaysCopy; while (!xr.EOF && xr.NodeType != XmlNodeType.EndElement) { if (xr.NodeType == XmlNodeType.Element && xr.Name == "image") { id = xr.GetAttribute("id"); if (id == null || id.Trim().Length == 0) { id = Guid.NewGuid().ToString(); } sourceFile = xr.GetAttribute("file"); if (sourceFile == null || sourceFile.Trim().Length == 0) { sourceFile = "Unknown.jpg"; } sourceFile = converter.FullPath(sourceFile); // Maintain any additional path info beyond the old base // project folder. if (sourceFile.StartsWith(oldFolder, StringComparison.OrdinalIgnoreCase)) { destFile = projectFolder + sourceFile.Substring( oldFolder.Length); } else { destFile = Path.Combine(projectFolder, Path.GetFileName(sourceFile)); } altText = xr.GetAttribute("altText"); alwaysCopy = Convert.ToBoolean(xr.GetAttribute( "alwaysCopy"), CultureInfo.InvariantCulture); fileItem = project.AddFileToProject(sourceFile, destFile); fileItem.BuildAction = BuildAction.Image; fileItem.ProjectElement.SetMetadata("ImageId", id); if (!String.IsNullOrEmpty(altText)) { fileItem.ProjectElement.SetMetadata("AlternateText", altText); } if (alwaysCopy) { fileItem.ProjectElement.SetMetadata("CopyToMedia", "True"); } } xr.Read(); } }
/// <summary> /// Import a file into the project /// </summary> /// <param name="buildItem">The file information</param> private void ImportFile(XPathNavigator buildItem) { string newPath, name, file = buildItem.GetAttribute("Include", String.Empty); FileItem fileItem; bool isTokens = false, isSnippets = false; if (String.IsNullOrEmpty(file)) { return; } // Ignore these paths as they are most likely presentation style files if (file.StartsWith(@"Help\Icons\", StringComparison.OrdinalIgnoreCase) || file.StartsWith(@"Help\Presentation\", StringComparison.OrdinalIgnoreCase) || file.StartsWith(@"Help\Scripts\", StringComparison.OrdinalIgnoreCase) || file.StartsWith(@"Help\Styles\", StringComparison.OrdinalIgnoreCase) || file.StartsWith(@"Help\Schemas\", StringComparison.OrdinalIgnoreCase)) { return; } // For websites, ignore these folders and files if ((project.HelpFileFormat & HelpFileFormats.Website) != 0) { if (file.StartsWith(@"App_Themes\", StringComparison.OrdinalIgnoreCase) || file.StartsWith(@"App_GlobalResources\", StringComparison.OrdinalIgnoreCase) || file.StartsWith(@"App_LocalResources\", StringComparison.OrdinalIgnoreCase) || file.StartsWith(@"Controls\", StringComparison.OrdinalIgnoreCase) || file.StartsWith(@"Scripts\", StringComparison.OrdinalIgnoreCase) || file.StartsWith(@"DocSite.", StringComparison.OrdinalIgnoreCase) || file.StartsWith(@"FileNotFound.htm", StringComparison.OrdinalIgnoreCase) || file.EndsWith(".config", StringComparison.OrdinalIgnoreCase) || file.EndsWith(".aspx", StringComparison.OrdinalIgnoreCase)) { return; } } // Conceptual content media file if (file.StartsWith(@"Help\Art\", StringComparison.OrdinalIgnoreCase)) { newPath = Path.Combine(base.ProjectFolder, file.Substring(5)); file = Path.Combine(base.OldFolder, file); fileItem = project.AddFileToProject(file, newPath); fileItem.BuildAction = BuildAction.None; return; } // Additional XML comments file, add as documentation source if (file.StartsWith(@"Help\Comments\", StringComparison.OrdinalIgnoreCase)) { newPath = Path.Combine(base.ProjectFolder, file.Substring(5)); file = Path.Combine(base.OldFolder, file); if (!Directory.Exists(Path.GetDirectoryName(newPath))) { Directory.CreateDirectory(Path.GetDirectoryName(newPath)); } fileItem = project.AddFileToProject(file, newPath); fileItem.BuildAction = BuildAction.None; project.DocumentationSources.Add(newPath, null, null, false); return; } // Content settings files if (file.StartsWith(@"Help\Settings\", StringComparison.OrdinalIgnoreCase)) { name = Path.GetFileName(file).ToLowerInvariant(); // Filter and process by name switch (name) { case "conceptual_art.xml": this.ImportMediaFile(Path.Combine(base.OldFolder, file)); return; case "conceptual_snippets.xml": isSnippets = true; break; case "metadata.xml": this.ImportCompanionFileInfo(Path.Combine( base.OldFolder, file)); return; case "tokens.xml": isTokens = true; break; case "topics.xml": // This gets processed later topicLayoutFilename = Path.Combine(base.OldFolder, file); return; case "help1x.config": // Ignore case "help2x.xslt": return; default: // Add as content break; } newPath = Path.Combine(base.ProjectFolder, file.Substring(5)); if (isTokens) { newPath = Path.ChangeExtension(newPath, ".tokens"); } else if (isSnippets) { newPath = Path.ChangeExtension(newPath, ".snippets"); } file = Path.Combine(base.OldFolder, file); fileItem = project.AddFileToProject(file, newPath); if (isTokens) { fileItem.BuildAction = BuildAction.Tokens; } else if (isSnippets) { fileItem.BuildAction = BuildAction.CodeSnippets; } return; } // Import companion file info? if (file.EndsWith(".cmp", StringComparison.OrdinalIgnoreCase)) { this.ImportCompanionFileInfo(Path.Combine(base.OldFolder, file)); } else { // General content file if (file.StartsWith(@"Help\", StringComparison.OrdinalIgnoreCase)) { newPath = Path.Combine(base.ProjectFolder, file.Substring(5)); } else { newPath = Path.Combine(base.ProjectFolder, file); } file = Path.Combine(base.OldFolder, file); fileItem = project.AddFileToProject(file, newPath); } }
/// <summary> /// Convert a conceptual content topic and all of its children /// </summary> /// <param name="xr">The XML reader containing the topics</param> /// <param name="xw">The XML writer to which they are written</param> /// <param name="project">The project to which the files are added</param> private void ConvertTopic(XmlReader xr, XmlWriter xw, SandcastleProject project) { FileItem newFile = null; string id, file, title, tocTitle, linkText, destFile, ext, name, value, oldFolder = converter.OldFolder, projectFolder = converter.ProjectFolder; bool visible; int revision; id = xr.GetAttribute("id"); // If not set, an ID will be created when needed if(id == null || id.Trim().Length == 0) id = new Guid(id).ToString(); file = xr.GetAttribute("file"); title = xr.GetAttribute("title"); tocTitle = xr.GetAttribute("tocTitle"); linkText = xr.GetAttribute("linkText"); if(!Int32.TryParse(xr.GetAttribute("revision"), out revision) || revision < 1) revision = 1; if(!Boolean.TryParse(xr.GetAttribute("visible"), out visible)) visible = true; // Add the topic to the content file and the project xw.WriteStartElement("Topic"); xw.WriteAttributeString("id", id); if(file != null && file.Trim().Length > 0) { file = converter.FullPath(file); // Maintain any additional path info beyond the old base // project folder. if(file.StartsWith(oldFolder, StringComparison.OrdinalIgnoreCase)) destFile = projectFolder + file.Substring(oldFolder.Length); else destFile = Path.Combine(projectFolder, Path.GetFileName(file)); ext = Path.GetExtension(destFile).ToLowerInvariant(); // Change the extension on .xml files to .aml and add the // root topic element. if(ext == ".xml") { destFile = Path.ChangeExtension(destFile, ".aml"); ConvertTopic(file, destFile, id, revision); file = destFile; } // Add meta elements for the ID and revision number if(ext == ".htm" || ext == ".html" || ext == ".topic") { ConvertTopic(file, destFile, id, revision); file = destFile; } newFile = project.AddFileToProject(file, destFile); newFile.BuildAction = BuildAction.None; } else xw.WriteAttributeString("noFile", "True"); if(title != null) xw.WriteAttributeString("title", title); if(tocTitle != null) xw.WriteAttributeString("tocTitle", tocTitle); if(linkText != null) xw.WriteAttributeString("linkText", linkText); xw.WriteAttributeString("visible", visible.ToString(CultureInfo.InvariantCulture)); // Add child elements, if any if(!xr.IsEmptyElement) while(!xr.EOF) { xr.Read(); if(xr.NodeType == XmlNodeType.EndElement && xr.Name == "topic") break; if(xr.NodeType == XmlNodeType.Element) if(xr.Name == "helpAttributes") { xw.WriteStartElement("HelpAttributes"); while(!xr.EOF && xr.NodeType != XmlNodeType.EndElement) { if(xr.NodeType == XmlNodeType.Element && xr.Name == "helpAttribute") { name = xr.GetAttribute("name"); value = xr.GetAttribute("value"); if(!String.IsNullOrEmpty(name)) { xw.WriteStartElement("HelpAttribute"); xw.WriteAttributeString("name", name); xw.WriteAttributeString("value", value); xw.WriteEndElement(); } } xr.Read(); } xw.WriteEndElement(); } else if(xr.Name == "helpKeywords") { xw.WriteStartElement("HelpKeywords"); while(!xr.EOF && xr.NodeType != XmlNodeType.EndElement) { if(xr.NodeType == XmlNodeType.Element && xr.Name == "helpKeyword") { name = xr.GetAttribute("index"); value = xr.GetAttribute("term"); if(!String.IsNullOrEmpty(name)) { xw.WriteStartElement("HelpKeyword"); xw.WriteAttributeString("index", name); xw.WriteAttributeString("term", value); xw.WriteEndElement(); } } xr.Read(); } xw.WriteEndElement(); } else if(xr.Name == "topic") this.ConvertTopic(xr, xw, project); } xw.WriteEndElement(); }