Example #1
0
        // EFW - Removed unused properties

        #region Constructor
        //=====================================================================

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="targetDir">The target directory</param>
        /// <param name="urlExp">The URL expression</param>
        /// <param name="textExp">The text (title) expression</param>
        /// <param name="linkTextExp">The alternate link text expression</param>
        /// <param name="typeOfLink">The link type</param>
        /// <exception cref="ArgumentNullException">This is thrown if the directory, URL expression, or either
        /// text expression is null.</exception>
        public TargetDirectory(string targetDir, XPathExpression urlExp,
                               XPathExpression textExp, XPathExpression linkTextExp, ConceptualLinkType typeOfLink)
        {
            if (targetDir == null)
            {
                throw new ArgumentNullException("targetDir");
            }

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

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

            // EFW - Added support for alternate link text expression
            if (linkTextExp == null)
            {
                throw new ArgumentNullException("linkTextExp");
            }

            directory          = targetDir;
            urlExpression      = urlExp;
            textExpression     = textExp;
            linkTextExpression = linkTextExp;
            linkType           = typeOfLink;
        }
Example #2
0
        // EFW - Removed unused properties

        #region Constructor
        //=====================================================================

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="targetDir">The target directory</param>
        /// <param name="urlExp">The URL expression</param>
        /// <param name="textExp">The text (title) expression</param>
        /// <param name="linkTextExp">The alternate link text expression</param>
        /// <param name="typeOfLink">The link type</param>
        /// <exception cref="ArgumentNullException">This is thrown if the directory, URL expression, or either
        /// text expression is null.</exception>
        public TargetDirectory(string targetDir, XPathExpression urlExp, XPathExpression textExp,
                               XPathExpression linkTextExp, ConceptualLinkType typeOfLink)
        {
            // EFW - Added support for alternate link text expression
            directory          = targetDir ?? throw new ArgumentNullException(nameof(targetDir));
            urlExpression      = urlExp ?? throw new ArgumentNullException(nameof(urlExp));
            textExpression     = textExp ?? throw new ArgumentNullException(nameof(textExp));
            linkTextExpression = linkTextExp ?? throw new ArgumentNullException(nameof(linkTextExp));
            linkType           = typeOfLink;
        }
Example #3
0
        //=====================================================================

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="targetUrl">The target URL</param>
        /// <param name="targetText">The target's link text</param>
        /// <param name="typeOfLink">The type of link</param>
        /// <exception cref="ArgumentNullException">This is thrown if the target URL or text is null</exception>
        public TargetInfo(string targetUrl, string targetText, ConceptualLinkType typeOfLink)
        {
            if (targetText == null)
            {
                throw new ArgumentNullException(nameof(targetText));
            }

            this.Url      = targetUrl ?? throw new ArgumentNullException(nameof(targetUrl));
            this.Text     = targetText.Trim();
            this.LinkType = typeOfLink;
        }
Example #4
0
 public TargetInfo(string url, string text, ConceptualLinkType type)
 {
     if (url == null)
     {
         throw new ArgumentNullException("url");
     }
     if (text == null)
     {
         throw new ArgumentNullException("url");
     }
     this._url  = url;
     this._text = text;
     this._type = type;
 }
Example #5
0
        //=====================================================================

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="targetUrl">The target URL</param>
        /// <param name="targetText">The target's link text</param>
        /// <param name="typeOfLink">The type of link</param>
        /// <exception cref="ArgumentNullException">This is thrown if the target URL or text is null</exception>
        public TargetInfo(string targetUrl, string targetText, ConceptualLinkType typeOfLink)
        {
            if(targetUrl == null)
                throw new ArgumentNullException("targetUrl");

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

            this.Url = targetUrl;

            // EFW - Use String.Empty or trim off unwanted whitespace
            this.Text = String.IsNullOrEmpty(targetText) ? String.Empty : targetText.Trim();

            this.LinkType = typeOfLink;
        }
Example #6
0
        public ConceptualTargetDirectory(string directory,
                                         XPathExpression urlExpression, XPathExpression textExpression,
                                         ConceptualLinkType type)
            : this(directory, type)
        {
            if (urlExpression == null)
            {
                throw new ArgumentNullException("urlExpression");
            }
            if (textExpression == null)
            {
                throw new ArgumentNullException("textExpression");
            }

            this._urlExpression  = urlExpression;
            this._textExpression = textExpression;
        }
