diff --git a/src/Umbraco.Core/StringExtensions.cs b/src/Umbraco.Core/StringExtensions.cs index edf336463b..f631fa5614 100644 --- a/src/Umbraco.Core/StringExtensions.cs +++ b/src/Umbraco.Core/StringExtensions.cs @@ -663,6 +663,80 @@ namespace Umbraco.Core : alternative; } + /// + /// Returns a copy of the string with the first character converted to uppercase. + /// + /// The string. + /// The converted string. + public static string ToFirstUpper(this string input) + { + return string.IsNullOrWhiteSpace(input) + ? input + : input.Substring(0, 1).ToUpper() + input.Substring(1); + } + + /// + /// Returns a copy of the string with the first character converted to lowercase. + /// + /// The string. + /// The converted string. + public static string ToFirstLower(this string input) + { + return string.IsNullOrWhiteSpace(input) + ? input + : input.Substring(0, 1).ToLower() + input.Substring(1); + } + + /// + /// Returns a copy of the string with the first character converted to uppercase using the casing rules of the specified culture. + /// + /// The string. + /// The culture. + /// The converted string. + public static string ToFirstUpper(this string input, CultureInfo culture) + { + return string.IsNullOrWhiteSpace(input) + ? input + : input.Substring(0, 1).ToUpper(culture) + input.Substring(1); + } + + /// + /// Returns a copy of the string with the first character converted to lowercase using the casing rules of the specified culture. + /// + /// The string. + /// The culture. + /// The converted string. + public static string ToFirstLower(this string input, CultureInfo culture) + { + return string.IsNullOrWhiteSpace(input) + ? input + : input.Substring(0, 1).ToLower(culture) + input.Substring(1); + } + + /// + /// Returns a copy of the string with the first character converted to uppercase using the casing rules of the invariant culture. + /// + /// The string. + /// The converted string. + public static string ToFirstUpperInvariant(this string input) + { + return string.IsNullOrWhiteSpace(input) + ? input + : input.Substring(0, 1).ToUpperInvariant() + input.Substring(1); + } + + /// + /// Returns a copy of the string with the first character converted to lowercase using the casing rules of the invariant culture. + /// + /// The string. + /// The converted string. + public static string ToFirstLowerInvariant(this string input) + { + return string.IsNullOrWhiteSpace(input) + ? input + : input.Substring(0, 1).ToLowerInvariant() + input.Substring(1); + } + /// /// Gets the short string helper. /// diff --git a/src/Umbraco.Core/Strings/LegacyShortStringHelper.cs b/src/Umbraco.Core/Strings/LegacyShortStringHelper.cs index 198b95185c..8fccca18cd 100644 --- a/src/Umbraco.Core/Strings/LegacyShortStringHelper.cs +++ b/src/Umbraco.Core/Strings/LegacyShortStringHelper.cs @@ -117,17 +117,17 @@ function isValidAlias(alias) {{ for (var i = 0; i < aliasLength; i++) { var currentChar = text.Substring(i, 1); - if (validAliasCharacters.Contains(currentChar.ToLower())) + if (validAliasCharacters.Contains(currentChar.ToLowerInvariant())) { // check for camel (if previous character is a space, we'll upper case the current one - if (safeString.Length == 0 && invalidFirstCharacters.Contains(currentChar.ToLower())) + if (safeString.Length == 0 && invalidFirstCharacters.Contains(currentChar.ToLowerInvariant())) { //currentChar = ""; } else { if (i < aliasLength - 1 && i > 0 && text.Substring(i - 1, 1) == " ") - currentChar = currentChar.ToUpper(); + currentChar = currentChar.ToUpperInvariant(); safeString.Append(currentChar); } diff --git a/src/Umbraco.Tests/CoreStrings/CmsHelperCasingTests.cs b/src/Umbraco.Tests/CoreStrings/CmsHelperCasingTests.cs new file mode 100644 index 0000000000..a4868ded50 --- /dev/null +++ b/src/Umbraco.Tests/CoreStrings/CmsHelperCasingTests.cs @@ -0,0 +1,53 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using NUnit.Framework; +using Umbraco.Core; +using Umbraco.Core.Strings; +using Umbraco.Core.ObjectResolution; + +namespace Umbraco.Tests.CoreStrings +{ + [TestFixture] + public class CmsHelperCasingTests + { + [TestCase("thisIsTheEnd", "This Is The End")] + [TestCase("th", "Th")] + [TestCase("t", "t")] + [TestCase("thisis", "Thisis")] + [TestCase("ThisIsTheEnd", "This Is The End")] + [TestCase("WhoIsNumber6InTheVillage", "Who Is Number6 In The Village")] + public void SpaceCamelCasing(string input, string expected) + { + var output = umbraco.cms.helpers.Casing.SpaceCamelCasing(input); + Assert.AreEqual(expected, output); + } + + [TestCase("thisIsTheEnd", "This Is The End")] + [TestCase("th", "Th")] + [TestCase("t", "t")] + [TestCase("thisis", "Thisis")] + [TestCase("ThisIsTheEnd", "This Is The End")] + [TestCase("WhoIsNumber6InTheVillage", "Who Is Number6 In The Village", IgnoreReason = "Legacy has issues with numbers.")] + public void CompatibleLegacyReplacement(string input, string expected) + { + var helper = new LegacyShortStringHelper(); + var output = input.Length < 2 ? input : helper.SplitPascalCasing(input, ' ').ToFirstUpperInvariant(); + Assert.AreEqual(expected, output); + } + + [TestCase("thisIsTheEnd", "This Is The End")] + [TestCase("th", "Th")] + [TestCase("t", "t")] + [TestCase("thisis", "Thisis")] + [TestCase("ThisIsTheEnd", "This Is The End")] + [TestCase("WhoIsNumber6InTheVillage", "Who Is Number6 In The Village")] + public void CompatibleDefaultReplacement(string input, string expected) + { + var helper = new DefaultShortStringHelper(); + var output = input.Length < 2 ? input : helper.SplitPascalCasing(input, ' ').ToFirstUpperInvariant(); + Assert.AreEqual(expected, output); + } + } +} diff --git a/src/Umbraco.Tests/CoreStrings/StringExtensionsTests.cs b/src/Umbraco.Tests/CoreStrings/StringExtensionsTests.cs index 2e14788b9e..896a572077 100644 --- a/src/Umbraco.Tests/CoreStrings/StringExtensionsTests.cs +++ b/src/Umbraco.Tests/CoreStrings/StringExtensionsTests.cs @@ -80,6 +80,28 @@ namespace Umbraco.Tests.CoreStrings Assert.AreEqual(shouldBe, trimmed); } + [TestCase(null, null)] + [TestCase("", "")] + [TestCase("x", "X")] + [TestCase("xyzT", "XyzT")] + [TestCase("XyzT", "XyzT")] + public void ToFirstUpper(string input, string expected) + { + var output = input.ToFirstUpper(); + Assert.AreEqual(expected, output); + } + + [TestCase(null, null)] + [TestCase("", "")] + [TestCase("X", "x")] + [TestCase("XyZ", "xyZ")] + [TestCase("xyZ", "xyZ")] + public void ToFirstLower(string input, string expected) + { + var output = input.ToFirstLower(); + Assert.AreEqual(expected, output); + } + // FORMAT STRINGS // note: here we just ensure that the proper helper gets called properly diff --git a/src/Umbraco.Tests/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj index c8a4b7b752..ba566b5aba 100644 --- a/src/Umbraco.Tests/Umbraco.Tests.csproj +++ b/src/Umbraco.Tests/Umbraco.Tests.csproj @@ -156,6 +156,7 @@ + diff --git a/src/Umbraco.Web/umbraco.presentation/helper.cs b/src/Umbraco.Web/umbraco.presentation/helper.cs index 7a965d09ae..2f0f93a8cd 100644 --- a/src/Umbraco.Web/umbraco.presentation/helper.cs +++ b/src/Umbraco.Web/umbraco.presentation/helper.cs @@ -2,7 +2,8 @@ using System; using System.Collections; using System.Text.RegularExpressions; using System.Web; - +using Umbraco.Core; +using Umbraco.Core.CodeAnnotations; using umbraco.BusinessLogic; using System.Xml; using umbraco.presentation; @@ -149,9 +150,10 @@ namespace umbraco return attributeValue; } + [UmbracoWillObsolete("We should really obsolete that one.")] public static string SpaceCamelCasing(string text) { - return cms.helpers.Casing.SpaceCamelCasing(text); + return text.SplitPascalCasing().ToFirstUpperInvariant(); } [Obsolete("Use umbraco.presentation.UmbracContext.Current.GetBaseUrl()")] diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/BaseTree.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/BaseTree.cs index 464d2f439e..caadca5caa 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/BaseTree.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/BaseTree.cs @@ -468,7 +468,7 @@ namespace umbraco.cms.presentation.Trees { ApplicationTree tree = ApplicationTree.getByAlias(alias); if (tree != null) - return helper.SpaceCamelCasing(tree.Title); + return tree.Title.SplitPascalCasing().ToFirstUpperInvariant(); } return treeCaption; } diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/controls/ContentTypeControlNew.ascx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/controls/ContentTypeControlNew.ascx.cs index 58476e154d..395de64482 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/controls/ContentTypeControlNew.ascx.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/controls/ContentTypeControlNew.ascx.cs @@ -274,7 +274,12 @@ namespace umbraco.controls // nh css file update, add support for css sprites foreach (string iconClass in cms.businesslogic.CMSNode.DefaultIconClasses) { - ListItem li = new ListItem(helper.SpaceCamelCasing((iconClass.Substring(1, iconClass.Length - 1))).Replace("Spr Tree", "").Trim(), iconClass); + var liText = iconClass + .Substring(1) + .SplitPascalCasing().ToFirstUpperInvariant() + .Replace("Spr Tree", "") + .Trim(); + ListItem li = new ListItem(liText, iconClass); li.Attributes.Add("class", "spriteBackground sprTree " + iconClass.Trim('.')); li.Attributes.Add("style", "padding-left:20px !important; background-repeat:no-repeat;"); diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/create/DLRScripting.ascx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/create/DLRScripting.ascx.cs index 55512371f3..58ecb44151 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/create/DLRScripting.ascx.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/create/DLRScripting.ascx.cs @@ -10,6 +10,7 @@ using System.Web.UI.HtmlControls; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Xml.Linq; +using Umbraco.Core; using umbraco.cms.businesslogic.macro; using umbraco.scripting; using umbraco.BasePages; @@ -75,7 +76,8 @@ namespace umbraco.presentation.create { string filename = System.IO.Path.GetFileName(fi.FullName); - list.Items.Add(new ListItem(helper.SpaceCamelCasing(filename.Replace(extension, "")), scriptType + "/" + filename)); + var liText = filename.Replace(extension, "").SplitPascalCasing().ToFirstUpperInvariant(); + list.Items.Add(new ListItem(liText, scriptType + "/" + filename)); } } } diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/create/DLRScriptingTasks.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/create/DLRScriptingTasks.cs index c1807623b1..2a2ecfee37 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/create/DLRScriptingTasks.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/create/DLRScriptingTasks.cs @@ -1,6 +1,7 @@ using System; using System.Data; using System.Web.Security; +using Umbraco.Core; using Umbraco.Core.Logging; using umbraco.BusinessLogic; using umbraco.DataLayer; @@ -101,8 +102,10 @@ namespace umbraco if (ParentID == 1) { - cms.businesslogic.macro.Macro m = cms.businesslogic.macro.Macro.MakeNew( - helper.SpaceCamelCasing(fileName.Substring(0, (fileName.LastIndexOf('.') + 1)).Trim('.'))); + var name = fileName + .Substring(0, (fileName.LastIndexOf('.') + 1)).Trim('.') + .SplitPascalCasing().ToFirstUpperInvariant(); + cms.businesslogic.macro.Macro m = cms.businesslogic.macro.Macro.MakeNew(name); m.ScriptingFile = fileName; } } diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/create/PartialViewTasks.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/create/PartialViewTasks.cs index 8000928d39..34552fa879 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/create/PartialViewTasks.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/create/PartialViewTasks.cs @@ -79,8 +79,10 @@ namespace umbraco // Create macro? if (ParentID == 1) { - var m = cms.businesslogic.macro.Macro.MakeNew( - helper.SpaceCamelCasing(fileName.Substring(0, (fileName.LastIndexOf('.') + 1)).Trim('.'))); + var name = fileName + .Substring(0, (fileName.LastIndexOf('.') + 1)).Trim('.') + .SplitPascalCasing().ToFirstUpperInvariant(); + var m = cms.businesslogic.macro.Macro.MakeNew(name); m.ScriptingFile = BasePath + fileName; } diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/create/XsltTasks.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/create/XsltTasks.cs index 147f2a7753..7f2d7f42a6 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/create/XsltTasks.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/create/XsltTasks.cs @@ -1,6 +1,7 @@ using System; using System.Data; using System.Web.Security; +using Umbraco.Core; using Umbraco.Core.IO; using Umbraco.Core.Logging; using umbraco.BusinessLogic; @@ -87,9 +88,10 @@ namespace umbraco // Create macro? if (ParentID == 1) { + var name = _alias.Substring(_alias.IndexOf("|||") + 3, _alias.Length - _alias.IndexOf("|||") - 3) + .SplitPascalCasing().ToFirstUpperInvariant(); cms.businesslogic.macro.Macro m = - cms.businesslogic.macro.Macro.MakeNew( - helper.SpaceCamelCasing(_alias.Substring(_alias.IndexOf("|||") + 3, _alias.Length - _alias.IndexOf("|||") - 3))); + cms.businesslogic.macro.Macro.MakeNew(name); m.Xslt = fileName + ".xslt"; } } diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/create/xslt.ascx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/create/xslt.ascx.cs index cdfd09b212..bbeb230300 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/create/xslt.ascx.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/create/xslt.ascx.cs @@ -5,6 +5,7 @@ using System.Web; using System.Web.UI.WebControls; using System.Web.UI.HtmlControls; using System.IO; +using Umbraco.Core; using Umbraco.Core.IO; using umbraco.cms.helpers; using umbraco.BasePages; @@ -27,8 +28,10 @@ namespace umbraco.presentation.create { FileInfo fi = new FileInfo(fileName); if (fi.Name != "Clean.xslt") - xsltTemplate.Items.Add(new ListItem(helper.SpaceCamelCasing(fi.Name.Replace(".xslt", "")), fi.Name)); - + { + var liText = fi.Name.Replace(".xslt", "").SplitPascalCasing().ToFirstUpperInvariant(); + xsltTemplate.Items.Add(new ListItem(liText, fi.Name)); + } } } diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/settings/editTemplate.aspx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/settings/editTemplate.aspx.cs index 8e24df4b19..ae84aac0dc 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/settings/editTemplate.aspx.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/settings/editTemplate.aspx.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.IO; using System.Web.UI; using System.Web.UI.WebControls; +using Umbraco.Core; using umbraco.BasePages; using umbraco.BusinessLogic; using umbraco.cms.businesslogic.skinning; @@ -194,7 +195,7 @@ namespace umbraco.cms.presentation.settings files.Add(new KeyValuePair( filename, - helper.SpaceCamelCasing(filename.Replace(extension, "")) + filename.Replace(extension, "").SplitPascalCasing().ToFirstUpperInvariant() )); } } diff --git a/src/umbraco.cms/businesslogic/Files/UmbracoFile.cs b/src/umbraco.cms/businesslogic/Files/UmbracoFile.cs index d7aa033e25..475446921a 100644 --- a/src/umbraco.cms/businesslogic/Files/UmbracoFile.cs +++ b/src/umbraco.cms/businesslogic/Files/UmbracoFile.cs @@ -6,6 +6,7 @@ using System.Drawing.Imaging; using System.IO; using System.Linq; using System.Web; +using Umbraco.Core; using Umbraco.Core.IO; using Encoder = System.Text.Encoder; @@ -139,7 +140,7 @@ namespace umbraco.cms.businesslogic.Files public string GetFriendlyName() { - return helpers.Casing.SpaceCamelCasing(_fileName); + return _fileName.SplitPascalCasing().ToFirstUpperInvariant(); } public System.Tuple GetDimensions() diff --git a/src/umbraco.cms/helpers/Casing.cs b/src/umbraco.cms/helpers/Casing.cs index a565f632b0..4e06d1d7ab 100644 --- a/src/umbraco.cms/helpers/Casing.cs +++ b/src/umbraco.cms/helpers/Casing.cs @@ -1,6 +1,8 @@ using System; using System.Linq; using System.Text; +using Umbraco.Core; +using Umbraco.Core.CodeAnnotations; namespace umbraco.cms.helpers { @@ -25,64 +27,25 @@ namespace umbraco.cms.helpers [Obsolete("Use Umbraco.Core.StringExtensions.ToSafeAlias instead")] public static string SafeAlias(string alias) { - var safeString = new StringBuilder(); - var aliasLength = alias.Length; - for (var i = 0; i < aliasLength;i++ ) - { - var currentChar = alias.Substring(i, 1); - if (VALID_ALIAS_CHARACTERS.Contains(currentChar.ToLowerInvariant())) - { - // check for camel (if previous character is a space, we'll upper case the current one - if (safeString.Length == 0 && INVALID_FIRST_CHARACTERS.Contains(currentChar.ToLowerInvariant())) - { - currentChar = ""; - } - else - { - // first char should always be lowercase (camel style) - // Skipping this check as it can cause incompatibility issues with 3rd party packages - if (i < aliasLength - 1 && i > 0 && alias.Substring(i - 1, 1) == " ") - currentChar = currentChar.ToUpperInvariant(); - - safeString.Append(currentChar); - } - } - } - - return safeString.ToString(); + return alias.ToSafeAlias(); // and anyway the code is the same } [Obsolete("Use Umbraco.Core.StringExtensions.ToSafeAliasWithForcingCheck instead")] public static string SafeAliasWithForcingCheck(string alias) { - return UmbracoSettings.ForceSafeAliases ? SafeAlias(alias) : alias; + return alias.ToSafeAliasWithForcingCheck(); // and anyway the code is the same } //NOTE: Not sure what this actually does but is used a few places, need to figure it out and then move to StringExtensions and obsolete. + // it basically is yet another version of SplitPascalCasing + // plugging string extensions here to be 99% compatible + // the only diff. is with numbers, Number6Is was "Number6 Is", and the new string helper does it too, + // but the legacy one does "Number6Is"... assuming it is not a big deal. + [UmbracoWillObsolete("We should really obsolete that one too.")] public static string SpaceCamelCasing(string text) { - var s = text; - - if (2 > s.Length) - return s; - - var sb = new StringBuilder(); - var ca = s.ToCharArray(); - ca[0] = char.ToUpperInvariant(ca[0]); - - sb.Append(ca[0]); - for (var i = 1; i < ca.Length - 1; i++) - { - var c = ca[i]; - if (char.IsUpper(c) && (char.IsLower(ca[i + 1]) || char.IsLower(ca[i - 1]))) - { - sb.Append(' '); - } - sb.Append(c); - } - sb.Append(ca[ca.Length - 1]); - return sb.ToString(); + return text.Length < 2 ? text : text.SplitPascalCasing().ToFirstUpperInvariant(); } } }