|
using System; |
|
using System.Collections.Generic; |
|
using System.Linq; |
|
using System.Text; |
|
using System.Text.RegularExpressions; |
|
using System.Web; |
|
|
|
namespace Eva.Dominio |
|
{ |
|
public static class StringExtensions |
|
{ |
|
/// <summary> |
|
/// A nicer way of calling <see cref="System.String.IsNullOrEmpty(string)"/> |
|
/// </summary> |
|
/// <param name="value">The string to test.</param> |
|
/// <returns>true if the value parameter is null or an empty string (""); otherwise, false.</returns> |
|
public static bool IsNullOrEmpty(this string value) |
|
{ |
|
return string.IsNullOrEmpty(value); |
|
} |
|
|
|
/// <summary> |
|
/// A nicer way of calling the inverse of <see cref="System.String.IsNullOrEmpty(string)"/> |
|
/// </summary> |
|
/// <param name="value">The string to test.</param> |
|
/// <returns>true if the value parameter is not null or an empty string (""); otherwise, false.</returns> |
|
public static bool IsNotNullOrEmpty(this string value) |
|
{ |
|
return !value.IsNullOrEmpty(); |
|
} |
|
|
|
/// <summary> |
|
/// A nicer way of calling <see cref="System.String.Format(string, object[])"/> |
|
/// </summary> |
|
/// <param name="format">A composite format string.</param> |
|
/// <param name="args">An object array that contains zero or more objects to format.</param> |
|
/// <returns>A copy of format in which the format items have been replaced by the string representation of the corresponding objects in args.</returns> |
|
public static string FormatWith(this string format, params object[] args) |
|
{ |
|
return string.Format(format, args); |
|
} |
|
|
|
/// <summary> |
|
/// Allows for using strings in null coalescing operations |
|
/// </summary> |
|
/// <param name="value">The string value to check</param> |
|
/// <returns>Null if <paramref name="value"/> is empty or the original value of <paramref name="value"/>.</returns> |
|
public static string NullIfEmpty(this string value) |
|
{ |
|
if (value == string.Empty) |
|
return null; |
|
|
|
return value; |
|
} |
|
|
|
/// <summary> |
|
/// Slugifies a string |
|
/// </summary> |
|
/// <param name="value">The string value to slugify</param> |
|
/// <param name="maxLength">An optional maximum length of the generated slug</param> |
|
/// <returns>A URL safe slug representation of the input <paramref name="value"/>.</returns> |
|
public static string ToSlug(this string value, int? maxLength = null) |
|
{ |
|
if (string.IsNullOrEmpty(value)) |
|
return string.Empty; |
|
// if it's already a valid slug, return it |
|
if (RegexUtils.SlugRegex.IsMatch(value)) |
|
return value; |
|
|
|
return GenerateSlug(value, maxLength); |
|
} |
|
|
|
/// <summary> |
|
/// Converts a string into a slug that allows segments e.g. <example>.blog/2012/07/01/title</example>. |
|
/// Normally used to validate user entered slugs. |
|
/// </summary> |
|
/// <param name="value">The string value to slugify</param> |
|
/// <returns>A URL safe slug with segments.</returns> |
|
public static string ToSlugWithSegments(this string value) |
|
{ |
|
var segments = value.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries); |
|
var result = segments.Aggregate(string.Empty, (slug, segment) => slug += "/" + segment.ToSlug()); |
|
return result.Trim('/'); |
|
} |
|
|
|
/// <summary> |
|
/// Separates a PascalCase string |
|
/// </summary> |
|
/// <example> |
|
/// "ThisIsPascalCase".SeparatePascalCase(); // returns "This Is Pascal Case" |
|
/// </example> |
|
/// <param name="value">The value to split</param> |
|
/// <returns>The original string separated on each uppercase character.</returns> |
|
public static string SeparatePascalCase(this string value) |
|
{ |
|
return Regex.Replace(value, "([A-Z])", " $1").Trim(); |
|
} |
|
|
|
/// <summary> |
|
/// Credit for this method goes to http://stackoverflow.com/questions/2920744/url-slugify-alrogithm-in-cs |
|
/// </summary> |
|
private static string GenerateSlug(string value, int? maxLength = null) |
|
{ |
|
// prepare string, remove accents, lower case and convert hyphens to whitespace |
|
var result = RemoveAccent(value).Replace("-", " ").ToLowerInvariant(); |
|
|
|
result = Regex.Replace(result, @"[^a-z0-9\s-]", string.Empty); // remove invalid characters |
|
result = Regex.Replace(result, @"\s+", " ").Trim(); // convert multiple spaces into one space |
|
|
|
if (maxLength.HasValue) // cut and trim |
|
result = result.Substring(0, result.Length <= maxLength ? result.Length : maxLength.Value).Trim(); |
|
|
|
return Regex.Replace(result, @"\s", "-"); // replace all spaces with hyphens |
|
} |
|
|
|
/// <summary> |
|
/// Returns a string array containing the trimmed substrings in this <paramref name="value"/> |
|
/// that are delimited by the provided <paramref name="separators"/>. |
|
/// </summary> |
|
public static IEnumerable<string> SplitAndTrim(this string value, params char[] separators) |
|
{ |
|
return value.Trim().Split(separators, StringSplitOptions.RemoveEmptyEntries).Select(s => s.Trim()); |
|
} |
|
|
|
/// <summary> |
|
/// Checks if the <paramref name="source"/> contains the <paramref name="input"/> based on the provided <paramref name="comparison"/> rules. |
|
/// </summary> |
|
public static bool Contains(this string source, string input, StringComparison comparison) |
|
{ |
|
return source.IndexOf(input, comparison) >= 0; |
|
} |
|
|
|
/// <summary> |
|
/// Limits the length of the <paramref name="source"/> to the specified <paramref name="maxLength"/>. |
|
/// </summary> |
|
public static string Limit(this string source, int maxLength, string suffix = null) |
|
{ |
|
if (suffix.IsNotNullOrEmpty()) |
|
{ |
|
maxLength = maxLength - suffix.Length; |
|
} |
|
|
|
if (source.Length <= maxLength) |
|
{ |
|
return source; |
|
} |
|
|
|
return string.Concat(source.Substring(0, maxLength).Trim(), suffix ?? string.Empty); |
|
} |
|
|
|
private static string RemoveAccent(string value) |
|
{ |
|
var bytes = Encoding.GetEncoding("Cyrillic").GetBytes(value); |
|
return Encoding.ASCII.GetString(bytes); |
|
} |
|
|
|
//remove tag http://stackoverflow.com/questions/19523913/remove-html-tags-from-string-including-nbsp-in-c-sharp |
|
|
|
private static readonly Regex _tags_ = new Regex(@"<[^>]+?>", RegexOptions.Multiline | RegexOptions.Compiled); |
|
|
|
//add characters that are should not be removed to this regex |
|
private static readonly Regex _notOkCharacter_ = new Regex(@"[^\w;&#@.:/\\?=|%!() -]", RegexOptions.Compiled); |
|
|
|
public static string UnHtml(this string html) |
|
{ |
|
html = HttpUtility.UrlDecode(html); |
|
html = HttpUtility.HtmlDecode(html); |
|
|
|
html = RemoveTag(html, "<!--", "-->"); |
|
html = RemoveTag(html, "<script", "</script>"); |
|
html = RemoveTag(html, "<style", "</style>"); |
|
|
|
//replace matches of these regexes with space |
|
html = _tags_.Replace(html, " "); |
|
html = _notOkCharacter_.Replace(html, " "); |
|
html = SingleSpacedTrim(html); |
|
|
|
return html; |
|
} |
|
|
|
private static string RemoveTag(string html, string startTag, string endTag) |
|
{ |
|
bool bAgain; |
|
do |
|
{ |
|
bAgain = false; |
|
var startTagPos = html.IndexOf(startTag, 0, StringComparison.CurrentCultureIgnoreCase); |
|
if (startTagPos < 0) |
|
continue; |
|
var endTagPos = html.IndexOf(endTag, startTagPos + 1, StringComparison.CurrentCultureIgnoreCase); |
|
if (endTagPos <= startTagPos) |
|
continue; |
|
html = html.Remove(startTagPos, endTagPos - startTagPos + endTag.Length); |
|
bAgain = true; |
|
} while (bAgain); |
|
return html; |
|
} |
|
|
|
private static string SingleSpacedTrim(string inString) |
|
{ |
|
var sb = new StringBuilder(); |
|
var inBlanks = false; |
|
foreach (var c in inString) |
|
{ |
|
switch (c) |
|
{ |
|
case '\r': |
|
case '\n': |
|
case '\t': |
|
case ' ': |
|
if (!inBlanks) |
|
{ |
|
inBlanks = true; |
|
sb.Append(' '); |
|
} |
|
continue; |
|
default: |
|
inBlanks = false; |
|
sb.Append(c); |
|
break; |
|
} |
|
} |
|
return sb.ToString().Trim(); |
|
} |
|
} |
|
} |