U4-4442 - Line break in macro text area breaks the Macro

Created by Mikael Hardø 14 Mar 2014, 15:59:14 Updated by Shannon Deminick 20 Mar 2014, 01:21:18

Relates to: U4-4290

Relates to: U4-4425

If a macro contains a "Textarea" with a text that contains a line break, it contains a macro text like this:

This does not fit into the regular expression found here:

{code:title=Line 2716 in umbraco.services.js} var expression = /(<?UMBRACO_MACRO macroAlias="'["'].+?)(/>|>.*?</?UMBRACO_MACRO>)/im;

This is what is used to parse the parameters from the macro to the server. Because this fails, nothing happens and the Macro will not load.

The steps to reproduce:

  1. Create a macro that contains a "TextArea"
  2. Use the macro and add a line break in the text.
  3. Watch how the macro is now shown without the linebreaks.
  4. Save
  5. The macro tries to reload and fails. The message "Macro alias: MacroName" remains.

Comments

Mikael Hardø 19 Mar 2014, 12:03:20

i did the following change, which seems to fix the issue:

{code:lang=JavaScript|title=umbraco.services.js (before)} /** parses the special macro syntax like <?UMBRACO_MACRO macroAlias="Map" /> and returns an object with the macro alias and it's parameters */ parseMacroSyntax: function (syntax) {

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

        //this will leave us with just the parameters
        var paramsChunk = match[1].trim().replace(new RegExp("UMBRACO_MACRO macroAlias=[\"']" + alias + "[\"']"), "").trim();
        
        var paramExpression = new RegExp("(\\w+?)=['\"](.*?)['\"]", "g");
        var paramMatch;
        var returnVal = {
            macroAlias: alias,
            marcoParamsDictionary: {}
        };
        while (paramMatch = paramExpression.exec(paramsChunk)) {
            returnVal.marcoParamsDictionary[paramMatch[1]] = paramMatch[2];
        }
        return returnVal;
    },

{code:lang=JavaScript|title=umbraco.services.js (after)} /** parses the special macro syntax like <?UMBRACO_MACRO macroAlias="Map" /> and returns an object with the macro alias and it's parameters */ parseMacroSyntax: function (syntax) {

        var expression = /(<\?UMBRACO_MACRO macroAlias=["'](\w+?)["'].[\s\S]*)(\/>|><\/\?UMBRACO_MACRO>)/im;
        var match = expression.exec(syntax);
        if (!match || match.length < 3) {
            return null;
        }
        var alias = match[2];

        //this will leave us with just the parameters
        var paramsChunk = match[1].trim().replace(new RegExp("UMBRACO_MACRO macroAlias=[\"']" + alias + "[\"']"), "").trim();
        
        var quoteExpression = /(\w+?)=['\"]([\s\S]*?)['\"]/g

        var paramExpression = new RegExp(quoteExpression);
        var paramMatch;
        var returnVal = {
            macroAlias: alias,
            marcoParamsDictionary: {}
        };
        while (paramMatch = paramExpression.exec(paramsChunk)) {
            returnVal.marcoParamsDictionary[paramMatch[1]] = paramMatch[2];
        }
        return returnVal;
    },

This code block starts on line 2714 in umbraco.services.js. It allows the regular expressions to parse the macro even when there is a line break in it.


Shannon Deminick 19 Mar 2014, 23:53:37

I think the better fix for this is to ensure line breaks are encoded properly since the values are being stored as html/xml attributes which generally do not support having line breaks directly in the value.

I'll investigate.


Shannon Deminick 20 Mar 2014, 00:22:54

Ok, so line breaks are supported in xml attributes - though they normally get encoded on their native system. After a quick review I do need to xml encode the values which is easily handled by underscorejs but this leaves line breaks alone. I also don't want to end up with cross browser/os problems with how they handle line breaks in xml attributes. So, i just need to review your regex changes and ensure that they also match what the .Net regex expressions allow and fix up unit tests.


Shannon Deminick 20 Mar 2014, 00:50:04

Ok, so have figured out why it isn't matching. In .Net we have the same expression but we have an option called "SingleLine" which is what is enabled - this means that the wildcard '.' will match line breaks, whereas in JavaScript this is not the case and in fact we have the wrong modifier 'm' declared.

So the expression that it should be is:

(<?UMBRACO_MACRO macroAlias="'["'][\s\S]+?)(/>|>.*?</?UMBRACO_MACRO>)/i;

so to match any whitespace char or any non-whitespace char (which is essentially '.' with a Single line match option)


Shannon Deminick 20 Mar 2014, 01:21:18

all done in rev: 2340adbe94323fd0d6810e53f586cee23733b13e including bug fixes for related issues.


Priority: Major

Type: Bug

State: Fixed

Assignee: Shannon Deminick

Difficulty: Normal

Category:

Backwards Compatible: True

Fix Submitted: Inline code

Affected versions: 7.0.1, 7.0.2, 7.0.3, 7.0.4

Due in version: 7.1.0

Sprint:

Story Points:

Cycle: