I’m trying to set the content of a metadata WYSIWYG field as a variable in a Server Side JavaScript block. The problem is that the metadata field contains Snippets and any escaping of quotes doesn’t seem to apply to the snippet. If I use something like: var value = "%asset_metadata_blah^escapequotes%"; var value = "%asset_metadata_blah^replace:":\"%";
and the snippet contains a " then the JS breaks because the quote in the snippet isn’t being escaped. The regular content within the field is escaped fine, it’s just what’s in the snippet that’s the risk.
^json_encode (the better alternative) won’t help here because the issue is that the keyword contains a %globals_ keyword which doesn’t get evaluated until after the ^escapequotes modifier. If the globals keyword contains newlines or quotes, your JS is borked.
Half-fix is to use ^base64encode instead of ^json_encode, which at least obfuscates the result and prevents any %globals_ from being evaluated and breaking things.
var value = "%asset_metadata_blah^base64encode%";
console.log(atob(value));
Of course this way you’re stuck with an unprocessed %globals_snippet_ keyword in the string when it hits the browser. This is better than broken JS, but not by much.
I’ve had some success with using ^run_ssjs to force evaluation of keywords before the encoding step
var value = "%asset_metadata_blah^run_ssjs^base64encode%";
console.log(atob(value))
however I don’t know if this works in all cases when the value doesn’t actually contain any SSJS. I’ve seen it work, but I think I’ve also seen it not work, so I’m not sure on the limits of this approach.
Thank you, David and John, for your suggestions. No joy unfortunately.
As John said, ^json_encode doesn’t help because the snippets aren’t evaluated yet. And ^run_ssjs really doesn’t like code without any SSJS in it! (And I just see John has already discovered this and replied while I’m still writing this.)
Do you need the snippet keyword to be evaluated at the time of setting it as a JS Var? If not, you could try and workaround it by doing something like
var value = "%asset_metadata_blah^replace:globals_snippet:foo_snippet%";
value = value.replace(/foo_snippet/g, 'globals_snippet');
That way whenever you print value, it will have the keyword un-replaced keyword but it will get replaced again before Matrix sends the content to the browser.
Alternatively you could just add the evalkeywords=“post” attribute to the script tag and not replace any keywords and leave them to be processed afterwards.