How to prevent Uglify un-escaping "</script" in strings? - javascript

I've got code like this:
var string = '<script src="' + src + '">\x3c/script>';
I've used \x3c instead of < to avoid having a closing script tag (which would end the script early if used as an inline script in a web browser, breaking everything).
But uglify unfortunately converts it back into a < character, breaking my page.
It looks like Uglify has an option called inline-scripts intended to fix this, but there are no docs on using this option with the API (I'm using it via gulp-uglify so I need to be able to pass this option in an options object, not via the CLI).
How do I do it? None of the following work:
{'inline-script': true}
{inlineScript: true}
{beautify: {inlineScript: true}}
{beautify: {'inline-script': true}}

I realize this is an old question, however, the answer given is not correct. You need to use the output object in uglifyjs.
.pipe(uglify({
output: {
'inline_script': true
}
}))

It should be specified with underscore, as this:
options: {{beautify: {'inline_script': true}}}

Related

force content to string in typescript / javascript

I'm in a situation where I will need to pass in a shell bash script from node. This script breaks template literals since it contains variables like
${foo}
So I want to completely ignore syntax like
" $ '
And so on. What alternatives do you see for accomplishing this?
I have considered using JSON somehow but did not succeed, maybe I should encode the content?
Isn't escaping what you are looking for ?
const str = `\${im-escaped}` // '${im-escaped}'

Fill a Javascript-Array within a Fluid foreach

i try to create a js-array with a fluid-foreach but i just get the "{obj.background.title}" output. when i put it in a console.log it works.
<script>
<f:for each="{settings.backgrounds}" as="obj" iteration="itemIteration">
{f:if(condition: itemIteration.isFirst, then: 'var backgrounds = [')}
{
src: "fileadmin/user_upload/configurator_1/background1.jpg",
isdark: true,
title: "{obj.background.title}",
},
{f:if(condition: itemIteration.isLast, then: ']')}
</f:for>
</script>
Use f:format.raw around the opening or closing curly braces. This prevents the Fluid parser from seeing it as an inline accessor.
The JavaScript-{ probably confuses the Fluid parser (off topic: what a catastrophic idea to use a JavaScript syntax token in an HTML templating engine and even forget about a clean way to escape it!).
That said it is sadly very common for JavaScript-in-Fluid to be parsed half-way or not at all or anything in between (as you just experienced). I used to use f:format.cdata() but even that has caveats. It often depends on the position of your <script> in the template so moving it more to the end of your template might help if you want to go the trial-and-error path...
I recommend passing over dynamic data to JavaScript by assigning the whole JavaScript to a template variable in your controller and outputting it via {script -> f:format.raw()}. This means ugly frontend-related stuff in your controller but it is the quickest and a very reliable way.
Or you can use a vhs-ViewHelper to convert your data to JSON and assign a HTML-data-property and process it via an external JavaScript logic. This also works reliably and is quite clean in my eyes.
In Fluid:
<x-mytag data-backgrounds="{v:format.json.encode(value: setting.backgrounds)}" />
Ideally in an external JavaScript (actually, this would even work inside Fluid):
var backgrounds = JSON.parse(
document.querySelector('[data-backgrounds]').dataset.backgrounds
)
Everybody made this experience once... I am very open to learn about other approaches.

How to use options in js-beautify plugin

JS noob here. I'm currently using js-beautify(https://github.com/beautify-web/js-beautify) plugin to properly indent/format a long string of HTML code. This is how I'm using it
html_beautify(HTML);
HTML is a variable containing regular HTML code.
How can I pass options like disabling word-wrap or removing empty lines?
It looks like you can add an object as the second parameter to handle your options:
html_beautify(elHTML, { preserve_newlines: false, wrap_line_length: 0 });

javascript, curly brace in onclick dont work?

Solved, server side ate my {}.
I have this code in my HTML:
onclick="changes = {'a': 'b'};"
This transforms to
onclick="changes = ;"
when I load the page. So the curly braces and everything in between disappears. Any idea how to fix this? Ultimately, I want to give an anonymous object as input to a function:
onclick="dothis({'a': 'b', '1': '2'});"
What I would recommend is making your code more semantic, by having your inputs keep track of data, but the actual binding and execution separate:
<div id="myDiv" data-changes="{'a':'b', '1':'2'}"></div>
document.getElementById('myDiv').onclick = function() {
var data = JSON.parse(this.getAttribute('data-changes'));
// here you should be able to say data.a, data.1, etc.
};
Most modern browsers support native JSON methods:
Browser-native JSON support (window.JSON)
but for those that don't, you can add support with the JSON library:
https://github.com/douglascrockford/JSON-js
Have you considered/are you able to not use inline JavaScript? Just have an external JavaScript file that gets loaded with something like (not actual code, for example purposes):
getElementById("myButton").click( function(){
dothis({'a':'b','1':'2'})
})
Something like that (especially when paired with a library) can also save you from having to duplicate your code in every item you're looking to run that function in.

JavaScript multiline strings and templating?

I have been wondering if there is a way to define multiline strings in JavaScript like you can do in languages like PHP:
var str = "here
goes
another
line";
Apparently this breaks up the parser. I found that placing a backslash \ in front of the line feed solves the problem:
var str = "here\
goes\
another\
line";
Or I could just close and reopen the string quotes again and again.
The reason why I am asking because I am making JavaScript based UI widgets that utilize HTML templates written in JavaScript. It is painful to type HTML in strings especially if you need to open and close quotes all the time. What would be a good way to define HTML templates within JavaScript?
I am considering using separate HTML files and a compilation system to make everything easier, but the library is distributed among other developers so that HTML templates have to be easy to include for the developers.
No thats basically what you have to do to do multiline strings.
But why define the templates in javascript anwyay? why not just put them into a file and have a ajax call load them up in a variable when you need them?
For instantce (using jquery)
$.get('/path/to/template.html', function(data) {
alert(data); //will alert the template code
});
#slebetman, Thanks for the detailed example.
Quick comment on the substitute_strings function.
I had to revise
str.replace(n,substitutions[n]);
to be
str = str.replace(n,substitutions[n]);
to get it to work. (jQuery version 1.5? - it is pure javascript though.)
Also when I had below situation in my template:
$CONTENT$ repeated twice $CONTENT$ like this
I had to do additional processing to get it to work.
str = str.replace(new RegExp(n, 'g'), substitutions[n]);
And I had to refrain from $ (regex special char) as the delimiter and used # instead.
Thought I would share my findings.
There are several templating systems in javascript. However, my personal favorite is one I developed myself using ajax to fetch XML templates. The templates are XML files which makes it easy to embed HTML cleanly and it looks something like this:
<title>This is optional</title>
<body><![CDATA[
HTML content goes here, the CDATA block prevents XML errors
when using non-xhtml html.
<div id="more">
$CONTENT$ may be substituted using replace() before being
inserted into $DOCUMENT$.
</div>
]]></body>
<script><![CDATA[
/* javascript code to be evaled after template
* is inserted into document. This is to get around
* the fact that this templating system does not
* have its own turing complete programming language.
* Here's an example use:
*/
if ($HIDE_MORE$) {
document.getElementById('more').display = 'none';
}
]]></script>
And the javascript code to process the template goes something like this:
function insertTemplate (url_to_template, insertion_point, substitutions) {
// Ajax call depends on the library you're using, this is my own style:
ajax(url_to_template, function (request) {
var xml = request.responseXML;
var title = xml.getElementsByTagName('title');
if (title) {
insertion_point.innerHTML += substitute_strings(title[0],substitutions);
}
var body = xml.getElementsByTagName('body');
if (body) {
insertion_point.innerHTML += substitute_strings(body[0],substitutions);
}
var script = xml.getElementsByTagName('script');
if (script) {
eval(substitute_strings(script[0],substitutions));
}
});
}
function substitute_strings (str, substitutions) {
for (var n in substitutions) {
str.replace(n,substitutions[n]);
}
return str;
}
The way to call the template would be:
insertTemplate('http://path.to.my.template', myDiv, {
'$CONTENT$' : "The template's content",
'$DOCUMENT$' : "the document",
'$HIDE_MORE$' : 0
});
The $ sign for substituted strings is merely a convention, you may use % of # or whatever delimiters you prefer. It's just there to make the part to be substituted unambiguous.
One big advantage to using substitutions on the javascript side instead of server side processing of the template is that this allows the template to be plain static files. The advantage of that (other than not having to write server side code) is that you can then set the caching policy for the template to be very aggressive so that the browser only needs to fetch the template the first time you load it. Subsequent use of the template would come from cache and would be very fast.
Also, this is a very simple example of the implementation to illustrate the mechanism. It's not what I'm using. You can modify this further to do things like multiple substitution, better handling of script block, handle multiple content blocks by using a for loop instead of just using the first element returned, properly handling HTML entities etc.
The reason I really like this is that the HTML is simply HTML in a plain text file. This avoids quoting hell and horrible string concatenation performance issues that you'll usually find if you directly embed HTML strings in javascript.
I think I found a solution I like.
I will store templates in files and fetch them using AJAX. This works for development stage only. For production stage, the developer has to run a compiler once that compiles all templates with the source files. It also compiles JavaScript and CSS to be more compact and it compiles them to a single file.
The biggest problem now is how to educate other developers doing that. I need to build it so that it is easy to do and understand why and what are they doing.
You could also use \n to generate newlines. The html would however be on a single line and difficult to edit. But if you generate the JS using PHP or something it might be an alternative

Categories