How can I remove empty strings in template literals? - javascript

I'm creating a script that loops through an array of objects and creates .edn file that we're using to migrate some of our client's data.
As we have to use .edn file which uses Clojure, I generate a template literal string and populate the data in the format that we need.
In the generated string I have many conditional operations, where I check if some data exist before returning some string. If the data doesn't exist I cannot use null, so I use an empty string. Now when my file gets created, those empty strings create an extra line that I want to remove. Investigating it more, the string adds /n which actually creates those extra lines from an empty string.
What is the best way to do it?
This is an example of what I'm doing:
arrayOfObjects.map(a => {
return `
; ...other code that doesn't depend on data
; Code that depends on data, if it's false I want to remove it completely and
; and avoid passing empty string as it creates extra space in the generated file
${a.stripe_connected_account
? `[[:im.stripeAccount/id]
#:im.stripeAccount{:stripeAccountId "${a.stripe_connected_account}"
:user #im/ref :user/${a.user}}]`
: ""}
`;
});
Appreciate any help, thanks!

An empty string doesn't do that. T${''}h${''}i${''}s is no different from This. The "extra space" is the whitespace that you (unconditionally) include in your template string around the ${ } part:
If you'd start the ${ } expression earlier and end it later and put the whitespace (if you even want it) as part of your if-true expression of the ternary, you will get what you want.
For example:
arrayOfObjects.map(a => {
return `
; ...other code that doesn't depend on data
; Code that depends on data, if it's false I want to remove it completely and
; and avoid passing empty string as it creates extra space in the generated file${
a.stripe_connected_account ? `
[[:im.stripeAccount/id]
#:im.stripeAccount{:stripeAccountId "${a.stripe_connected_account}"
:user #im/ref :user/${a.user}}]`
: ""
}`;
});
(Yes, the strange indentation is a result of merging two different indentation levels, the code's and the output's, and preventing line breaks in the output unless desired. I tried several ways to format it but none of them looked good - there are only ugly ways, no way to indent it nicely and have the result you want, unless you were to write a tagged template function that would smartly detect when a ${ } expression would need surrounding whitespace stripped and when it wouldn't.)

Related

Convert string expression into JS object (not JSON)

I have an expression like this inside a contenteditable div:
{
name : "Jeff",
job : "rat whacker"
}
How can I get this into a JS object?
If I grab the string from the div:
$("div").text();
...I get this:
"{\n name: \"Jeff\",\n job: \"rat whacker\"\n}"
Obviously JSON.parse won't work since this isn't valid JSON. How can I grab this as text but then assign it to a regular JSON object:
{
name : "Jeff",
job : "rat whacker"
}
Note that the last thing you want to do is trust people. Someone is going to abuse your site if you allow arbitrary code execution, so make that impossible: write code that validates user input before it's allowed to even make it to the next step.
Either take the textContent from your div, rewrite it so that it's valid JSON, and then parse that JSON (bonus: JSON.parse automatically throws an error if the input can't be parsed, so you can write a pretty simply string replacement that works for the kind of input you want, while yielding bad JSON for anything else, and the JSON.parse function will just reject bad input), or literally parse the text string as JS, using a JS parser that is set to throw away any active content (function, fat arrow notation, exercution operators, etc). If you only want to allow simple input like what you're showing, then writing your own simple-and-limited-JS parser is a little bit of work, but might be more than enough.

javascript use in React setState

I'm studying a React book but see a simple like this, but I don't know why there is a ',' behind the [item]:value]
handleChange(item ,e) {
const {value} = e.target;
this.setState({[item]:value,});
}
render() {
const {name, age} = this.state;
return (
<div className="FormA">
name: <input value={name} onChange={this.handleChange.bind(this,'name')}/>
age: <input value={age} onChange={this.handleChange.bind(this,'age')}/>
</div>
);
}
It is considered as best practice to have a ',' after every object property. You must have used ESLint: https://eslint.org/docs/rules/comma-style
It is just a matter of syntax and does not add anything to your code.
Its a best practice, because of the below reasons
Its easier to track the commas. Eg. If you want a long list of object properties and you want to comment out some of them, then you need not worry about comas, as they are commented as well. Same goes for copy-paste.
Its easier to see the diffs in version control.
The commas can be either at the end or at the front.
[I usually use at front, personal choice.]
To Quote from ESList rules
The Comma Style rule enforces styles for comma-separated lists. There are two comma styles primarily used in JavaScript:
The standard style, in which commas are placed at the end of the current line
Comma First style, in which commas are placed at the start of the next line
One of the justifications for using Comma First style is that it can help track missing and trailing commas. These are problematic because missing commas in variable declarations can lead to the leakage of global variables and trailing commas can lead to errors in older versions of IE.
Refer:
https://eslint.org/docs/rules/comma-dangle,
https://medium.com/#nikgraf/why-you-should-enforce-dangling-commas-for-multiline-statements-d034c98e36f8,
https://eslint.org/docs/rules/comma-style
This is because you can define a collection of named values to be set. If you're going to set only one you don't need to use it. In the same way the last element does't need it neither, for example:
this.setState({[item]:value}); //You don't necessary need the ',' here.
this.setState({
[item]:value, //here you need to use ','
[item2]:value2, //here you need to use ','
[item3]:value3}); //here you don't need to use ','
For more infor about objects check this link and this one

"Fixing" JSON coming out of MySQL

I'm fetching JSON code stored in MySQL and it has extra slashes, which I have to remove in order to parse it in JavaScript, after I print it on the page. Right now I'm doing the following:
$save = str_replace("\n", "<br>", $save); // Replace new line characters with <br>
$save = str_replace('\\"', '"', $save); // top-level JSON
$save = str_replace('\\\\"', '\"', $save); // HTML inside top level JSON
$save = str_replace('\\\\\\\\\\"', '\\\\\"', $save); // HTML inside second level JSON
Here is an example JSON code, as it comes out from MySQL:
{\"id\":2335,\"editor\":{\"selected_shape\":\"spot-7488\"},\"general\":{\"name\":\"HTML Test\",\"shortcode\":\"html-test\",\"width\":1280,\"height\":776},\"spots\":[{\"id\":\"spot-7488\",\"x\":9.9,\"y\":22.6,\"default_style\":{\"use_icon\":1},\"tooltip_content\":{\"content_type\":\"content-builder\",\"plain_text\":\"<p class=\\\"test\\\">Test</p>\",\"squares_json\":\"{\\\"containers\\\":[{\\\"id\\\":\\\"sq-container-293021\\\",\\\"settings\\\":{\\\"elements\\\":[{\\\"settings\\\":{\\\"name\\\":\\\"Paragraph\\\",\\\"iconClass\\\":\\\"fa fa-paragraph\\\"},\\\"options\\\":{\\\"text\\\":{\\\"text\\\":\\\"<p class=\\\\\\\"test\\\\\\\">Test</p>\\\"}}}]}}]}\"}}]}
And here is how it's supposed to look in order to get parsed correctly (using jsonlint.com to test):
{"id":2335,"editor":{"selected_shape":"spot-7488"},"general":{"name":"HTML Test","shortcode":"html-test","width":1280,"height":776},"spots":[{"id":"spot-7488","x":9.9,"y":22.6,"default_style":{"use_icon":1},"tooltip_content":{"content_type":"content-builder","plain_text":"<p class=\"test\">Test</p>","squares_json":"{\"containers\":[{\"id\":\"sq-container-293021\",\"settings\":{\"elements\":[{\"settings\":{\"name\":\"Paragraph\",\"iconClass\":\"fa fa-paragraph\"},\"options\":{\"text\":{\"text\":\"<p class=\\\"test\\\">Test</p>\"}}}]}}]}"}}]}
Please note that I have HTML code inside JSON, which is inside another JSON and this is where it gets a bit messy.
My question - is there a function or library for PHP (for JS will work too) which covers all those corner cases, because I'm sure someone will find a way to break the script.
Thanks!
The short answer, which is woefully inadequate, is for you to use stripslashes. The reason this answer is not adequate is that your JSON string might have been escaped or had addslashes called on it multiple times and you would have to call stripslashes precisely once for each time this had happened.
The proper solution is to find out where the slashes are being added and either a) avoid adding the slashes or b) understand why the slashes are there and respond accordingly. I strongly believe that the process that creates that broken JSON is where the problem lies.
Slashes are typically added in PHP in a few cases:
magic_quotes are turned on. This is an old PHP feature which has been removed. The basic idea is that PHP used to auto-escape quotes in incoming requests to let you just cram incoming strings into a db. Guess what? NOT SAFE.
add_slashes has been called. Why call this? Some folks use it as an incorrect means of escaping data before sticking stuff in a db. Others use it to keep HTML from breaking when echoing variables out (htmlspecialchars should probably be used instead). It can also come in handy in a variety of other meta situations when you are defining code in a string.
When escaping data input. The most common escaping function is mysqli_real_escape_string. It's very important to escape values before inserting them in a db to prevent sql injection and other exploits but you should never escape things twice.
So there's a possibility that your code is double-escaping things or that addslashes is getting called or something like magic_quotes is causing the problem, but I suspect it is another problem: some JS code might be supplying this JSON not as a proper JSON string, but one that has been escaped so to define a string within javascript.
If you take your example JSON string above, and slap some quotes around it:
var myJSON = "<put your string here>";
then SURPRISE your javascript is not broken and the var myJSON contains a string that is actually valid JSON and can be parsed into an a valid JSON object:
var myJSON = "{\"id\":2335,\"editor\":{\"selected_shape\":\"spot-7488\"},\"general\":{\"name\":\"HTML Test\",\"shortcode\":\"html-test\",\"width\":1280,\"height\":776},\"spots\":[{\"id\":\"spot-7488\",\"x\":9.9,\"y\":22.6,\"default_style\":{\"use_icon\":1},\"tooltip_content\":{\"content_type\":\"content-builder\",\"plain_text\":\"<p class=\\\"test\\\">Test</p>\",\"squares_json\":\"{\\\"containers\\\":[{\\\"id\\\":\\\"sq-container-293021\\\",\\\"settings\\\":{\\\"elements\\\":[{\\\"settings\\\":{\\\"name\\\":\\\"Paragraph\\\",\\\"iconClass\\\":\\\"fa fa-paragraph\\\"},\\\"options\\\":{\\\"text\\\":{\\\"text\\\":\\\"<p class=\\\\\\\"test\\\\\\\">Test</p>\\\"}}}]}}]}\"}}]}";
console.log(JSON.parse(myJSON)); // this is an actual object
The key here is to examine the point of entry where this JSON arrives in your system. I suspect some AJAX request has created some object and rather than sending valid JSON Of that object, it is sending instead an escaped string of a JSON object.
EDIT:
Here's a simple example of what happens when you have too many encodings. Try running this JS in your browser and observe the console output:
var myObj = {"key":"here is my value"};
console.log(myObj);
var myJSON = JSON.stringify(myObj);
console.log(myJSON);
var doubleEncoded = JSON.stringify(myJSON);
console.log(doubleEncoded);

Is there some way that I can pass the return value of one helper function into another as a parameter in Handlebars

I have run into a problem with a current project using Handlebars.js. I am writing a complex template which must be output only as text (it is fed directly as a string to a text printer) and that text can be a maximum of 40 chars wide.
The problem I have is that I need to use various helper functions to get and organise my data, but I then need to take that text and put it though another function to format it into the 40 char width.
So... I have helper functions that look a bit like this:
Handlebars.registerHelper('getLit' , function (litName) {
// some logic to retrieve a string lit in correct language
});
Handlebars.registerHelper('getArrayValue', function(array, key) {
return array[key];
});
Handlebars.registerHelper('textFormat', function(string, max_width, align) {
// logic to format the text
});
Now if my htm looks like this:
{{textFormat "This is a really long string that needs formating into the correcct length blah blah blah blah" 40 'left'}}
I have no problems.
However I need to be able to use helper function to build the string e.g.
{{textFormat {{getArrayValue address 0}} 40 'right'}}
I hope my explanation is not too convoluted, obviously the data I am dealing with is very large and very complex so simply preparing all the data to feed into the template (e.g. instead of using getLit making 6 forms of each string in their various languages) is just not practical.
Is there anyway to make this work or do I need to use a totally different approach?
You cannot use nested helpers. If you need include new helper, use construct
{{#textformat 10 'right'}}
{{getArrayValue address 0}}
{{/textformat}}
You can find out more about constructing block helpers here: http://handlebarsjs.com/block_helpers.html

remove double quotes from Json return data using Jquery

I use JQuery to get Json data, but the data it display has double quotes. It there a function to remove it?
$('div#ListingData').text(JSON.stringify(data.data.items[0].links[1].caption))
it returns:
"House"
How can I remove the double quote? Cheers.
Use replace:
var test = "\"House\"";
console.log(test);
console.log(test.replace(/\"/g, ""));
// "House"
// House
Note the g on the end means "global" (replace all).
For niche needs when you know your data like your example ... this works :
JSON.parse(this_is_double_quoted);
JSON.parse("House"); // for example
The stringfy method is not for parsing JSON, it's for turning an object into a JSON string.
The JSON is parsed by jQuery when you load it, you don't need to parse the data to use it. Just use the string in the data:
$('div#ListingData').text(data.data.items[0].links[1].caption);
Someone here suggested using eval() to remove the quotes from a string. Don't do that, that's just begging for code injection.
Another way to do this that I don't see listed here is using:
let message = JSON.stringify(your_json_here); // "Hello World"
console.log(JSON.parse(message)) // Hello World
I also had this question, but in my case I didn't want to use a regex, because my JSON value may contain quotation marks. Hopefully my answer will help others in the future.
I solved this issue by using a standard string slice to remove the first and last characters. This works for me, because I used JSON.stringify() on the textarea that produced it and as a result, I know that I'm always going to have the "s at each end of the string.
In this generalized example, response is the JSON object my AJAX returns, and key is the name of my JSON key.
response.key.slice(1, response.key.length-1)
I used it like this with a regex replace to preserve the line breaks and write the content of that key to a paragraph block in my HTML:
$('#description').html(studyData.description.slice(1, studyData.description.length-1).replace(/\\n/g, '<br/>'));
In this case, $('#description') is the paragraph tag I'm writing to. studyData is my JSON object, and description is my key with a multi-line value.
You can simple try String(); to remove the quotes.
Refer the first example here: https://www.w3schools.com/jsref/jsref_string.asp
Thank me later.
PS: TO MODs: don't mistaken me for digging the dead old question. I faced this issue today and I came across this post while searching for the answer and I'm just posting the answer.
What you are doing is making a JSON string in your example. Either don't use the JSON.stringify() or if you ever do have JSON data coming back and you don't want quotations, Simply use JSON.parse() to remove quotations around JSON responses! Don't use regex, there's no need to.
I dont think there is a need to replace any quotes, this is a perfectly formed JSON string, you just need to convert JSON string into object.This article perfectly explains the situation : Link
Example :
success: function (data) {
// assuming that everything is correct and there is no exception being thrown
// output string {"d":"{"username":"hi","email":"hi#gmail.com","password":"123"}"}
// now we need to remove the double quotes (as it will create problem and
// if double quotes aren't removed then this JSON string is useless)
// The output string : {"d":"{"username":"hi","email":"hi#gmail.com","password":"123"}"}
// The required string : {"d":{username:"hi",email:"hi#gmail.com",password:"123"}"}
// For security reasons the d is added (indicating the return "data")
// so actually we need to convert data.d into series of objects
// Inbuilt function "JSON.Parse" will return streams of objects
// JSON String : "{"username":"hi","email":"hi#gmail.com","password":"123"}"
console.log(data); // output : Object {d="{"username":"hi","email":"hi#gmail.com","password":"123"}"}
console.log(data.d); // output : {"username":"hi","email":"hi#gmail.com","password":"123"} (accessing what's stored in "d")
console.log(data.d[0]); // output : { (just accessing the first element of array of "strings")
var content = JSON.parse(data.d); // output : Object {username:"hi",email:"hi#gmail.com",password:"123"}" (correct)
console.log(content.username); // output : hi
var _name = content.username;
alert(_name); // hi
}
I had similar situation in a Promise just solved doing a cast as (String)
export async function getUserIdByRole(userRole: string): Promise<string> {
const getRole = userData.users.find((element) => element.role === userRole);
return String (getRole?.id);
}

Categories

Resources