November 23, 2010
@ 08:54 PM

A few years ago I needed the ability to “autolink” text – basically, I had a list of keywords and anytime those keywords were displayed on a page I needed to have them turned into a link. The code is relatively straightforward, but I thought it might be of some use to other people.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

namespace RCSSolutions
{
    public class Term
    {
        public string LinkTerm { get; set; }       
        public string Url { get; set; }
        public string Target { get; set; }
    }

    /// <summary>
    /// Adds links to a passed in string based on records in
    /// the SourceAutolink table.
    /// </summary>
    public class AutoLinker
    {            
        private string m_linkStyle = "";

        /// <summary>List of words which auto link</summary>
        public List<Term> LinkWords { get; set; }

        /// <summary>The CSS class to assign to the link tag</summary>
        public string LinkStyle
        {
            get { return this.m_linkStyle; }
            set { this.m_linkStyle = value; }
        }

        public AutoLinker (List<Term> linkWords)
        {
            LinkWords = linkWords;
        }

        /// <summary>
        /// Adds any links to the passed in content.
        /// </summary>
        /// <param name="content">Content to evaluate</param>
        /// <returns>Marked up results</returns>
        /// <developer>Paul Mrozowski</developer>
        /// <created>07/07/2008</created>
        public string AutoLink(string content)
        {
            if (this.LinkWords == null)
                return content;
           
            StringBuilder result = new StringBuilder();

            // Replaces HTML (and html-like) tags with spaces (we want to keep
            // the same relative positions of everything else in the text since
            // we're going to use them to do the final replacements.)
            string newSentence = Regex.Replace(content,
                                     @"<(.|\n)*?>",
                                     match => " ".PadRight(match.Length));

            string tmpContent = content;

            // Loop through each link term, search for matches. Save each of them into a new collection
            // We're going to use the results to sort the matches in decending order by location. That
            // way we can perform the replacements w/o moving the starting location of the other replacements.
            foreach (var linkRow in LinkWords)
            {
                var allMatches = new List<Match>();
                MatchCollection matches = Regex.Matches(newSentence, linkRow.LinkTerm, RegexOptions.IgnoreCase);
                foreach (Match match in matches)
                    allMatches.Add(match);

                var orderedMatches = from m in allMatches
                                     orderby m.Index descending
                                     select m;

                // General idea is to grab all of the text following the match, get the newly
                // link word w/html markup and insert it before the this text. Then truncate
                // the original content to remove everything from the starting position of the
                // match to the end of file - this is basically done so I don't have to track
                // the current position within the file. After we're done with the loop we
                // insert anything that's left to the beginning of the new string.
                foreach (Match item in orderedMatches)
                {
                    string endOfMatchedStringToEOF = tmpContent.Substring(item.Index + item.Length);
                    result.Insert(0, GetAutolinkText(linkRow, item.Value) + endOfMatchedStringToEOF);
                    tmpContent = tmpContent.Substring(0, item.Index);
                }
            }

            result.Insert(0, tmpContent);

            return result.ToString();
        }

        /// <summary>
        /// Get the replacement text.
        /// </summary>
        /// <param name="token">Word token</param>
        /// <param name="content">Original content</param>
        /// <returns>Empty string if no replacement</returns>
        /// <developer>Paul Mrozowski</developer>
        /// <created>07/08/2008</created>
        private string GetAutolinkText(Term linkTo, string match)
        {
            string newWord = match;

            if (this.m_linkStyle.Length == 0)
                newWord = string.Format("<a href='{0}' ", linkTo.Url);
            else
                newWord = string.Format("<a class='{0}' href='{1}' ",
                                        this.LinkStyle,
                                        linkTo.Url);

            if ((linkTo.Target ?? "").Length > 0)
                newWord += string.Format("target='{0}' ", linkTo.Target);

            // We pass in the original match term to maintain its case (the initial match was case-insensitive).
            newWord += string.Format(">{0}</a>", match);

            return newWord;
        }
    }
}

Usage is simple – create a list of terms that you want linked (along with the URL, style (if any), and target) and pass it to the AutoLinker class, then call AutoLink with your source text. It will return the text with the links embedded in it. Here’s a sample from a console application:

        static void Main(string[] args)
        {
            var terms = new List<Term>();
            terms.Add(new Term() { LinkTerm = "Hello", Target = "_blank", Url = "http://www.rcs-solutions.com" });

            string sentence = "Why, hello! This is a sentence where I'm going to link to the word \"hello\".";
            Console.Write(sentence);
            var linker = new AutoLinker(terms);
           
            Console.Write(linker.AutoLink(sentence));
            Console.ReadKey();
        }

 
Monday, March 07, 2011 6:43:21 AM (Eastern Standard Time, UTC-05:00)


Cheap Flower Girl Dresses - Gorgeous Collection of flower girls dress at cheapest price.
Name
E-mail
(will show your gravatar icon)
Home page

Comment (Some html is allowed: a@href@title, b, i, strike) where the @ means "attribute." For example, you can use <a href="" title=""> or <blockquote cite="Scott">.  

Enter the code shown (prevents robots):

Live Comment Preview