diff --git a/src/Umbraco.Core/Strings/DefaultShortStringHelper.cs b/src/Umbraco.Core/Strings/DefaultShortStringHelper.cs index 16aa05d1a0..ef7e43e870 100644 --- a/src/Umbraco.Core/Strings/DefaultShortStringHelper.cs +++ b/src/Umbraco.Core/Strings/DefaultShortStringHelper.cs @@ -64,24 +64,29 @@ namespace Umbraco.Core.Strings } public DefaultShortStringHelper WithConfig( - Func preFilter = null, bool breakTermsOnUpper = true, bool allowLeadingDigits = false) + Func preFilter = null, + bool breakTermsOnUpper = true, bool allowLeadingDigits = false, bool allowUnderscoreInTerm = false) { - return WithConfig(_defaultCulture, CleanStringType.RoleMask, preFilter, breakTermsOnUpper, allowLeadingDigits); + return WithConfig(_defaultCulture, CleanStringType.RoleMask, + preFilter, breakTermsOnUpper, allowLeadingDigits, allowUnderscoreInTerm); } public DefaultShortStringHelper WithConfig(CleanStringType stringRole, - Func preFilter = null, bool breakTermsOnUpper = true, bool allowLeadingDigits = false) + Func preFilter = null, + bool breakTermsOnUpper = true, bool allowLeadingDigits = false, bool allowUnderscoreInTerm = false) { - return WithConfig(_defaultCulture, stringRole, preFilter, breakTermsOnUpper, allowLeadingDigits); + return WithConfig(_defaultCulture, stringRole, + preFilter, breakTermsOnUpper, allowLeadingDigits, allowUnderscoreInTerm); } public DefaultShortStringHelper WithConfig(CultureInfo culture, CleanStringType stringRole, - Func preFilter = null, bool breakTermsOnUpper = true, bool allowLeadingDigits = false) + Func preFilter = null, + bool breakTermsOnUpper = true, bool allowLeadingDigits = false, bool allowUnderscoreInTerm = false) { EnsureNotFrozen(); if (!_configs.ContainsKey(culture)) _configs[culture] = new Dictionary(); - _configs[culture][stringRole] = new HelperConfig(preFilter, breakTermsOnUpper, allowLeadingDigits); + _configs[culture][stringRole] = new HelperConfig(preFilter, breakTermsOnUpper, allowLeadingDigits, allowUnderscoreInTerm); return this; } @@ -94,17 +99,19 @@ namespace Umbraco.Core.Strings AllowLeadingDigits = false; } - public HelperConfig(Func preFilter, bool breakTermsOnUpper, bool allowLeadingDigits) + public HelperConfig(Func preFilter, bool breakTermsOnUpper, bool allowLeadingDigits, bool allowUnderscoreInTerm) : this() { PreFilter = preFilter; BreakTermsOnUpper = breakTermsOnUpper; AllowLeadingDigits = allowLeadingDigits; + AllowUnderscoreInTerm = allowUnderscoreInTerm; } public Func PreFilter { get; private set; } public bool BreakTermsOnUpper { get; private set; } public bool AllowLeadingDigits { get; private set; } + public bool AllowUnderscoreInTerm { get; private set; } public static readonly HelperConfig Empty = new HelperConfig(); } @@ -604,12 +611,13 @@ function isSafeAlias(alias) {{ var isDigit = char.IsDigit(c); var isUpper = char.IsUpper(c); // false for digits, symbols... var isLower = char.IsLower(c); // false for digits, symbols... - var isTerm = char.IsLetterOrDigit(c); // || (config.TermExtraCharacters != null && config.TermExtraCharacters.Contains(c)); + var isUnder = config.AllowUnderscoreInTerm && c == '_'; + var isTerm = char.IsLetterOrDigit(c) || isUnder; switch (state) { case StateBreak: - if (isTerm && (opos > 0 || config.AllowLeadingDigits || !isDigit)) + if (isTerm && (opos > 0 || (!isUnder && (config.AllowLeadingDigits || !isDigit)))) { ipos = i; if (opos > 0 && separator != char.MinValue) diff --git a/src/Umbraco.Tests/CoreStrings/DefaultShortStringHelperTests.cs b/src/Umbraco.Tests/CoreStrings/DefaultShortStringHelperTests.cs index a0e3f6c9e6..b8e9363acc 100644 --- a/src/Umbraco.Tests/CoreStrings/DefaultShortStringHelperTests.cs +++ b/src/Umbraco.Tests/CoreStrings/DefaultShortStringHelperTests.cs @@ -30,16 +30,16 @@ namespace Umbraco.Tests.CoreStrings .WithConfig(CleanStringType.Alias, StripQuotes) .WithConfig(new CultureInfo("fr-FR"), CleanStringType.Alias, WhiteQuotes); - ShortStringHelperResolver.Reset(); - ShortStringHelperResolver.Current = new ShortStringHelperResolver(_helper); - Resolution.Freeze(); + //ShortStringHelperResolver.Reset(); + //ShortStringHelperResolver.Current = new ShortStringHelperResolver(_helper); + //Resolution.Freeze(); } - [TearDown] - public void TearDown() - { - ShortStringHelperResolver.Reset(); - } + //[TearDown] + //public void TearDown() + //{ + // ShortStringHelperResolver.Reset(); + //} static readonly Regex FrenchElisionsRegex = new Regex("\\b(c|d|j|l|m|n|qu|s|t)('|\u8217)", RegexOptions.Compiled | RegexOptions.IgnoreCase); @@ -95,6 +95,30 @@ namespace Umbraco.Tests.CoreStrings Assert.AreEqual(expected, output); } + #region Cases + [TestCase("This is my_little_house so cute.", "thisIsMyLittleHouseSoCute", false)] + [TestCase("This is my_little_house so cute.", "thisIsMy_little_houseSoCute", true)] + [TestCase("This is my_Little_House so cute.", "thisIsMyLittleHouseSoCute", false)] + [TestCase("This is my_Little_House so cute.", "thisIsMy_Little_HouseSoCute", true)] + [TestCase("An UPPER_CASE_TEST to check", "anUpperCaseTestToCheck", false)] + [TestCase("An UPPER_CASE_TEST to check", "anUpper_case_testToCheck", true)] + [TestCase("Trailing_", "trailing", false)] + [TestCase("Trailing_", "trailing_", true)] + [TestCase("_Leading", "leading", false)] + [TestCase("_Leading", "leading", true)] + [TestCase("Repeat___Repeat", "repeatRepeat", false)] + [TestCase("Repeat___Repeat", "repeat___Repeat", true)] + [TestCase("Repeat___repeat", "repeatRepeat", false)] + [TestCase("Repeat___repeat", "repeat___repeat", true)] + #endregion + public void CleanStringWithUnderscore(string input, string expected, bool allowUnderscoreInTerm) + { + var helper = new DefaultShortStringHelper() + .WithConfig(allowUnderscoreInTerm: allowUnderscoreInTerm); + var output = helper.CleanString(input, CleanStringType.Alias | CleanStringType.Ascii | CleanStringType.CamelCase); + Assert.AreEqual(expected, output); + } + #region Cases [TestCase("Home Page", "home-page")] [TestCase("Shannon's Home Page!", "shannons-home-page")] diff --git a/src/Umbraco.Tests/CoreStrings/LegacyShortStringHelperTests.cs b/src/Umbraco.Tests/CoreStrings/LegacyShortStringHelperTests.cs index 71491c2967..45ef075fdb 100644 --- a/src/Umbraco.Tests/CoreStrings/LegacyShortStringHelperTests.cs +++ b/src/Umbraco.Tests/CoreStrings/LegacyShortStringHelperTests.cs @@ -11,7 +11,13 @@ namespace Umbraco.Tests.CoreStrings [TestFixture] public class LegacyShortStringHelperTests { - readonly LegacyShortStringHelper _helper = new LegacyShortStringHelper(); + private LegacyShortStringHelper _helper; + + [SetUp] + public void Setup() + { + _helper = new LegacyShortStringHelper(); + } #region Cases [TestCase("foo", "foo")]