Skip to content

Commit f0573fc

Browse files
committed
Fixes: U4-4084 Macro's with non alphanumeric chars in their aliases cannot render in the rich text editor
1 parent eb44480 commit f0573fc

File tree

4 files changed

+103
-11
lines changed

4 files changed

+103
-11
lines changed

src/Umbraco.Core/Macros/MacroTagParser.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ namespace Umbraco.Core.Macros
1212
internal class MacroTagParser
1313
{
1414
private static readonly Regex MacroRteContent = new Regex(@"(<!--\s*?)(<\?UMBRACO_MACRO.*?/>)(\s*?-->)", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Singleline);
15-
private static readonly Regex MacroPersistedFormat = new Regex(@"(<\?UMBRACO_MACRO macroAlias=[""'](\w+?)[""'].+?)(?:/>|>.*?</\?UMBRACO_MACRO>)", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Singleline);
15+
private static readonly Regex MacroPersistedFormat = new Regex(@"(<\?UMBRACO_MACRO macroAlias=[""']([\w\.]+?)[""'].+?)(?:/>|>.*?</\?UMBRACO_MACRO>)", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Singleline);
1616

1717
/// <summary>
1818
/// This formats the persisted string to something useful for the rte so that the macro renders properly since we
@@ -39,8 +39,8 @@ internal static string FormatRichTextPersistedDataForEditor(string persistedCont
3939
//<div class="umb-macro-holder myMacro mceNonEditable">
4040
var alias = match.Groups[2].Value;
4141
var sb = new StringBuilder("<div class=\"umb-macro-holder ");
42-
sb.Append(alias);
43-
sb.Append(" mceNonEditable\"");
42+
//sb.Append(alias.ToSafeAlias());
43+
sb.Append("mceNonEditable\"");
4444
foreach (var htmlAttribute in htmlAttributes)
4545
{
4646
sb.Append(" ");

src/Umbraco.Tests/Macros/MacroParserTests.cs

Lines changed: 85 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,29 @@ public void Format_RTE_Data_For_Editor_With_No_Macros()
1616
Assert.AreEqual(@"<p>hello world</p>", content);
1717
}
1818

19+
[Test]
20+
public void Format_RTE_Data_For_Editor_With_Non_AlphaNumeric_Char_In_Alias()
21+
{
22+
var content = @"<p>asdfasdf</p>
23+
<p>asdfsadf</p>
24+
<?UMBRACO_MACRO macroAlias=""My.Map.isCool"" />
25+
<p>asdfasdf</p>";
26+
var result = MacroTagParser.FormatRichTextPersistedDataForEditor(content, new Dictionary<string, string>() { { "test1", "value1" }, { "test2", "value2" } });
27+
28+
// Assert.AreEqual(@"<p>asdfasdf</p>
29+
//<p>asdfsadf</p>
30+
//<div class=""umb-macro-holder Map mceNonEditable"" test1=""value1"" test2=""value2"">
31+
//<!-- <?UMBRACO_MACRO macroAlias=""Map"" /> -->
32+
//<ins>Macro alias: <strong>Map</strong></ins></div>
33+
//<p>asdfasdf</p>".Replace(Environment.NewLine, string.Empty), result.Replace(Environment.NewLine, string.Empty));
34+
Assert.AreEqual(@"<p>asdfasdf</p>
35+
<p>asdfsadf</p>
36+
<div class=""umb-macro-holder mceNonEditable"" test1=""value1"" test2=""value2"">
37+
<!-- <?UMBRACO_MACRO macroAlias=""My.Map.isCool"" /> -->
38+
<ins>Macro alias: <strong>My.Map.isCool</strong></ins></div>
39+
<p>asdfasdf</p>".Replace(Environment.NewLine, string.Empty), result.Replace(Environment.NewLine, string.Empty));
40+
}
41+
1942
[Test]
2043
public void Format_RTE_Data_For_Editor()
2144
{
@@ -25,9 +48,16 @@ public void Format_RTE_Data_For_Editor()
2548
<p>asdfasdf</p>";
2649
var result = MacroTagParser.FormatRichTextPersistedDataForEditor(content, new Dictionary<string, string>(){{"test1", "value1"},{"test2", "value2"}});
2750

51+
// Assert.AreEqual(@"<p>asdfasdf</p>
52+
//<p>asdfsadf</p>
53+
//<div class=""umb-macro-holder Map mceNonEditable"" test1=""value1"" test2=""value2"">
54+
//<!-- <?UMBRACO_MACRO macroAlias=""Map"" /> -->
55+
//<ins>Macro alias: <strong>Map</strong></ins></div>
56+
//<p>asdfasdf</p>".Replace(Environment.NewLine, string.Empty), result.Replace(Environment.NewLine, string.Empty));
57+
2858
Assert.AreEqual(@"<p>asdfasdf</p>
2959
<p>asdfsadf</p>
30-
<div class=""umb-macro-holder Map mceNonEditable"" test1=""value1"" test2=""value2"">
60+
<div class=""umb-macro-holder mceNonEditable"" test1=""value1"" test2=""value2"">
3161
<!-- <?UMBRACO_MACRO macroAlias=""Map"" /> -->
3262
<ins>Macro alias: <strong>Map</strong></ins></div>
3363
<p>asdfasdf</p>".Replace(Environment.NewLine, string.Empty), result.Replace(Environment.NewLine, string.Empty));
@@ -42,9 +72,15 @@ public void Format_RTE_Data_For_Editor_Closing_Tag()
4272
<p>asdfasdf</p>";
4373
var result = MacroTagParser.FormatRichTextPersistedDataForEditor(content, new Dictionary<string, string>() { { "test1", "value1" }, { "test2", "value2" } });
4474

75+
// Assert.AreEqual(@"<p>asdfasdf</p>
76+
//<p>asdfsadf</p>
77+
//<div class=""umb-macro-holder Map mceNonEditable"" test1=""value1"" test2=""value2"">
78+
//<!-- <?UMBRACO_MACRO macroAlias=""Map"" /> -->
79+
//<ins>Macro alias: <strong>Map</strong></ins></div>
80+
//<p>asdfasdf</p>".Replace(Environment.NewLine, string.Empty), result.Replace(Environment.NewLine, string.Empty));
4581
Assert.AreEqual(@"<p>asdfasdf</p>
4682
<p>asdfsadf</p>
47-
<div class=""umb-macro-holder Map mceNonEditable"" test1=""value1"" test2=""value2"">
83+
<div class=""umb-macro-holder mceNonEditable"" test1=""value1"" test2=""value2"">
4884
<!-- <?UMBRACO_MACRO macroAlias=""Map"" /> -->
4985
<ins>Macro alias: <strong>Map</strong></ins></div>
5086
<p>asdfasdf</p>".Replace(Environment.NewLine, string.Empty), result.Replace(Environment.NewLine, string.Empty));
@@ -59,9 +95,15 @@ public void Format_RTE_Data_For_Editor_With_Params()
5995
<p>asdfasdf</p>";
6096
var result = MacroTagParser.FormatRichTextPersistedDataForEditor(content, new Dictionary<string, string>() { { "test1", "value1" }, { "test2", "value2" } });
6197

98+
// Assert.AreEqual(@"<p>asdfasdf</p>
99+
//<p>asdfsadf</p>
100+
//<div class=""umb-macro-holder Map mceNonEditable"" test1=""value1"" test2=""value2"">
101+
//<!-- <?UMBRACO_MACRO macroAlias=""Map"" test1=""value1"" test2=""value2"" /> -->
102+
//<ins>Macro alias: <strong>Map</strong></ins></div>
103+
//<p>asdfasdf</p>".Replace(Environment.NewLine, string.Empty), result.Replace(Environment.NewLine, string.Empty));
62104
Assert.AreEqual(@"<p>asdfasdf</p>
63105
<p>asdfsadf</p>
64-
<div class=""umb-macro-holder Map mceNonEditable"" test1=""value1"" test2=""value2"">
106+
<div class=""umb-macro-holder mceNonEditable"" test1=""value1"" test2=""value2"">
65107
<!-- <?UMBRACO_MACRO macroAlias=""Map"" test1=""value1"" test2=""value2"" /> -->
66108
<ins>Macro alias: <strong>Map</strong></ins></div>
67109
<p>asdfasdf</p>".Replace(Environment.NewLine, string.Empty), result.Replace(Environment.NewLine, string.Empty));
@@ -76,9 +118,15 @@ public void Format_RTE_Data_For_Editor_With_Params_Closing_Tag()
76118
<p>asdfasdf</p>";
77119
var result = MacroTagParser.FormatRichTextPersistedDataForEditor(content, new Dictionary<string, string>() { { "test1", "value1" }, { "test2", "value2" } });
78120

121+
// Assert.AreEqual(@"<p>asdfasdf</p>
122+
//<p>asdfsadf</p>
123+
//<div class=""umb-macro-holder Map mceNonEditable"" test1=""value1"" test2=""value2"">
124+
//<!-- <?UMBRACO_MACRO macroAlias=""Map"" test1=""value1"" test2=""value2"" /> -->
125+
//<ins>Macro alias: <strong>Map</strong></ins></div>
126+
//<p>asdfasdf</p>".Replace(Environment.NewLine, string.Empty), result.Replace(Environment.NewLine, string.Empty));
79127
Assert.AreEqual(@"<p>asdfasdf</p>
80128
<p>asdfsadf</p>
81-
<div class=""umb-macro-holder Map mceNonEditable"" test1=""value1"" test2=""value2"">
129+
<div class=""umb-macro-holder mceNonEditable"" test1=""value1"" test2=""value2"">
82130
<!-- <?UMBRACO_MACRO macroAlias=""Map"" test1=""value1"" test2=""value2"" /> -->
83131
<ins>Macro alias: <strong>Map</strong></ins></div>
84132
<p>asdfasdf</p>".Replace(Environment.NewLine, string.Empty), result.Replace(Environment.NewLine, string.Empty));
@@ -93,9 +141,15 @@ public void Format_RTE_Data_For_Editor_With_Params_Closing_Tag_And_Content()
93141
<p>asdfasdf</p>";
94142
var result = MacroTagParser.FormatRichTextPersistedDataForEditor(content, new Dictionary<string, string>() { { "test1", "value1" }, { "test2", "value2" } });
95143

144+
// Assert.AreEqual(@"<p>asdfasdf</p>
145+
//<p>asdfsadf</p>
146+
//<div class=""umb-macro-holder Map mceNonEditable"" test1=""value1"" test2=""value2"">
147+
//<!-- <?UMBRACO_MACRO macroAlias=""Map"" test1=""value1"" test2=""value2"" /> -->
148+
//<ins>Macro alias: <strong>Map</strong></ins></div>
149+
//<p>asdfasdf</p>".Replace(Environment.NewLine, string.Empty), result.Replace(Environment.NewLine, string.Empty));
96150
Assert.AreEqual(@"<p>asdfasdf</p>
97151
<p>asdfsadf</p>
98-
<div class=""umb-macro-holder Map mceNonEditable"" test1=""value1"" test2=""value2"">
152+
<div class=""umb-macro-holder mceNonEditable"" test1=""value1"" test2=""value2"">
99153
<!-- <?UMBRACO_MACRO macroAlias=""Map"" test1=""value1"" test2=""value2"" /> -->
100154
<ins>Macro alias: <strong>Map</strong></ins></div>
101155
<p>asdfasdf</p>".Replace(Environment.NewLine, string.Empty), result.Replace(Environment.NewLine, string.Empty));
@@ -104,10 +158,26 @@ public void Format_RTE_Data_For_Editor_With_Params_Closing_Tag_And_Content()
104158
[Test]
105159
public void Format_RTE_Data_For_Persistence()
106160
{
161+
// var content = @"<html>
162+
//<body>
163+
//<h1>asdfasdf</h1>
164+
//<div class='umb-macro-holder Map mceNonEditable' att1='asdf' att2='asdfasdfasdf' att3=""sdfsdfd"">
165+
//<!-- <?UMBRACO_MACRO macroAlias=""myMacro"" param1=""test1"" param2=""test2"" /> -->
166+
//asdfasdf
167+
//asdfas
168+
//<span>asdfasdfasdf</span>
169+
//<p>asdfasdf</p>
170+
//</div>
171+
//<span>asdfdasf</span>
172+
//<div>
173+
//asdfsdf
174+
//</div>
175+
//</body>
176+
//</html>";
107177
var content = @"<html>
108178
<body>
109179
<h1>asdfasdf</h1>
110-
<div class='umb-macro-holder Map mceNonEditable' att1='asdf' att2='asdfasdfasdf' att3=""sdfsdfd"">
180+
<div class='umb-macro-holder mceNonEditable' att1='asdf' att2='asdfasdfasdf' att3=""sdfsdfd"">
111181
<!-- <?UMBRACO_MACRO macroAlias=""myMacro"" param1=""test1"" param2=""test2"" /> -->
112182
asdfasdf
113183
asdfas
@@ -170,7 +240,15 @@ public void Format_RTE_Data_For_Persistence_No_Class()
170240
[Test]
171241
public void Format_RTE_Data_For_Persistence_Custom_Single_Entry()
172242
{
173-
var content = @"<div class=""umb-macro-holder Test mceNonEditable umb-macro-mce_1""><!-- <?UMBRACO_MACRO macroAlias=""Test"" content=""1089"" textArea=""asdfasdf"" title="""" bool=""0"" number="""" contentType="""" multiContentType="""" multiProperties="""" properties="""" tabs="""" multiTabs="""" /> --><ins>
243+
// var content = @"<div class=""umb-macro-holder Test mceNonEditable umb-macro-mce_1""><!-- <?UMBRACO_MACRO macroAlias=""Test"" content=""1089"" textArea=""asdfasdf"" title="""" bool=""0"" number="""" contentType="""" multiContentType="""" multiProperties="""" properties="""" tabs="""" multiTabs="""" /> --><ins>
244+
//<div class=""facts-box"">
245+
//<div class=""fatcs-box-header"">
246+
//<h3>null</h3>
247+
//</div>
248+
//<div class=""fatcs-box-body"">1089</div>
249+
//</div>
250+
//</ins></div>";
251+
var content = @"<div class=""umb-macro-holder mceNonEditable umb-macro-mce_1""><!-- <?UMBRACO_MACRO macroAlias=""Test"" content=""1089"" textArea=""asdfasdf"" title="""" bool=""0"" number="""" contentType="""" multiContentType="""" multiProperties="""" properties="""" tabs="""" multiTabs="""" /> --><ins>
174252
<div class=""facts-box"">
175253
<div class=""fatcs-box-header"">
176254
<h3>null</h3>

src/Umbraco.Web.UI.Client/src/common/services/macro.service.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ function macroService() {
1313
/** parses the special macro syntax like <?UMBRACO_MACRO macroAlias="Map" /> and returns an object with the macro alias and it's parameters */
1414
parseMacroSyntax: function (syntax) {
1515

16-
var expression = /(<\?UMBRACO_MACRO macroAlias=["'](\w+?)["'].+?)(\/>|>.*?<\/\?UMBRACO_MACRO>)/im;
16+
var expression = /(<\?UMBRACO_MACRO macroAlias=["']([\w\.]+?)["'].+?)(\/>|>.*?<\/\?UMBRACO_MACRO>)/im;
1717
var match = expression.exec(syntax);
1818
if (!match || match.length < 3) {
1919
return null;

src/Umbraco.Web.UI.Client/test/unit/common/services/macro-service.spec.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,20 @@ describe('macro service tests', function () {
2121
expect(result.marcoParamsDictionary.test2).toBe("hello");
2222

2323

24+
});
25+
26+
it('can parse syntax for macros with aliases containing dots', function () {
27+
28+
var result = macroService.parseMacroSyntax("<?UMBRACO_MACRO macroAlias='Map.Test' test1=\"asdf\" test2='hello' />");
29+
30+
expect(result).not.toBeNull();
31+
expect(result.macroAlias).toBe("Map.Test");
32+
expect(result.marcoParamsDictionary.test1).not.toBeUndefined();
33+
expect(result.marcoParamsDictionary.test1).toBe("asdf");
34+
expect(result.marcoParamsDictionary.test2).not.toBeUndefined();
35+
expect(result.marcoParamsDictionary.test2).toBe("hello");
36+
37+
2438
});
2539

2640
it('can parse syntax for macros with body', function () {

0 commit comments

Comments
 (0)