Example #1
0
        public void ExtractMentionsOrListsWithIndicesTest()
        {
            List <string> failures = new List <string>();

            foreach (dynamic test in LoadTestSection <dynamic>("mentions_or_lists_with_indices"))
            {
                try
                {
                    List <Extractor.Entity> actual = extractor.ExtractMentionsOrListsWithIndices(test.text);
                    for (int i = 0; i < actual.Count; i++)
                    {
                        Extractor.Entity entity = actual[i];
                        Assert.AreEqual(test.expected[i].screen_name, entity.Value);
                        Assert.AreEqual(test.expected[i].list_slug, entity.ListSlug);
                        Assert.AreEqual(test.expected[i].indices[0], entity.Start);
                        Assert.AreEqual(test.expected[i].indices[1], entity.End);
                    }
                }
                catch (Exception)
                {
                    failures.Add(test.description + ": " + test.text);
                }
            }
            if (failures.Any())
            {
                Assert.Fail(string.Join("\n", failures));
            }
        }
Example #2
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="text"></param>
        /// <param name="builder"></param>
        public void LinkToCashtag(Extractor.Entity entity, string text, StringBuilder builder)
        {
            string cashtag = entity.Value;

            IDictionary <string, string> attrs = new Dictionary <string, string>();

            attrs["href"]  = CashtagUrlBase + cashtag;
            attrs["title"] = "$" + cashtag;
            attrs["class"] = CashtagClass;

            LinkToTextWithSymbol(entity, "$", cashtag, attrs, builder);
        }
Example #3
0
        public void URLEntitiesTest()
        {
            autolink.NoFollow = true;
            Extractor.Entity entity = new Extractor.Entity(0, 19, "http://t.co/0JG5Mcq", Extractor.EntityType.Url);
            entity.DisplayURL  = "blog.twitter.com/2011/05/twitte…";
            entity.ExpandedURL = "http://blog.twitter.com/2011/05/twitter-for-mac-update.html";
            List <Extractor.Entity> entities = new List <Extractor.Entity>();

            entities.Add(entity);
            String tweet    = "http://t.co/0JG5Mcq";
            String expected = "<a href=\"http://t.co/0JG5Mcq\" title=\"http://blog.twitter.com/2011/05/twitter-for-mac-update.html\" rel=\"nofollow\"><span class='tco-ellipsis'><span style='position:absolute;left:-9999px;'>&nbsp;</span></span><span style='position:absolute;left:-9999px;'>http://</span><span class='js-display-url'>blog.twitter.com/2011/05/twitte</span><span style='position:absolute;left:-9999px;'>r-for-mac-update.html</span><span class='tco-ellipsis'><span style='position:absolute;left:-9999px;'>&nbsp;</span>…</span></a>";

            AssertAutolink(expected, autolink.AutoLinkEntities(tweet, entities));
        }
Example #4
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="symbol"></param>
        /// <param name="text"></param>
        /// <param name="attributes"></param>
        /// <param name="builder"></param>
        public void LinkToTextWithSymbol(Extractor.Entity entity, string symbol, string text, IDictionary <string, string> attributes, StringBuilder builder)
        {
            string taggedSymbol = string.IsNullOrWhiteSpace(SymbolTag) ? symbol : string.Format("<{0}>{1}</{0}>", SymbolTag, symbol);

            text = EscapeHTML(text);
            string taggedText    = string.IsNullOrWhiteSpace(TextWithSymbolTag) ? text : string.Format("<{0}>{1}</{0}>", TextWithSymbolTag, text);
            bool   includeSymbol = UsernameIncludeSymbol || !Regex.AT_SIGNS.IsMatch(symbol);

            if (includeSymbol)
            {
                LinkToText(entity, taggedSymbol.ToString() + taggedText, attributes, builder);
            }
            else
            {
                builder.Append(taggedSymbol);
                LinkToText(entity, taggedText, attributes, builder);
            }
        }
Example #5
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="text"></param>
        /// <param name="builder"></param>
        public void LinkToMentionAndList(Extractor.Entity entity, string text, StringBuilder builder)
        {
            string mention = entity.Value;
            // Get the original at char from text as it could be a full-width char.
            string atChar = text.Substring(entity.Start, 1);

            IDictionary <string, string> attrs = new Dictionary <string, string>();

            if (entity.ListSlug != null)
            {
                mention       += entity.ListSlug;
                attrs["class"] = ListClass;
                attrs["href"]  = ListUrlBase + mention;
            }
            else
            {
                attrs["class"] = UsernameClass;
                attrs["href"]  = UsernameUrlBase + mention;
            }

            LinkToTextWithSymbol(entity, atChar, mention, attrs, builder);
        }
Example #6
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="text"></param>
        /// <param name="builder"></param>
        public void LinkToHashtag(Extractor.Entity entity, string text, StringBuilder builder)
        {
            // Get the original hash char from text as it could be a full-width char.
            string hashChar = text.Substring(entity.Start, 1);
            string hashtag  = entity.Value;

            IDictionary <string, string> attrs = new Dictionary <string, string>();

            attrs["href"]  = HashtagUrlBase + hashtag;
            attrs["title"] = "#" + hashtag;

            if (Regex.RTL_CHARACTERS.IsMatch(text))
            {
                attrs["class"] = HashtagClass + " rtl";
            }
            else
            {
                attrs["class"] = HashtagClass;
            }

            LinkToTextWithSymbol(entity, hashChar, hashtag, attrs, builder);
        }