Example #7
0
        public ReferenceLinkComponent(BuildAssembler assembler,
                                      XPathNavigator configuration)
            : base(assembler, configuration)
        {
            _hasMsdnStorage = false;
            _hasTopicLinks  = false;

            _linkTarget = "_blank";
            _hrefFormat = "{0}.htm";

            _baseLinkType = ConceptualLinkType.Null;

            _buildController = BuildComponentController.Controller;

            this.ParseReferenceConfiguration(configuration);
            this.ParseConceptualConfiguration(configuration);
        }
        //=====================================================================

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="targetUrl">The target URL</param>
        /// <param name="targetText">The target's link text</param>
        /// <param name="typeOfLink">The type of link</param>
        /// <exception cref="ArgumentNullException">This is thrown if the target URL or text is null</exception>
        public TargetInfo(string targetUrl, string targetText, ConceptualLinkType typeOfLink)
        {
            if (targetUrl == null)
            {
                throw new ArgumentNullException("targetUrl");
            }

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

            this.Url = targetUrl;

            // EFW - Use String.Empty or trim off unwanted whitespace
            this.Text = String.IsNullOrEmpty(targetText) ? String.Empty : targetText.Trim();

            this.LinkType = typeOfLink;
        }
Example #9
0
        public ConceptualTargetDirectory(string directory, ConceptualLinkType type)
        {
            if (directory == null)
            {
                throw new ArgumentNullException("directory");
            }

            this._directory = directory;
            this._type      = type;

            _fileExpression = XPathExpression.Compile(
                "concat($target,'.cmp.htm')");

            _urlExpression = XPathExpression.Compile(
                "concat(/metadata/topic/@id,'.htm')");

            _textExpression = XPathExpression.Compile(
                "string(/metadata/topic/title)");
        }
