diff --git a/src/Umbraco.Core/Strings/CleanStringType.cs b/src/Umbraco.Core/Strings/CleanStringType.cs
index f681c42d4a..4c53be4cb8 100644
--- a/src/Umbraco.Core/Strings/CleanStringType.cs
+++ b/src/Umbraco.Core/Strings/CleanStringType.cs
@@ -14,25 +14,6 @@ namespace Umbraco.Core.Strings
// note: you have 32 bits at your disposal
// 0xffffffff
-
- // masks
-
- ///
- /// Flag mask for casing.
- ///
- CaseMask = 0x3f, // 0xff - 8 possible values
-
- ///
- /// Flag mask for encoding.
- ///
- CodeMask = 0x700, // 0xff00 - 8 possible values
-
- ///
- /// Flag mask for role.
- ///
- RoleMask = 0x070000, // 0xff0000 - 8 possible values
-
-
// no value
///
@@ -43,6 +24,11 @@ namespace Umbraco.Core.Strings
// casing values
+ ///
+ /// Flag mask for casing.
+ ///
+ CaseMask = PascalCase | CamelCase | Unchanged | LowerCase | UpperCase | UmbracoCase,
+
///
/// Pascal casing eg "PascalCase".
///
@@ -78,6 +64,11 @@ namespace Umbraco.Core.Strings
// encoding values
+ ///
+ /// Flag mask for encoding.
+ ///
+ CodeMask = Unicode | Utf8 | Ascii,
+
///
/// Unicode encoding.
///
@@ -97,6 +88,11 @@ namespace Umbraco.Core.Strings
// role values
+ ///
+ /// Flag mask for role.
+ ///
+ RoleMask = UrlSegment | Alias | FileName | ConvertCase,
+
///
/// Url role.
///
@@ -110,6 +106,11 @@ namespace Umbraco.Core.Strings
///
/// FileName role.
///
- FileName = 0x040000
+ FileName = 0x040000,
+
+ ///
+ /// ConvertCase role.
+ ///
+ ConvertCase = 0x080000
}
}
diff --git a/src/Umbraco.Core/Strings/DefaultShortStringHelper.cs b/src/Umbraco.Core/Strings/DefaultShortStringHelper.cs
index fbbc25ea20..07f262c272 100644
--- a/src/Umbraco.Core/Strings/DefaultShortStringHelper.cs
+++ b/src/Umbraco.Core/Strings/DefaultShortStringHelper.cs
@@ -1,9 +1,20 @@
-using System;
+
+// debugging
+// define WRTCONS to write cleaning details & steps to console
+// leave it wrapped within #if DEBUG to make sure it does leak
+// into RELEASE, see http://issues.umbraco.org/issue/U4-4199
+#if DEBUG
+#undef WRTCONS
+#endif
+
+using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Globalization;
+using System.Text;
+using System.Text.RegularExpressions;
using Umbraco.Core.Configuration;
namespace Umbraco.Core.Strings
@@ -176,6 +187,12 @@ namespace Umbraco.Core.Strings
: (char.IsLetterOrDigit(c) || c == '_'), // letter, digit or underscore
StringType = CleanStringType.Ascii | CleanStringType.UmbracoCase,
BreakTermsOnUpper = false
+ }).WithConfig(CleanStringType.ConvertCase, new Config
+ {
+ PreFilter = null,
+ IsTerm = (c, leading) => char.IsLetterOrDigit(c) || c == '_', // letter, digit or underscore
+ StringType = CleanStringType.Ascii,
+ BreakTermsOnUpper = true
});
}
@@ -503,6 +520,10 @@ function validateSafeAlias(id, value, immediate, callback) {{
if (culture == null)
throw new ArgumentNullException("culture");
+#if WRTCONS
+ Console.WriteLine("STRING TYPE {0}", stringType);
+#endif
+
// get config
var config = GetConfig(stringType, culture);
stringType = config.StringTypeExtend(stringType);
@@ -570,6 +591,9 @@ function validateSafeAlias(id, value, immediate, callback) {{
var state = StateBreak;
caseType &= CleanStringType.CaseMask;
+#if WRTCONS
+ Console.WriteLine("CASE {0}", caseType);
+#endif
// if we apply global ToUpper or ToLower to text here
// then we cannot break words on uppercase chars
@@ -595,13 +619,13 @@ function validateSafeAlias(id, value, immediate, callback) {{
var isPair = char.IsSurrogate(c);
if (isPair)
throw new NotSupportedException("Surrogate pairs are not supported.");
-
- //Console.WriteLine("CHAR '{0}' {1} {2} - {3} - {4}/{5} {6}",
- // c,
- // isTerm ? "term" : "!term", isUpper ? "upper" : "!upper",
- // state,
- // i, ipos, leading ? "leading" : "!leading");
-
+#if WRTCONS
+ Console.WriteLine("CHAR '{0}' {1} {2} - {3} - {4}/{5} {6}",
+ c,
+ isTerm ? "term" : "!term", isUpper ? "upper" : "!upper",
+ state,
+ i, ipos, leading ? "leading" : "!leading");
+#endif
switch (state)
{
// within a break
@@ -708,11 +732,12 @@ function validateSafeAlias(id, value, immediate, callback) {{
CleanStringType caseType, CultureInfo culture, bool isAcronym)
{
var term = input.Substring(ipos, len);
- //Console.WriteLine("TERM \"{0}\" {1} {2}",
- // term,
- // isAcronym ? "acronym" : "word",
- // caseType);
-
+#if WRTCONS
+ Console.WriteLine("TERM \"{0}\" {1} {2}",
+ term,
+ isAcronym ? "acronym" : "word",
+ caseType);
+#endif
if (isAcronym)
{
if ((caseType == CleanStringType.CamelCase && len <= 2 && opos > 0) ||