Example #7
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="entity"></param>
 /// <param name="text"></param>
 /// <param name="attributes"></param>
 /// <param name="builder"></param>
 public void LinkToText(Extractor.Entity entity, string text, IDictionary <string, string> attributes, StringBuilder builder)
 {
     if (NoFollow)
     {
         attributes["rel"] = "nofollow";
     }
     if (LinkAttributeModifier != null)
     {
         LinkAttributeModifier.Modify(entity, attributes);
     }
     if (LinkTextModifier != null)
     {
         text = LinkTextModifier.Modify(entity, text);
     }
     // append <a> tag
     builder.Append("<a");
     foreach (var entry in attributes)
     {
         builder.Append(" ").Append(EscapeHTML(entry.Key)).Append("=\"").Append(EscapeHTML(entry.Value)).Append("\"");
     }
     builder.Append(">").Append(text).Append("</a>");
 }
Example #8
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="text"></param>
        /// <param name="builder"></param>
        public void LinkToURL(Extractor.Entity entity, string text, StringBuilder builder)
        {
            string url      = entity.Value;
            string linkText = EscapeHTML(url);

            if (entity.DisplayURL != null && entity.ExpandedURL != null)
            {
                // Goal: If a user copies and pastes a tweet containing t.co'ed link, the resulting paste
                // should contain the full original URL (expanded_url), not the display URL.
                //
                // Method: Whenever possible, we actually emit HTML that contains expanded_url, and use
                // font-size:0 to hide those parts that should not be displayed (because they are not part of display_url).
                // Elements with font-size:0 get copied even though they are not visible.
                // Note that display:none doesn't work here. Elements with display:none don't get copied.
                //
                // Additionally, we want to *display* ellipses, but we don't want them copied.  To make this happen we
                // wrap the ellipses in a tco-ellipsis class and provide an onCopy handler that sets display:none on
                // everything with the tco-ellipsis class.
                //
                // As an example: The user tweets "hi http://longdomainname.com/foo"
                // This gets shortened to "hi http://t.co/xyzabc", with display_url = "…nname.com/foo"
                // This will get rendered as:
                // <span class='tco-ellipsis'> <!-- This stuff should get displayed but not copied -->
                //   …
                //   <!-- There's a chance the onCopy event handler might not fire. In case that happens,
                //        we include an &nbsp; here so that the … doesn't bump up against the URL and ruin it.
                //        The &nbsp; is inside the tco-ellipsis span so that when the onCopy handler *does*
                //        fire, it doesn't get copied.  Otherwise the copied text would have two spaces in a row,
                //        e.g. "hi  http://longdomainname.com/foo".
                //   <span style='font-size:0'>&nbsp;</span>
                // </span>
                // <span style='font-size:0'>  <!-- This stuff should get copied but not displayed -->
                //   http://longdomai
                // </span>
                // <span class='js-display-url'> <!-- This stuff should get displayed *and* copied -->
                //   nname.com/foo
                // </span>
                // <span class='tco-ellipsis'> <!-- This stuff should get displayed but not copied -->
                //   <span style='font-size:0'>&nbsp;</span>
                //   …
                // </span>
                //
                // Exception: pic.twitter.com images, for which expandedUrl = "https://twitter.com/#!/username/status/1234/photo/1
                // For those URLs, display_url is not a substring of expanded_url, so we don't do anything special to render the elided parts.
                // For a pic.twitter.com URL, the only elided part will be the "https://", so this is fine.
                string displayURLSansEllipses      = entity.DisplayURL.Replace("…", "");
                int    diplayURLIndexInExpandedURL = entity.ExpandedURL.IndexOf(displayURLSansEllipses);
                if (diplayURLIndexInExpandedURL != -1)
                {
                    string beforeDisplayURL  = entity.ExpandedURL.Substring(0, diplayURLIndexInExpandedURL);
                    string afterDisplayURL   = entity.ExpandedURL.Substring(diplayURLIndexInExpandedURL + displayURLSansEllipses.Length);
                    string precedingEllipsis = entity.DisplayURL.StartsWith("…") ? "…" : "";
                    string followingEllipsis = entity.DisplayURL.EndsWith("…") ? "…" : "";
                    string invisibleSpan     = "<span " + InvisibleTagAttrs + ">";

                    StringBuilder sb = new StringBuilder("<span class='tco-ellipsis'>");
                    sb.Append(precedingEllipsis);
                    sb.Append(invisibleSpan).Append("&nbsp;</span></span>");
                    sb.Append(invisibleSpan).Append(EscapeHTML(beforeDisplayURL)).Append("</span>");
                    sb.Append("<span class='js-display-url'>").Append(EscapeHTML(displayURLSansEllipses)).Append("</span>");
                    sb.Append(invisibleSpan).Append(EscapeHTML(afterDisplayURL)).Append("</span>");
                    sb.Append("<span class='tco-ellipsis'>").Append(invisibleSpan).Append("&nbsp;</span>").Append(followingEllipsis).Append("</span>");

                    linkText = sb.ToString();
                }
                else
                {
                    linkText = entity.DisplayURL;
                }
            }

            IDictionary <string, string> attrs = new Dictionary <string, string>();

            attrs["href"] = url;

            if (!string.IsNullOrWhiteSpace(entity.DisplayURL) && !string.IsNullOrWhiteSpace(entity.ExpandedURL))
            {
                attrs["title"] = entity.ExpandedURL;
            }

            if (!string.IsNullOrWhiteSpace(UrlClass))
            {
                attrs["class"] = UrlClass;
            }

            if (!string.IsNullOrWhiteSpace(UrlTarget))
            {
                attrs["target"] = UrlTarget;
            }

            LinkToText(entity, linkText, attrs, builder);
        }