Example #10
0
        // EFW - Removed unused properties

        #region Constructor
        //=====================================================================

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="targetDir">The target directory</param>
        /// <param name="urlExp">The URL expression</param>
        /// <param name="textExp">The text (title) expression</param>
        /// <param name="linkTextExp">The alternate link text expression</param>
        /// <param name="typeOfLink">The link type</param>
        /// <exception cref="ArgumentNullException">This is thrown if the directory, URL expression, or either
        /// text expression is null.</exception>
        public TargetDirectory(string targetDir, XPathExpression urlExp,
          XPathExpression textExp, XPathExpression linkTextExp, ConceptualLinkType typeOfLink)
        {
            if(targetDir == null)
                throw new ArgumentNullException("targetDir");

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

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

            // EFW - Added support for alternate link text expression
            if(linkTextExp == null)
                throw new ArgumentNullException("linkTextExp");

            directory = targetDir;
            urlExpression = urlExp;
            textExpression = textExp;
            linkTextExpression = linkTextExp;
            linkType = typeOfLink;
        }
        public ConceptualLinkComponent(BuildAssembler assembler,
                                       XPathNavigator configuration)
            : base(assembler, configuration)
        {
            _baseLinkType     = ConceptualLinkType.Null;
            _targetController = ConceptualTargetController.GetInstance("conceptual");

            XPathNavigator optionsNode = configuration.SelectSingleNode("options");

            if (optionsNode != null)
            {
                string showBrokenLinkTextValue = configuration.GetAttribute(
                    "showBrokenLinkText", String.Empty);
                if (!String.IsNullOrEmpty(showBrokenLinkTextValue))
                {
                    _showBrokenLinkText = Convert.ToBoolean(showBrokenLinkTextValue);
                }

                string tempText = optionsNode.GetAttribute("type", String.Empty);
                if (!String.IsNullOrEmpty(tempText))
                {
                    try
                    {
                        // convert the link type to an enumeration member
                        _baseLinkType = (ConceptualLinkType)Enum.Parse(typeof(ConceptualLinkType),
                                                                       tempText, true);
                    }
                    catch (ArgumentException)
                    {
                        this.WriteMessage(MessageLevel.Error, String.Format(
                                              "'{0}' is not a valid link type.", tempText));
                    }
                }

                tempText = optionsNode.GetAttribute("showText", String.Empty);
                if (!String.IsNullOrEmpty(tempText))
                {
                    _showText = tempText.Equals("true",
                                                StringComparison.OrdinalIgnoreCase);
                }
            }

            XPathNodeIterator targetsNodes = configuration.Select("targets");

            foreach (XPathNavigator targetsNode in targetsNodes)
            {
                // the base directory containing target; required
                string baseValue = targetsNode.GetAttribute("base", String.Empty);
                if (String.IsNullOrEmpty(baseValue))
                {
                    this.WriteMessage(MessageLevel.Error,
                                      "Every targets element must have a base attribute that specifies the path to a directory of target metadata files.");
                }

                baseValue = Environment.ExpandEnvironmentVariables(baseValue);
                if (!Directory.Exists(baseValue))
                {
                    this.WriteMessage(MessageLevel.Error, String.Format(
                                          "The specified target metadata directory '{0}' does not exist.", baseValue));
                }

                // an xpath expression to construct a file name
                // (not currently used; pattern is hard-coded to $target.cmp.xml
                string filesValue = targetsNode.GetAttribute("files", String.Empty);

                // an xpath expression to construct a url
                string          urlValue = targetsNode.GetAttribute("url", String.Empty);
                XPathExpression urlExpression;
                if (String.IsNullOrEmpty(urlValue))
                {
                    urlExpression = XPathExpression.Compile(
                        "concat(/metadata/topic/@id,'.htm')");
                }
                else
                {
                    urlExpression = CompileXPathExpression(urlValue);
                }

                // an xpath expression to construct link text
                string          textValue = targetsNode.GetAttribute("text", String.Empty);
                XPathExpression textExpression;
                if (String.IsNullOrEmpty(textValue))
                {
                    textExpression = XPathExpression.Compile(
                        "string(/metadata/topic/title)");
                }
                else
                {
                    textExpression = CompileXPathExpression(textValue);
                }

                // the type of link to create to targets found in the directory; required
                string typeValue = targetsNode.GetAttribute("type", String.Empty);
                if (String.IsNullOrEmpty(typeValue))
                {
                    WriteMessage(MessageLevel.Error,
                                 "Every targets element must have a type attribute that specifies what kind of link to create to targets found in that directory.");
                }

                // convert the link type to an enumeration member
                ConceptualLinkType type = ConceptualLinkType.None;
                try
                {
                    type = (ConceptualLinkType)Enum.Parse(typeof(ConceptualLinkType), typeValue, true);
                }
                catch (ArgumentException)
                {
                    this.WriteMessage(MessageLevel.Error, String.Format(
                                          "'{0}' is not a valid link type.", typeValue));
                }

                // We have all the required information; create a TargetDirectory
                // and add it to our collection
                ConceptualTargetDirectory targetDirectory = new ConceptualTargetDirectory(baseValue,
                                                                                          urlExpression, textExpression, type);
                _targetController.Add(targetDirectory);
            }

            this.WriteMessage(MessageLevel.Info, String.Format(
                                  "Collected {0} targets directories.", _targetController.Count));
        }
        public override void Apply(XmlDocument document, string key)
        {
            // find links
            XPathNodeIterator linkIterator =
                document.CreateNavigator().Select(conceptualLinks);

            if (linkIterator == null || linkIterator.Count == 0)
            {
                return;
            }

            // copy them to an array, because enumerating through an XPathNodeIterator
            // fails when the nodes in it are altered
            XPathNavigator[] linkNodes =
                BuildComponentUtilities.ConvertNodeIteratorToArray(linkIterator);

            foreach (XPathNavigator linkNode in linkNodes)
            {
                ConceptualLinkInfo link = ConceptualLinkInfo.Create(linkNode);

                // determine url, text, and link type
                string             url  = null;
                string             text = null;
                ConceptualLinkType type = ConceptualLinkType.None;
                bool isValidLink        = validGuid.IsMatch(link.Target);
                if (isValidLink)
                {
                    // a valid link; try to fetch target info
                    TargetInfo target = _targetController[link.Target];
                    if (target == null)
                    {
                        // no target found; issue warning, set link style to none, and text to in-source fall-back
                        //type = LinkType.None;
                        //type = LinkType.Index;
                        text = BrokenLinkDisplayText(link.Target, link.Text);
                        WriteMessage(MessageLevel.Warn, String.Format(
                                         "Unknown conceptual link target '{0}'.", link.Target));
                    }
                    else
                    {
                        // found target; get url, text, and type from stored info
                        url = target.Url;
                        if (link.IsAnchored)
                        {
                            url += link.Anchor;
                        }
                        if (_showText && !String.IsNullOrEmpty(link.Text))
                        {
                            text = link.Text;
                        }
                        else
                        {
                            text = target.Text;
                        }
                        type = target.Type;
                    }
                }
                else
                {
                    // not a valid link; issue warning, set link style to none, and text to invalid target
                    //type = LinkType.None;
                    text = BrokenLinkDisplayText(link.Target, link.Text);
                    WriteMessage(MessageLevel.Warn, String.Format(
                                     "Invalid conceptual link target '{0}'.", link.Target));
                }

                // Override the type, if valid...
                if (_baseLinkType != ConceptualLinkType.Null && type != ConceptualLinkType.None)
                {
                    type = _baseLinkType;
                }

                // write opening link tag and target info
                XmlWriter writer = linkNode.InsertAfter();
                switch (type)
                {
                case ConceptualLinkType.None:
                    writer.WriteStartElement("span");
                    writer.WriteAttributeString("class", "nolink");
                    break;

                case ConceptualLinkType.Local:
                    writer.WriteStartElement("a");
                    writer.WriteAttributeString("href", url);
                    break;

                case ConceptualLinkType.Index:
                    writer.WriteStartElement("mshelp", "link", "http://msdn.microsoft.com/mshelp");
                    writer.WriteAttributeString("keywords", link.Target.ToLower());
                    writer.WriteAttributeString("tabindex", "0");
                    break;

                case ConceptualLinkType.Id:
                    string xhelp = String.Format("ms-xhelp://?Id={0}", link.Target);
                    writer.WriteStartElement("a");
                    writer.WriteAttributeString("href", xhelp);
                    break;
                }

                // write the link text
                writer.WriteString(text);

                // write the closing link tag
                writer.WriteEndElement();
                writer.Close();

                // delete the original tag
                linkNode.DeleteSelf();
            }
        }
        //=====================================================================

        /// <inheritdoc />
        public override void Initialize(XPathNavigator configuration)
        {
            TargetDirectory    targetDirectory;
            XPathExpression    urlExp, textExp, linkTextExp;
            ConceptualLinkType linkType = ConceptualLinkType.None;
            string             attribute, basePath;

            targetDirectories = new TargetDirectoryCollection();

            // This is a simple cache.  If the cache size limit is reached, it clears the cache and starts over
            cache = new Dictionary <string, TargetInfo>(CacheSize);

            attribute = (string)configuration.Evaluate("string(showBrokenLinkText/@value)");

            if (!String.IsNullOrWhiteSpace(attribute))
            {
                showBrokenLinkText = Convert.ToBoolean(attribute, CultureInfo.InvariantCulture);
            }

            foreach (XPathNavigator navigator in configuration.Select("targets"))
            {
                basePath = navigator.GetAttribute("base", String.Empty);

                if (String.IsNullOrEmpty(basePath))
                {
                    base.WriteMessage(MessageLevel.Error, "Every targets element must have a base attribute " +
                                      "that specifies the path to a directory of target metadata files.");
                }

                basePath = Environment.ExpandEnvironmentVariables(basePath);

                if (!Directory.Exists(basePath))
                {
                    base.WriteMessage(MessageLevel.Error, "The specified target metadata directory '{0}' " +
                                      "does not exist.", basePath);
                }

                attribute = navigator.GetAttribute("url", String.Empty);

                if (String.IsNullOrEmpty(attribute))
                {
                    urlExp = XPathExpression.Compile("concat(/metadata/topic/@id,'.htm')");
                }
                else
                {
                    urlExp = this.CompileXPathExpression(attribute);
                }

                attribute = navigator.GetAttribute("text", String.Empty);

                if (String.IsNullOrEmpty(attribute))
                {
                    textExp = XPathExpression.Compile("string(/metadata/topic/title)");
                }
                else
                {
                    textExp = this.CompileXPathExpression(attribute);
                }

                // EFW - Added support for linkText option
                attribute = navigator.GetAttribute("linkText", String.Empty);

                if (String.IsNullOrEmpty(attribute))
                {
                    linkTextExp = XPathExpression.Compile("string(/metadata/topic/linkText)");
                }
                else
                {
                    linkTextExp = this.CompileXPathExpression(attribute);
                }

                attribute = navigator.GetAttribute("type", String.Empty);

                if (String.IsNullOrEmpty(attribute))
                {
                    base.WriteMessage(MessageLevel.Error, "Every targets element must have a type attribute " +
                                      "that specifies what kind of link to create to targets found in that directory.");
                }

                if (!Enum.TryParse <ConceptualLinkType>(attribute, true, out linkType))
                {
                    base.WriteMessage(MessageLevel.Error, "'{0}' is not a valid link type.", attribute);
                }

                targetDirectory = new TargetDirectory(basePath, urlExp, textExp, linkTextExp, linkType);
                targetDirectories.Add(targetDirectory);
            }

            base.WriteMessage(MessageLevel.Info, "Collected {0} targets directories.", targetDirectories.Count);
        }
