diff options
Diffstat (limited to 'tools/Sandcastle/Source/BuildAssembler/BuildComponents')
9 files changed, 449 insertions, 17 deletions
diff --git a/tools/Sandcastle/Source/BuildAssembler/BuildComponents/BuildComponents.csproj b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/BuildComponents.csproj index 9e3932f..e844ba6 100644 --- a/tools/Sandcastle/Source/BuildAssembler/BuildComponents/BuildComponents.csproj +++ b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/BuildComponents.csproj @@ -89,6 +89,7 @@ <Compile Include="GlobalSuppressions.cs" /> <Compile Include="HxfGeneratorComponent.cs" /> <Compile Include="IntellisenseComponent2.cs" /> + <Compile Include="MSHCComponent.cs" /> <Compile Include="MsdnResolver.cs" /> <Compile Include="References.cs" /> <Compile Include="ResolveReferenceLinksComponent2.cs" /> diff --git a/tools/Sandcastle/Source/BuildAssembler/BuildComponents/GlobalSuppressions.cs b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/GlobalSuppressions.cs index 3fd693e..65a3f01 100644 --- a/tools/Sandcastle/Source/BuildAssembler/BuildComponents/GlobalSuppressions.cs +++ b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/GlobalSuppressions.cs @@ -317,3 +317,41 @@ [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1051:DoNotDeclareVisibleInstanceFields", Scope = "member", Target = "Microsoft.Ddue.Tools.Specialization.#arguments")] [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly", Scope = "member", Target = "Microsoft.Ddue.Tools.XmlTargetCollectionUtilities.#CreateTypeReference(System.Xml.XPath.XPathNavigator)")] [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Ddue.Tools.LinkTextResolver.#WriteConversionOperator(Microsoft.Ddue.Tools.ProcedureTarget,System.Xml.XmlWriter)")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "MHS", Scope = "type", Target = "Microsoft.Ddue.Tools.MHSComponent")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.MHSComponent.#AddMHSMeta(System.String,System.String,System.Boolean)")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1304:SpecifyCultureInfo", MessageId = "System.String.ToLower", Scope = "member", Target = "Microsoft.Ddue.Tools.MHSComponent.#Apply(System.Xml.XmlDocument,System.String)")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.Int32.ToString", Scope = "member", Target = "Microsoft.Ddue.Tools.MHSComponent.#Apply(System.Xml.XmlDocument,System.String)")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.MHSComponent.#Apply(System.Xml.XmlDocument,System.String)")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.MHSComponent.#FixHeaderBottomBackground(System.String,System.String)")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.MHSComponent.#ModifyAttribute(System.String,System.String)")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1812:AvoidUninstantiatedInternalClasses", Scope = "type", Target = "Microsoft.Ddue.Tools.MHSComponent+ConfigurationAttr")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1812:AvoidUninstantiatedInternalClasses", Scope = "type", Target = "Microsoft.Ddue.Tools.MHSComponent+ConfigurationTag")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1812:AvoidUninstantiatedInternalClasses", Scope = "type", Target = "Microsoft.Ddue.Tools.MHSComponent+Help2Attr")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1812:AvoidUninstantiatedInternalClasses", Scope = "type", Target = "Microsoft.Ddue.Tools.MHSComponent+Help2Namespace")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1812:AvoidUninstantiatedInternalClasses", Scope = "type", Target = "Microsoft.Ddue.Tools.MHSComponent+Help2Value")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1812:AvoidUninstantiatedInternalClasses", Scope = "type", Target = "Microsoft.Ddue.Tools.MHSComponent+Help2XPath")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1812:AvoidUninstantiatedInternalClasses", Scope = "type", Target = "Microsoft.Ddue.Tools.MHSComponent+MHSDefault")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1812:AvoidUninstantiatedInternalClasses", Scope = "type", Target = "Microsoft.Ddue.Tools.MHSComponent+MHSMetaAttr")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1812:AvoidUninstantiatedInternalClasses", Scope = "type", Target = "Microsoft.Ddue.Tools.MHSComponent+MHSMetaName")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1812:AvoidUninstantiatedInternalClasses", Scope = "type", Target = "Microsoft.Ddue.Tools.MHSComponent+MHSTag")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1812:AvoidUninstantiatedInternalClasses", Scope = "type", Target = "Microsoft.Ddue.Tools.MHSComponent+TocAttr")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1812:AvoidUninstantiatedInternalClasses", Scope = "type", Target = "Microsoft.Ddue.Tools.MHSComponent+TocXPath")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.MSHCComponent.#AddMHSMeta(System.String,System.String,System.Boolean)")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1304:SpecifyCultureInfo", MessageId = "System.String.ToLower", Scope = "member", Target = "Microsoft.Ddue.Tools.MSHCComponent.#Apply(System.Xml.XmlDocument,System.String)")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.Int32.ToString", Scope = "member", Target = "Microsoft.Ddue.Tools.MSHCComponent.#Apply(System.Xml.XmlDocument,System.String)")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.MSHCComponent.#Apply(System.Xml.XmlDocument,System.String)")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.MSHCComponent.#FixHeaderBottomBackground(System.String,System.String)")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object,System.Object)", Scope = "member", Target = "Microsoft.Ddue.Tools.MSHCComponent.#ModifyAttribute(System.String,System.String)")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1812:AvoidUninstantiatedInternalClasses", Scope = "type", Target = "Microsoft.Ddue.Tools.MSHCComponent+ConfigurationAttr")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1812:AvoidUninstantiatedInternalClasses", Scope = "type", Target = "Microsoft.Ddue.Tools.MSHCComponent+ConfigurationTag")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1812:AvoidUninstantiatedInternalClasses", Scope = "type", Target = "Microsoft.Ddue.Tools.MSHCComponent+Help2Attr")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1812:AvoidUninstantiatedInternalClasses", Scope = "type", Target = "Microsoft.Ddue.Tools.MSHCComponent+Help2Namespace")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1812:AvoidUninstantiatedInternalClasses", Scope = "type", Target = "Microsoft.Ddue.Tools.MSHCComponent+Help2Value")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1812:AvoidUninstantiatedInternalClasses", Scope = "type", Target = "Microsoft.Ddue.Tools.MSHCComponent+Help2XPath")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1812:AvoidUninstantiatedInternalClasses", Scope = "type", Target = "Microsoft.Ddue.Tools.MSHCComponent+MHSDefault")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1812:AvoidUninstantiatedInternalClasses", Scope = "type", Target = "Microsoft.Ddue.Tools.MSHCComponent+MHSMetaAttr")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1812:AvoidUninstantiatedInternalClasses", Scope = "type", Target = "Microsoft.Ddue.Tools.MSHCComponent+MHSMetaName")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1812:AvoidUninstantiatedInternalClasses", Scope = "type", Target = "Microsoft.Ddue.Tools.MSHCComponent+MHSTag")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1812:AvoidUninstantiatedInternalClasses", Scope = "type", Target = "Microsoft.Ddue.Tools.MSHCComponent+TocAttr")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1812:AvoidUninstantiatedInternalClasses", Scope = "type", Target = "Microsoft.Ddue.Tools.MSHCComponent+TocXPath")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "MSHC", Scope = "type", Target = "Microsoft.Ddue.Tools.MSHCComponent")] diff --git a/tools/Sandcastle/Source/BuildAssembler/BuildComponents/MSHCComponent.cs b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/MSHCComponent.cs new file mode 100644 index 0000000..3fe5458 --- /dev/null +++ b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/MSHCComponent.cs @@ -0,0 +1,368 @@ +using System; +using System.IO; +using System.Collections.Generic; +using System.Text; +using System.Xml; +using System.Xml.XPath; +using Microsoft.Ddue.Tools; + +namespace Microsoft.Ddue.Tools +{ + /// <summary> + /// Sandcastle component converting Microsoft Help 2.0 output to Microsoft Help System output. + /// </summary> + public class MSHCComponent : BuildComponent + { + // component tag names in the configuration file + private class ConfigurationTag + { + public const string Data = "data"; + } + + // component attribute names in the configuration file + private class ConfigurationAttr + { + public const string Locale = "locale"; + public const string SelfBranded = "self-branded"; + public const string TopicVersion = "topic-version"; + public const string TocFile = "toc-file"; + public const string TocParent = "toc-parent"; + public const string TocParentVersion = "toc-parent-version"; + } + + // XPath expressions to navigate the TOC file + private class TocXPath + { + public const string Topics = "/topics"; + public const string Topic = "topic"; + } + + // attribute names in the TOC file + private class TocAttr + { + public const string Id = "id"; + } + + // Microsoft Help 2.0 namespace info + private class Help2Namespace + { + public const string Prefix = "MSHelp"; + public const string Uri = "http://msdn.microsoft.com/mshelp"; + } + + // XPath expressions to navigate Microsoft Help 2.0 data in the document + private class Help2XPath + { + public const string Head = "head"; + public const string Xml = "xml"; + public const string TocTitle = "MSHelp:TOCTitle"; + public const string Attr = "MSHelp:Attr[@Name='{0}']"; + public const string Keyword = "MSHelp:Keyword[@Index='{0}']"; + } + + // Microsoft Help 2.0 tag attributes in the document + private class Help2Attr + { + public const string Value = "Value"; + public const string Term = "Term"; + public const string Title = "Title"; + } + + // Microsoft Help 2.0 attribute values in the document + private class Help2Value + { + public const string K = "K"; + public const string F = "F"; + public const string Locale = "Locale"; + public const string AssetID = "AssetID"; + public const string DevLang = "DevLang"; + public const string Abstract = "Abstract"; + } + + // Microsoft Help System tags + private class MHSTag + { + public const string Meta = "meta"; + } + + // Microsoft Help System meta tag attributes + private class MHSMetaAttr + { + public const string Name = "name"; + public const string Content = "content"; + } + + // Microsoft Help System meta names + private class MHSMetaName + { + public const string SelfBranded = "SelfBranded"; + public const string ContentType = "ContentType"; + public const string Locale = "Microsoft.Help.Locale"; + public const string TopicLocale = "Microsoft.Help.TopicLocale"; + public const string Id = "Microsoft.Help.Id"; + public const string TopicVersion = "Microsoft.Help.TopicVersion"; + public const string TocParent = "Microsoft.Help.TocParent"; + public const string TocParentVersion = "Microsoft.Help.TOCParentTopicVersion"; + public const string TocOrder = "Microsoft.Help.TocOrder"; + public const string Title = "Title"; + public const string Keywords = "Microsoft.Help.Keywords"; + public const string F1 = "Microsoft.Help.F1"; + public const string Category = "Microsoft.Help.Category"; + public const string Description = "Description"; + } + + // Microsoft Help System meta default values + private class MHSDefault + { + public const bool SelfBranded = true; + public const string Locale = "en-us"; + public const string Reference = "Reference"; + public const string TopicVersion = "100"; + public const string TocParent = "-1"; + public const string TocParentVersion = "100"; + public const string TocFile = "./toc.xml"; + public const string ShortName = "MHS"; + } + + // TOC information of a document + private class TocInfo + { + private string _parent; + private string _parentVersion; + private int _order; + + public TocInfo(string parent, string parentVersion, int order) + { + _parent = parent; + _parentVersion = parentVersion; + _order = order; + } + + public string Parent { get { return _parent; }} + public string ParentVersion { get { return _parentVersion; } } + public int Order { get { return _order; } } + } + + private XmlDocument _document; + private XmlNode _head; + private XmlNode _xml; + + private string _locale = string.Empty; + private bool _selfBranded = MHSDefault.SelfBranded; + private string _topicVersion = MHSDefault.TopicVersion; + private string _tocParent = MHSDefault.TocParent; + private string _tocParentVersion = MHSDefault.TocParentVersion; + private Dictionary<string, TocInfo> _toc = new Dictionary<string, TocInfo>(); + /// <summary> + /// Creates a new instance of the <see cref="MHSComponent"/> class. + /// </summary> + /// <param name="assembler">The active <see cref="BuildAssembler"/>.</param> + /// <param name="configuration">The current <see cref="XPathNavigator"/> of the configuration.</param> + public MSHCComponent(BuildAssembler assembler, XPathNavigator configuration) + : base(assembler, configuration) + { + string tocFile = MHSDefault.TocFile; + XPathNavigator data = configuration.SelectSingleNode(ConfigurationTag.Data); + if (data != null) + { + string value = data.GetAttribute(ConfigurationAttr.Locale, string.Empty); + if (!string.IsNullOrEmpty(value)) + _locale = value; + + value = data.GetAttribute(ConfigurationAttr.SelfBranded, string.Empty); + if (!string.IsNullOrEmpty(value)) + _selfBranded = bool.Parse(value); + + value = data.GetAttribute(ConfigurationAttr.TopicVersion, string.Empty); + if (!string.IsNullOrEmpty(value)) + _topicVersion = value; + + value = data.GetAttribute(ConfigurationAttr.TocParent, string.Empty); + if (!string.IsNullOrEmpty(value)) + _tocParent = value; + + value = data.GetAttribute(ConfigurationAttr.TocParentVersion, string.Empty); + if (!string.IsNullOrEmpty(value)) + _tocParentVersion = value; + + value = data.GetAttribute(ConfigurationAttr.TocFile, string.Empty); + if (!string.IsNullOrEmpty(value)) + tocFile = value; + } + LoadToc(Path.GetFullPath(Environment.ExpandEnvironmentVariables(tocFile))); + } + + #region Public + /// <summary> + /// Applies Microsoft Help System transformation to the output document. + /// </summary> + /// <param name="document">The <see cref="XmlDocument"/> to apply transformation to.</param> + /// <param name="key">Topic key of the output document.</param> + public override void Apply(XmlDocument document, string key) + { + _document = document; + + ModifyAttribute("id", "mainSection"); + ModifyAttribute("class", "members"); + FixHeaderBottomBackground("nsrBottom", "headerBottom"); + + XmlElement html = _document.DocumentElement; + _head = html.SelectSingleNode(Help2XPath.Head); + if (_head == null) + { + _head = document.CreateElement(Help2XPath.Head); + if (!html.HasChildNodes) + html.AppendChild(_head); + else + html.InsertBefore(_head, html.FirstChild); + } + + AddMHSMeta(MHSMetaName.SelfBranded, _selfBranded.ToString().ToLower()); + AddMHSMeta(MHSMetaName.ContentType, MHSDefault.Reference); + AddMHSMeta(MHSMetaName.TopicVersion, _topicVersion); + + string locale = _locale; + string id = Guid.NewGuid().ToString(); + _xml = _head.SelectSingleNode(Help2XPath.Xml); + if (_xml != null) + { + XmlNamespaceManager nsmgr = new XmlNamespaceManager(_document.NameTable); + if (!nsmgr.HasNamespace(Help2Namespace.Prefix)) + nsmgr.AddNamespace(Help2Namespace.Prefix, Help2Namespace.Uri); + + XmlElement elem = _xml.SelectSingleNode(Help2XPath.TocTitle, nsmgr) as XmlElement; + if (elem != null) + AddMHSMeta(MHSMetaName.Title, elem.GetAttribute(Help2Attr.Title)); + + foreach (XmlElement keyword in _xml.SelectNodes(string.Format(Help2XPath.Keyword, Help2Value.K), nsmgr)) + AddMHSMeta(MHSMetaName.Keywords, keyword.GetAttribute(Help2Attr.Term), true); + + foreach (XmlElement keyword in _xml.SelectNodes(string.Format(Help2XPath.Keyword, Help2Value.F), nsmgr)) + AddMHSMeta(MHSMetaName.F1, keyword.GetAttribute(Help2Attr.Term), true); + + foreach (XmlElement lang in _xml.SelectNodes(string.Format(Help2XPath.Attr, Help2Value.DevLang), nsmgr)) + AddMHSMeta(MHSMetaName.Category, Help2Value.DevLang + ":" + lang.GetAttribute(Help2Attr.Value), true); + + elem = _xml.SelectSingleNode(string.Format(Help2XPath.Attr, Help2Value.Abstract), nsmgr) as XmlElement; + if (elem != null) + AddMHSMeta(MHSMetaName.Description, elem.GetAttribute(Help2Attr.Value)); + + elem = _xml.SelectSingleNode(string.Format(Help2XPath.Attr, Help2Value.AssetID), nsmgr) as XmlElement; + if (elem != null) + id = elem.GetAttribute(Help2Attr.Value); + + if (string.IsNullOrEmpty(locale)) + { + elem = _xml.SelectSingleNode(string.Format(Help2XPath.Attr, Help2Value.Locale), nsmgr) as XmlElement; + if (elem != null) + locale = elem.GetAttribute(Help2Attr.Value); + } + } + + if (string.IsNullOrEmpty(locale)) + locale = MHSDefault.Locale; + + AddMHSMeta(MHSMetaName.Locale, locale); + AddMHSMeta(MHSMetaName.TopicLocale, locale); + AddMHSMeta(MHSMetaName.Id, id); + + if (_toc.ContainsKey(id)) + { + TocInfo tocInfo = _toc[id]; + AddMHSMeta(MHSMetaName.TocParent, tocInfo.Parent); + if (tocInfo.Parent != MHSDefault.TocParent) + AddMHSMeta(MHSMetaName.TocParentVersion, tocInfo.ParentVersion); + AddMHSMeta(MHSMetaName.TocOrder, tocInfo.Order.ToString()); + } + + } + + #endregion + + #region Private + // loads TOC structure from a file + private void LoadToc(string path) + { + _toc.Clear(); + using (Stream stream = File.OpenRead(path)) + { + XPathDocument document = new XPathDocument(stream); + XPathNavigator navigator = document.CreateNavigator(); + LoadToc(navigator.SelectSingleNode(TocXPath.Topics), _tocParent, _tocParentVersion); + } + } + // loads TOC structure from an XPathNavigator + private void LoadToc(XPathNavigator navigator, string parent, string parentVersion) + { + int i = -1; + XPathNodeIterator interator = navigator.SelectChildren(TocXPath.Topic, string.Empty); + while (interator.MoveNext()) + { + XPathNavigator current = interator.Current; + string id = current.GetAttribute(TocAttr.Id, string.Empty); + if (!string.IsNullOrEmpty(id)) + { + TocInfo info = new TocInfo(parent, parentVersion, ++i); + _toc.Add(id, info); + LoadToc(current, id, _topicVersion); + } + } + } + + // Adds Microsoft Help System meta data to the output document + private XmlElement AddMHSMeta(string name, string content) + { + return AddMHSMeta(name, content, false); + } + + // Adds Microsoft Help System meta data to the output document + private XmlElement AddMHSMeta(string name, string content, bool multiple) + { + if (string.IsNullOrEmpty(content)) + return null; + XmlElement elem = null; + if (!multiple) + elem = _document.SelectSingleNode(string.Format(@"//meta[@{0}]", name)) as XmlElement; + if (elem == null) + { + elem = _document.CreateElement(MHSTag.Meta); + elem.SetAttribute(MHSMetaAttr.Name, name); + elem.SetAttribute(MHSMetaAttr.Content, content); + _head.AppendChild(elem); + } + return elem; + } + + // Modifies an attribute value to prevent conflicts with Microsoft Help System branding + private void ModifyAttribute(string name, string value) + { + XmlNodeList list = _document.SelectNodes(string.Format(@"//*[@{0}='{1}']", name, value)); + foreach (XmlElement elem in list) + elem.SetAttribute(name, value + MHSDefault.ShortName); + } + + // Works around a Microsoft Help System issue ('background' attribute isn't supported): + // adds a hidden image so that its path will be transformed by MHS runtime handler, + // sets the 'background' attribute to the transformed path on page load + private void FixHeaderBottomBackground(string className, string newId) + { + XmlElement elem = _document.SelectSingleNode(string.Format(@"//*[@class='{0}']", className)) as XmlElement; + if (elem == null) + return; + + string src = elem.GetAttribute("background"); + if (string.IsNullOrEmpty(src)) + return; + elem.SetAttribute("id", newId); + + XmlElement img = _document.CreateElement("img"); + img.SetAttribute("src", src); + img.SetAttribute("id", newId + "Image"); + img.SetAttribute("style", "display: none"); + + elem.AppendChild(img); + } + + #endregion + } +} diff --git a/tools/Sandcastle/Source/BuildAssembler/BuildComponents/Properties/AssemblyInfo.cs b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/Properties/AssemblyInfo.cs index 41965fc..c15c5d6 100644 --- a/tools/Sandcastle/Source/BuildAssembler/BuildComponents/Properties/AssemblyInfo.cs +++ b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/Properties/AssemblyInfo.cs @@ -38,5 +38,5 @@ using System.Runtime.InteropServices; // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("2.5.10626.00")] -[assembly: AssemblyFileVersion("2.5.10626.00")] +[assembly: AssemblyVersion("2.6.10621.1")] +[assembly: AssemblyFileVersion("2.6.10621.1")] diff --git a/tools/Sandcastle/Source/BuildAssembler/BuildComponents/ResolveConceptualLinksComponent.cs b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/ResolveConceptualLinksComponent.cs index 2531e23..c830fef 100644 --- a/tools/Sandcastle/Source/BuildAssembler/BuildComponents/ResolveConceptualLinksComponent.cs +++ b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/ResolveConceptualLinksComponent.cs @@ -168,6 +168,11 @@ namespace Microsoft.Ddue.Tools { writer.WriteAttributeString("keywords", link.Target.ToLower()); writer.WriteAttributeString("tabindex", "0"); break; + case LinkType.Id: + string xhelp = String.Format("ms-xhelp://?Id={0}", link.Target); + writer.WriteStartElement("a"); + writer.WriteAttributeString("href", xhelp); + break; } // write the link text @@ -215,7 +220,8 @@ namespace Microsoft.Ddue.Tools { internal enum LinkType { None, // not active Local, // a href - Index // mshelp:link keyword + Index, // mshelp:link keyword + Id // ms-xhelp link //Regex // regular expression with match/replace } diff --git a/tools/Sandcastle/Source/BuildAssembler/BuildComponents/ResolveReferenceLinksComponent2.cs b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/ResolveReferenceLinksComponent2.cs index 22587ac..5ba0869 100644 --- a/tools/Sandcastle/Source/BuildAssembler/BuildComponents/ResolveReferenceLinksComponent2.cs +++ b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/ResolveReferenceLinksComponent2.cs @@ -281,6 +281,12 @@ namespace Microsoft.Ddue.Tools { writer.WriteAttributeString("href", msdnUrl); writer.WriteAttributeString("target", linkTarget); break; + case LinkType2.Id: + string xhelp = String.Format("ms-xhelp://?Id={0}", targetId); + xhelp = xhelp.Replace("#", "%23"); + writer.WriteStartElement("a"); + writer.WriteAttributeString("href", xhelp); + break; } // write the link text diff --git a/tools/Sandcastle/Source/BuildAssembler/BuildComponents/SaveComponent.cs b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/SaveComponent.cs index 8b8fea9..6c767ce 100644 --- a/tools/Sandcastle/Source/BuildAssembler/BuildComponents/SaveComponent.cs +++ b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/SaveComponent.cs @@ -53,6 +53,12 @@ namespace Microsoft.Ddue.Tools { linkPath = save_node.GetAttribute("link", String.Empty); if (String.IsNullOrEmpty(linkPath)) linkPath = "../html"; + // add-xhtml-namespace adds a default namespace for xhtml. Required by Help3 documentation. + string addXhtmlDeclaration = save_node.GetAttribute("add-xhtml-namespace", String.Empty); + if (!String.IsNullOrEmpty(addXhtmlDeclaration)) + writeXhtmlNamespace = Convert.ToBoolean(addXhtmlDeclaration); + + // encoding settings.CloseOutput = true; @@ -63,6 +69,9 @@ namespace Microsoft.Ddue.Tools { private string linkPath = null; + private bool writeXhtmlNamespace = false; + + public override void Apply (XmlDocument document, string key) { // set the evaluation context @@ -95,6 +104,12 @@ namespace Microsoft.Ddue.Tools { string targetDirectory = Path.GetDirectoryName(path); if (!Directory.Exists(targetDirectory)) Directory.CreateDirectory(targetDirectory); + if (writeXhtmlNamespace) + { + document.DocumentElement.SetAttribute("xmlns", "http://www.w3.org/1999/xhtml"); + document.LoadXml(document.OuterXml); + } + // save the document // select_expression determines which nodes get saved. If there is no select_expression // we simply save the root node as before. If there is a select_expression, we evaluate the @@ -130,16 +145,16 @@ namespace Microsoft.Ddue.Tools { settings.ConformanceLevel = ConformanceLevel.Auto; using (StreamWriter output = File.CreateText(path)) { using (XmlWriter writer = XmlWriter.Create(output, settings)) { - XPathExpression select_xpath = select_expression.Clone(); - select_xpath.SetContext(context); - XPathNodeIterator ni = document.CreateNavigator().Select(select_expression); - while (ni.MoveNext()) { - if (ni.Current.NodeType == XPathNodeType.ProcessingInstruction && ni.Current.Name.Equals("literal-text")) { - writer.Flush(); - output.Write(ni.Current.Value); - } - else - ni.Current.WriteSubtree(writer); + XPathExpression select_xpath = select_expression.Clone(); + select_xpath.SetContext(context); + XPathNodeIterator ni = document.CreateNavigator().Select(select_expression); + while (ni.MoveNext()) { + if (ni.Current.NodeType == XPathNodeType.ProcessingInstruction && ni.Current.Name.Equals("literal-text")) { + writer.Flush(); + output.Write(ni.Current.Value); + } + else + ni.Current.WriteSubtree(writer); } } } diff --git a/tools/Sandcastle/Source/BuildAssembler/BuildComponents/SnippetComponent.cs b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/SnippetComponent.cs index d4a3d68..a42e067 100644 --- a/tools/Sandcastle/Source/BuildAssembler/BuildComponents/SnippetComponent.cs +++ b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/SnippetComponent.cs @@ -1135,9 +1135,6 @@ namespace Microsoft.Ddue.Tools string[] stringSeparators = new string[] { "\r\n" }; string[] lines = text.Split(stringSeparators, StringSplitOptions.None); - // no need to do this if there is only one line - if (lines.Length == 1) return (lines[0]); - // figure out how many leading spaces to delete int spaces = Int32.MaxValue; for (int i = 0; i < lines.Length; i++) diff --git a/tools/Sandcastle/Source/BuildAssembler/BuildComponents/TargetCollection.cs b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/TargetCollection.cs index 188da53..c956b5e 100644 --- a/tools/Sandcastle/Source/BuildAssembler/BuildComponents/TargetCollection.cs +++ b/tools/Sandcastle/Source/BuildAssembler/BuildComponents/TargetCollection.cs @@ -2733,7 +2733,8 @@ namespace Microsoft.Ddue.Tools { Local, Index, LocalOrIndex, - Msdn + Msdn, + Id } }
\ No newline at end of file |