Add support for Inline Macro - To enable: Add a Macro Parameter called: enableInlineMacro with Umbraco.TrueFalse set to True (value:"1") (#13628)

- Custom Macro Parameter with true as default value can be created for those prefering that in their project

Co-authored-by: Jo Mehmet Sollihagen <jomehmet@solsol.no>
This commit is contained in:
jomehmet
2023-02-22 15:21:53 +01:00
committed by GitHub
parent 62fdbd159c
commit 2a3c0358b1
4 changed files with 57 additions and 19 deletions

View File

@@ -40,10 +40,15 @@ public class MacroTagParser
{
if (match.Groups.Count >= 3)
{
var macroCanBeInlinedInParagraph = match.Value?.Contains("enableInlineMacro=\"1\"") ?? false;
var macroElementType = macroCanBeInlinedInParagraph ? "span" : "div";
// <div class="umb-macro-holder myMacro mceNonEditable">
var alias = match.Groups[2].Value;
var sb = new StringBuilder("<div class=\"umb-macro-holder ");
var sb = new StringBuilder($"<{macroElementType} class=\"umb-macro-holder ");
if (macroCanBeInlinedInParagraph)
{
sb.Append("inlined-macro ");
}
// sb.Append(alias.ToSafeAlias());
sb.Append("mceNonEditable\"");
foreach (KeyValuePair<string, string> htmlAttribute in htmlAttributes)
@@ -64,7 +69,7 @@ public class MacroTagParser
sb.Append("Macro alias: ");
sb.Append("<strong>");
sb.Append(alias);
sb.Append("</strong></ins></div>");
sb.Append($"</strong></ins></{macroElementType}>");
return sb.ToString();
}

View File

@@ -766,14 +766,20 @@ function tinyMceService($rootScope, $q, imageHelper, $locale, $http, $timeout, s
}
var e = $(element).closest(".umb-macro-holder");
if (e.length > 0) {
if (e.get(0).parentNode.nodeName === "P") {
var macroHolder = e.get(0);
// In case of Inline Macro we don't need the be backward compliant
if(macroHolder.tagName === 'SPAN'){
return macroHolder;
}
if (macroHolder.parentNode.nodeName === "P") {
//now check if we're the only element
if (element.parentNode.childNodes.length === 1) {
return e.get(0).parentNode;
return macroHolder.parentNode;
}
}
return e.get(0);
return macroHolder;
}
return null;
}
@@ -830,35 +836,37 @@ function tinyMceService($rootScope, $q, imageHelper, $locale, $http, $timeout, s
var macroSyntaxComment = "<!-- " + macroObject.syntax + " -->";
//create an id class for this element so we can re-select it after inserting
var uniqueId = "umb-macro-" + editor.dom.uniqueId();
var macroDiv = editor.dom.create('div',
var isInlined = macroObject.macroParamsDictionary["enableInlineMacro"] === "1";
var macroElementType = isInlined ? 'span' : 'div';
var macroElement = editor.dom.create(macroElementType,
{
'class': 'umb-macro-holder ' + macroObject.macroAlias + " " + uniqueId + ' mceNonEditable',
'class': 'umb-macro-holder ' + macroObject.macroAlias + " " + uniqueId + ' mceNonEditable' + (isInlined ? ' inlined-macro' : ''),
'contenteditable': 'false'
},
macroSyntaxComment + '<ins>Macro alias: <strong>' + macroObject.macroAlias + '</strong></ins>');
//if there's an activeMacroElement then replace it, otherwise set the contents of the selected node
if (activeMacroElement) {
activeMacroElement.replaceWith(macroDiv); //directly replaces the html node
activeMacroElement.replaceWith(macroElement); //directly replaces the html node
}
else {
editor.selection.setNode(macroDiv);
editor.selection.setNode(macroElement);
}
var $macroDiv = $(editor.dom.select("div.umb-macro-holder." + uniqueId));
var $macroElement = $(editor.dom.select(".umb-macro-holder." + uniqueId));
editor.setDirty(true);
//async load the macro content
this.loadMacroContent($macroDiv, macroObject, editor);
this.loadMacroContent($macroElement, macroObject, editor);
},
/** loads in the macro content async from the server */
loadMacroContent: function ($macroDiv, macroData, editor) {
loadMacroContent: function ($macroElement, macroData, editor) {
//if we don't have the macroData, then we'll need to parse it from the macro div
if (!macroData) {
var contents = $macroDiv.contents();
var contents = $macroElement.contents();
var comment = _.find(contents, function (item) {
return item.nodeType === 8;
});
@@ -870,15 +878,15 @@ function tinyMceService($rootScope, $q, imageHelper, $locale, $http, $timeout, s
macroData = parsed;
}
var $ins = $macroDiv.find("ins");
var $ins = $macroElement.find("ins");
//show the throbber
$macroDiv.addClass("loading");
$macroElement.addClass("loading");
// Add the contenteditable="false" attribute
// As just the CSS class of .mceNonEditable is not working by itself?!
// TODO: At later date - use TinyMCE editor DOM manipulation as opposed to jQuery
$macroDiv.attr("contenteditable", "false");
$macroElement.attr("contenteditable", "false");
var contentId = $routeParams.id;
@@ -887,7 +895,7 @@ function tinyMceService($rootScope, $q, imageHelper, $locale, $http, $timeout, s
macroResource.getMacroResultAsHtmlForEditor(macroData.macroAlias, contentId, macroData.macroParamsDictionary)
.then(function (htmlResult) {
$macroDiv.removeClass("loading");
$macroElement.removeClass("loading");
htmlResult = htmlResult.trim();
if (htmlResult !== "") {
var wasDirty = editor.isDirty();

View File

@@ -4,9 +4,13 @@
.mce-content-body .umb-macro-holder {
border: 3px dotted @pinkLight;
padding: 7px;
display: block;
margin: 3px;
}
.mce-content-body .umb-macro-holder.inlined-macro {
border: 1px dotted @pinkLight;
padding: 1px;
margin: 0px;
}
.umb-rte .mce-content-body .umb-macro-holder.loading {

View File

@@ -396,4 +396,25 @@ asdfsdf
@"<?UMBRACO_MACRO macroAlias=""Test"" content=""1089"" textArea=""asdfasdf"" title="""" bool=""0"" number="""" contentType="""" multiContentType="""" multiProperties="""" properties="""" tabs="""" multiTabs="""" />",
result);
}
[Test]
public void Format_RTE_WhenMacroContainsParameter_EnableInlineMacro_WithValue_1_ItShouldBeInASpan()
{
var content = @"<p>asdfasdf</p>
<p>asdfsadf</p>
<?UMBRACO_MACRO macroAlias=""My.Map.isCool eh[boy!]"" test1=""value1"" enableInlineMacro=""1""/>
<p>asdfasdf</p>";
var result = MacroTagParser.FormatRichTextPersistedDataForEditor(
content,
new Dictionary<string, string> { { "test1", "value1" }, { "enableInlineMacro", "1"} });
Assert.AreEqual(
@"<p>asdfasdf</p>
<p>asdfsadf</p>
<span class=""umb-macro-holder inlined-macro mceNonEditable"" test1=""value1"" enableInlineMacro=""1"">
<!-- <?UMBRACO_MACRO macroAlias=""My.Map.isCool eh[boy!]"" test1=""value1"" enableInlineMacro=""1"" /> -->
<ins>Macro alias: <strong>My.Map.isCool eh[boy!]</strong></ins></span>
<p>asdfasdf</p>".StripNewLines(),
result.StripNewLines());
}
}