// Internal for unit testing purposes only.
        private int GetDefaultTeaserLength(TeaserTruncationMode mode)
        {
            switch (mode)
            {
            case TeaserTruncationMode.Length:
                return(defaultLengthAbsolute);

            case TeaserTruncationMode.Character:
                return(defaultLengthCharacters);

            case TeaserTruncationMode.Word:
            default:
                return(defaultLengthWords);
            }
        }
        private string GetModeDescription(TeaserTruncationMode mode)
        {
            switch (mode)
            {
            case TeaserTruncationMode.Length:
                return("string length");

            case TeaserTruncationMode.Character:
                return("letters or digits");

            case TeaserTruncationMode.Word:
            default:
                return("words");
            }
        }
Example #3
0
        public TeaserResult GenerateTeaser(
            TeaserTruncationMode truncationMode,
            int truncationLength,
            string html,
            string cacheKey,
            string slug,
            string languageCode)
        {
            var result = new TeaserResult();

            result.Content     = html;
            result.DidTruncate = false;

            return(result);
        }
        // Internal for unit testing purposes only.
        private string TruncatePost(TeaserTruncationMode mode, string content, int length, bool isRightToLeftLanguage = false)
        {
            var truncateFrom = isRightToLeftLanguage ? TruncateFrom.Left : TruncateFrom.Right;

            switch (mode)
            {
            case TeaserTruncationMode.Length:
                return(content.Truncate(length, terminator, Truncator.FixedLength, truncateFrom));

            case TeaserTruncationMode.Character:
                return(content.Truncate(length, terminator, Truncator.FixedNumberOfCharacters, truncateFrom));

            case TeaserTruncationMode.Word:
            default:
                return(content.Truncate(length, terminator, Truncator.FixedNumberOfWords, truncateFrom));
            }
        }
        private int GetContentLength(string html, TeaserTruncationMode mode)
        {
            if (string.IsNullOrEmpty(html))
            {
                return(0);
            }
            switch (mode)
            {
            case TeaserTruncationMode.Length:
                return(html.Length);

            case TeaserTruncationMode.Character:
                return(html.ToCharArray().Count(char.IsLetterOrDigit));

            case TeaserTruncationMode.Word:
            default:
                return(html.Split((char[])null, StringSplitOptions.RemoveEmptyEntries).Count());
            }
        }
        public TeaserResult GenerateTeaser(
            TeaserTruncationMode truncationMode,
            int truncationLength,
            string html,
            string cacheKey,
            string slug,
            string languageCode)
        {
            var result = new TeaserResult();

            if (string.IsNullOrWhiteSpace(html))
            {
                result.Content     = html;
                result.DidTruncate = false;
                return(result);
            }

            // Try to get language metadata for humanizer.
            var cultureInfo = CultureInfo.InvariantCulture;

            if (!string.IsNullOrEmpty(languageCode))
            {
                try
                {
                    cultureInfo = new CultureInfo(languageCode);
                }
                catch (CultureNotFoundException) { }
            }

            var contentLength = GetContentLength(html, truncationMode);

            if (contentLength <= truncationLength)
            {
                result.Content     = html;
                result.DidTruncate = false;
                return(result);
            }

            if (_cache != null)
            {
                var cachedTeaser = _cache.GetTeaser(cacheKey);
                if (!string.IsNullOrEmpty(cachedTeaser))
                {
                    result.Content     = cachedTeaser;
                    result.DidTruncate = true;
                    return(result);
                }
            }

            var isRightToLeftLanguage = cultureInfo.TextInfo.IsRightToLeft;

            // Get global teaser settings.
            var truncationLengthToUse = truncationLength <= 0 ? GetDefaultTeaserLength(truncationMode) : truncationLength;

            // Truncate the raw content first. In general, Humanizer is smart enough to ignore tags, especially if using word truncation.
            var text = TruncatePost(truncationMode, html, truncationLengthToUse, isRightToLeftLanguage);

            // Don't leave dangling <p> tags.
            HtmlNode.ElementsFlags["p"] = HtmlElementFlag.Closed;

            var modeDesc = GetModeDescription(truncationMode);

            //if we get bad output try increasing the allowed length unti it is valid
            while (!IsValidMarkup(text) && truncationLengthToUse <= contentLength)
            {
                truncationLengthToUse += 1;
                if (_log != null)
                {
                    _log.LogWarning($"teaser truncation for post {slug}, produced invalid html, so trying again and increasing the truncation length to {truncationLengthToUse} {modeDesc}. Might be best to make an explicit teaser for this post.");
                }

                text = TruncatePost(truncationMode, html, truncationLengthToUse, isRightToLeftLanguage);
            }

            if (!IsValidMarkup(text))
            {
                if (_log != null)
                {
                    _log.LogError($"failed to create valid teaser for post {slug}, so returning full content");
                }

                result.Content     = html;
                result.DidTruncate = false;
                return(result);
            }

            if (_cache != null)
            {
                _cache.AddToCache(text, cacheKey);
            }

            var doc = new HtmlDocument();

            doc.LoadHtml(text);

            result.Content     = doc.DocumentNode.InnerHtml;
            result.DidTruncate = true;
            return(result);
        }