/// <summary> /// Writes any custom HTML attributes defined in the ConceptualLinkInfo /// to the XmlWriter. /// </summary> private static void WriteHtmlAttributes(XmlWriter writer, ConceptualLinkInfo link) { foreach (var attribute in link.HtmlAttributes) { writer.WriteAttributeString(attribute.Key, attribute.Value); } }
/// <summary> /// This is used to create a conceptual link based on the information /// in the supplied XPath navigator. /// </summary> /// <param name="node">The XPath navigator node from which to load the /// link settings.</param> /// <returns>A conceptual link info object</returns> /// <exception cref="ArgumentNullException">This is thrown if the /// node parameters is null.</exception> public static ConceptualLinkInfo Create(XPathNavigator node) { string target; int pos; if (node == null) { throw new ArgumentNullException("node"); } ConceptualLinkInfo info = new ConceptualLinkInfo(); target = node.GetAttribute("target", string.Empty); // EFW - Added support for an optional anchor name in the target pos = target.IndexOf('#'); if (pos != -1) { info.anchor = target.Substring(pos); target = target.Substring(0, pos); } info.target = target; // EFW - Trim off unwanted whitespace info.text = node.ToString().Trim(); if (node.MoveToFirstAttribute()) { do { if (AllowedHtmlAttributes.Contains(node.Name)) { info.HtmlAttributes.Add(node.Name, node.Value); } }while (node.MoveToNextAttribute()); node.MoveToParent(); } return(info); }
//===================================================================== /// <summary> /// This is implemented to resolve the conceptual links /// </summary> /// <param name="document">The XML document with which to work.</param> /// <param name="key">The key (member name) of the item being /// documented.</param> public override void Apply(XmlDocument document, string key) { ConceptualLinkInfo info; TargetInfo targetInfo; LinkType linkType; string url, text; foreach (XPathNavigator navigator in BuildComponentUtilities.ConvertNodeIteratorToArray( document.CreateNavigator().Select(conceptualLinks))) { info = ConceptualLinkInfo.Create(navigator); url = text = null; linkType = LinkType.None; if (validGuid.IsMatch(info.Target)) { targetInfo = this.GetTargetInfoFromCache(info.Target.ToLower(CultureInfo.InvariantCulture)); if (targetInfo == null) { // EFW - Removed linkType = Index, broken links should use the None style. text = this.BrokenLinkDisplayText(info.Target, info.Text); base.WriteMessage(MessageLevel.Warn, String.Format(CultureInfo.InvariantCulture, "Unknown conceptual link target '{0}'.", info.Target)); } else { url = targetInfo.Url; // EFW - Append the anchor if one was specified if (!String.IsNullOrEmpty(info.Anchor)) { url += info.Anchor; } // EFW - Use the link text if specified if (!String.IsNullOrEmpty(info.Text)) { text = info.Text; } else { text = targetInfo.Text; } linkType = targetInfo.LinkType; } } else { // EFW - Removed linkType = Index, broken links should use the None style. text = this.BrokenLinkDisplayText(info.Target, info.Text); base.WriteMessage(MessageLevel.Warn, String.Format(CultureInfo.InvariantCulture, "Invalid conceptual link target '{0}'.", info.Target)); } XmlWriter writer = navigator.InsertAfter(); switch (linkType) { case LinkType.None: writer.WriteStartElement("span"); writer.WriteAttributeString("class", "nolink"); break; case LinkType.Local: writer.WriteStartElement("a"); writer.WriteAttributeString("href", url); WriteHtmlAttributes(writer, info); break; case LinkType.Index: writer.WriteStartElement("mshelp", "link", "http://msdn.microsoft.com/mshelp"); writer.WriteAttributeString("keywords", info.Target.ToLower(CultureInfo.InvariantCulture)); writer.WriteAttributeString("tabindex", "0"); break; case LinkType.Id: writer.WriteStartElement("a"); writer.WriteAttributeString("href", String.Format(CultureInfo.InvariantCulture, "ms-xhelp://?Id={0}", info.Target)); break; } writer.WriteString(text); writer.WriteEndElement(); writer.Close(); navigator.DeleteSelf(); } }