Example #14
0
        private void ProcessConceptualLink(XPathNavigator linkNode, string key)
        {
            // extract link information
            ConceptualLinkInfo link = ConceptualLinkInfo.Create(linkNode);

            if (link == null)
            {
                this.WriteMessage(MessageLevel.Warn,
                                  "Invalid conceptualLink element.");
#if DEBUG
                this.WriteMessage(MessageLevel.Warn, linkNode.OuterXml);
#endif
            }
            else
            {
                // determine url, text, and link type
                string             url  = null;
                string             text = null;
                ConceptualLinkType type = ConceptualLinkType.None;
                bool isValidLink        = validGuid.IsMatch(link.Target);
                if (isValidLink)
                {
                    // a valid link; try to fetch target info
                    TargetInfo target = _targetController[link.Target];
                    if (target == null)
                    {
                        // no target found; issue warning, set link style to none, and text to in-source fall-back
                        //type = LinkType.None;
                        //type = LinkType.Index;
                        text = BrokenLinkDisplayText(link.Target, link.Text);
                        WriteMessage(MessageLevel.Warn, String.Format(
                                         "Unknown conceptual link target '{0}'.", link.Target));
                    }
                    else
                    {
                        // found target; get url, text, and type from stored info
                        url = target.Url;
                        if (link.IsAnchored)
                        {
                            url += link.Anchor;
                        }
                        if (_showText && !String.IsNullOrEmpty(link.Text))
                        {
                            text = link.Text;
                        }
                        else
                        {
                            text = target.Text;
                        }
                        type = target.Type;
                    }
                }
                else
                {
                    // not a valid link; issue warning, set link style to none, and text to invalid target
                    //type = LinkType.None;
                    text = BrokenLinkDisplayText(link.Target, link.Text);
                    WriteMessage(MessageLevel.Warn, String.Format(
                                     "Invalid conceptual link target '{0}'.", link.Target));
                }

                // Override the type, if valid...
                if (_baseLinkType != ConceptualLinkType.Null && type != ConceptualLinkType.None)
                {
                    type = _baseLinkType;
                }

                // write opening link tag and target info
                XmlWriter writer = linkNode.InsertAfter();
                switch (type)
                {
                case ConceptualLinkType.None:
                    writer.WriteStartElement("span");
                    writer.WriteAttributeString("class", "nolink");
                    break;

                case ConceptualLinkType.Local:
                    writer.WriteStartElement("a");
                    writer.WriteAttributeString("href", url);
                    break;

                case ConceptualLinkType.Index:
                    writer.WriteStartElement("mshelp", "link", "http://msdn.microsoft.com/mshelp");
                    writer.WriteAttributeString("keywords", link.Target.ToLower());
                    writer.WriteAttributeString("tabindex", "0");
                    break;

                case ConceptualLinkType.Id:
                    string xhelp = String.Format("ms-xhelp://?Id={0}", link.Target);
                    writer.WriteStartElement("a");
                    writer.WriteAttributeString("href", xhelp);
                    break;
                }

                // write the link text
                writer.WriteString(text);

                // write the closing link tag
                writer.WriteEndElement();
                writer.Close();
            }
        }