javascript recast .toSource options ignored - javascript

I am trying to transform and reformat this javascript code:
if (name == "c") {b();}
using this recode plugin:
return j(file.source)
.find(j.Identifier)
.forEach(path => {
j(path).replaceWith(
j.identifier(path.node.name.split('').reverse().join(''))
);
})
.toSource({quote:'single'});
as saved here https://astexplorer.net/#/gist/994b660144d9e065906dc41bc14c9c39/c3910178f527d57de5422a0ddce9e515a460182d
I want to get the following output:
if (eman == 'c') {
b();
}
but the {quote:'single'} option is ignored, and I am not sure that there is an option to force indent on if body on new line.
Is this a bug with astexplorer, recode or I am doing something wrong?

The problem is that .toSource() uses recast.print() which tries to retain original formatting. prettyPrint() will respect more options:
var rc = require('recast');
rc.prettyPrint(ast, {quote:'single'}).code

Related

Custom word translator in React

Update: scroll to see my solution, can it be improved?
So I have this issue, I am building a word translator thats translates english to 'doggo', I have built this in vanilla JS but would like to do it React.
My object comes from firebase like this
dictionary = [
0: {
name: "paws",
paws: ["stumps", "toes beans"]
}
1: {
name: "fur",
fur: ["floof"]
}
2: {
name: "what"
what: ["wut"]
}
]
I then convert it to this format for easier access:
dictionary = {
what : ["wut"],
paws : ["stumps", "toe beans"],
fur : ["floof"]
}
Then, I have two text-area inputs one of which takes input and I would like the other one to output the corresponding translation. Currently I am just logging it to the console.
This works fine to output the array of the corresponding word, next I have another variable which I call 'levelOfDerp' which is basically a number between 0 - 2 (set to 0 by default) which I can throw on the end of the console.log() as follows to correspond to the word within the array that gets output.
dictionary.map(item => {
console.log(item[evt.target.value][levelOfDerp]);
});
When I do this I get a "TypeError: Cannot read property '0' of undefined". I am trying to figure out how to get past this error and perform the translation in real-time as the user types.
Here is the code from the vanilla js which performs the translation on a click event and everything at once. Not what I am trying to achieve here but I added it for clarity.
function convertText(event) {
event.preventDefault();
let text = inputForm.value.toLowerCase().trim();
let array = text.split(/,?\s+/);
array.forEach(word => {
if (dictionary[word] === undefined) {
outputForm.innerHTML += `${word} `;
noTranslationArr.push(word);
} else {
let output = dictionary[word][levelOfDerp];
if (output === undefined) {
output = dictionary[word][1];
if (output === undefined) {
output = dictionary[word][0];
}
}
outputForm.innerHTML += `${output} `;
hashtagArr.push(output);
}
});
addData(noTranslationArr);
}
Also here is a link to the translator in vanilla js to get a better idea of the project https://darrencarlin.github.io/DoggoSpk/
Solution, but could be better..
I found a solution but I just feel this code is going against the reason to use react in the first place.. My main concern is that I am declaring variables to store strings inside of an array within the function (on every keystroke) which I haven't really done in React, I feel this is going against best practice?
translate = evt => {
// Converting the firebase object
const dict = this.state.dictionary;
let dictCopy = Object.assign(
{},
...dict.map(item => ({ [item["name"]]: item }))
);
let text = evt.target.value.toLowerCase().trim();
let textArr = text.split(/,?\s+/);
let translation = "";
textArr.forEach(word => {
if (dictCopy[word] === undefined) {
translation += `${word} `;
} else {
translation += dictCopy[word][word][this.state.derpLvl];
}
});
this.setState({ translation });
};
levelOfDerp is not defined, try to use 'levelOfDerp' as string with quotes.
let output = dictionary[word]['levelOfDerp' ];
The problem happens because setState() is asynchronous, so by the time it's executed your evt.target.value reference might not be there anymore. The solution is, as you stated, to store that reference into a variable.
Maybe consider writing another function that handles the object conversion and store it in a variable, because as is, you're doing the conversion everytime the user inputs something.

How to Combine Multiple Return Functions (JavaScript)

I am learning JavaScript so that I can implement Google Tag Manager. I have a list of paths that I would like GTM to rewrite to something friendlier like so:
function() {
return document.location.pathname.indexOf('/l/138281/2016-06-07/dy383') > -1 ? 'Test Success' : undefined;
}
function() {
return document.location.pathname.indexOf('/l/138281/2016-04-03/55z63') > -1 ? 'SPP Contact Success' : undefined;
I'm just not sure how to combine these returns into one function (I currently have about 30 URLs to rewrite). I imagine I can use if/else, but advice would be quite lovely.
--edit--
URL Path Rewrite To
/test-638-jsj /test-success
/spp-zxcv-765 /spp-contact-success
/foo-asdf-123 /foo
/foo-bar-987 /foo-bar
The return function mentioned above does this beautifully for an individual link. I just want to be able to rewrite a series of URLs in one function (or however it makes sense to do this most specifically). Hopefully that helps clarify.
Thanks!
It is always a great idea to structure your code: separate abstract functionality from the specific problem.
What you are actually doing is scannins strings for occurences of keywords and returning specific values if such a keyword has been found.
Therefore, you need a function performing the above computation and a JavaScript datastructure holding your keywords and their values (= Object):
// Return patterns[key] if any key is found in string, else return string:
function match(string, patterns) {
for (key of Object.keys(patterns)) {
if (string.indexOf(key) > -1) return patterns[key];
}
return string;
}
var patterns = {
'/l/138281/2016-06-07/dy383': 'Test Success',
'/l/138281/2016-04-03/55z63': 'SPP Contact Success'
}
console.log(match('/l/138281/2016-06-07/dy383', patterns)); // "Test Success"
console.log(match('/doesnotexist', patterns)); // "/doesnotexist"
console.log(match(document.location.pathname, patterns));

DataTables custom detection plug-in and sorting order

i'm trying to implement a function on Datatables that has to look up the table data, do a regex and then, if it returns true, then, when i click on the header to sort data, it will sort it by the last 5 digits, ignoring the letters that comes up in the beginning of the string.
i have the following code
$.fn.dataTable.ext.oSort['custom'] = function (settings, col) {
return this.api().column(col, {order: 'index'}).nodes().map(function (td, i) {
var string= $(td).html();
return $.trim(string.substr(string.length - 4));
});
}
$.fn.dataTable.ext.type.detect.push(
function (value) {
var test = (/PT\d/).test(value);
return test ? 'custom' : null;
}
);
this is for a custom data that has lots of trash in the beggining, like country code and stuff, but the data order is only by the last 5 digits.
i've been searching all over i'm having a hard time to understand and debug. Debuguing the detect works, if 1 put an alert, it gives-me true when it hits the colum with the values i want, but the custom sorting doesn't work, can anybody help?
hope i'm clear about it
thanks
actualy i solved it myself.
the problem was that DataTables needs to make the entire column return true, so, if the regex fails in any value in the same column it fails.
$.fn.dataTable.ext.type.detect.unshift(
function (d) {
var pt = (/^PT\d/).test(d);
var es= (/^ES\d/).test(d);
var en= (/^EN\d/).test(d);
if (pt || es|| en) {
return 'custom'
} else {
return false;
}
}
);
$.fn.dataTable.ext.type.order['custom-pre'] = function (string) {
return $.trim(string.substr(string.length - 4));
};
so this is my last code used and it works just fine.
i'm posting it so anybody with the same problem can have a clue to solve some future problem :)

ES5 - Parse script version from src path

I was hoping someone already had this done but what I'm trying to do is output a list of semantic versions of various javascript libraries. Let's assume I have the the following input:
https://code.jquery.com/jquery-2.1.3.js
//maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css
https://cdnjs.cloudflare.com/ajax/libs/1140/2.0/1140.css
https://cdnjs.cloudflare.com/ajax/libs/Base64/0.3.0/base64.min.js
https://cdnjs.cloudflare.com/ajax/libs/angular-google-maps/2.1.0-X.10/angular-google-maps.min.js
https://cdnjs.cloudflare.com/ajax/libs/swagger-ui/2.1.8-M1/swagger-ui.min.js
https://cdnjs.cloudflare.com/BLAH/BLAH.min.js
I'd like to call a function on each of these strings and have it output the semver from the path:
2.1.3
3.3.4
1140 or 2.0 (prefer)
0.3.0
2.1.0-X.10
2.1.8-M1
null
I was unable to find any existing libraries and was hoping someone had one handy that worked on IE9ish.
I was able to get this to work by using the following code:
it('should parse version from script source', () => {
function getVersion(source:string) {
if (!source) {
return null;
}
var versionRegex = /(v?((\d+)\.(\d+)(\.(\d+))?)(?:-([\dA-Za-z\-]+(?:\.[\dA-Za-z\-]+)*))?(?:\+([\dA-Za-z\-]+(?:\.[\dA-Za-z\-]+)*))?)/;
var matches = versionRegex.exec(source);
if (matches && matches.length > 0) {
return matches[0];
}
return null;
}
expect(getVersion('https://code.jquery.com/jquery-2.1.3.js')).toBe('2.1.3');
expect(getVersion('//maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css')).toBe('3.3.4');
expect(getVersion('https://cdnjs.cloudflare.com/ajax/libs/1140/2.0/1140.css')).toBe('2.0');
expect(getVersion('https://cdnjs.cloudflare.com/ajax/libs/Base64/0.3.0/base64.min.js')).toBe('0.3.0');
expect(getVersion('https://cdnjs.cloudflare.com/ajax/libs/angular-google-maps/2.1.0-X.10/angular-google-maps.min.js')).toBe('2.1.0-X.10');
expect(getVersion('https://cdnjs.cloudflare.com/ajax/libs/swagger-ui/2.1.8-M1/swagger-ui.min.js')).toBe('2.1.8-M1');
expect(getVersion('https://cdnjs.cloudflare.com/BLAH/BLAH.min.js')).toBe(null);
});

Parse.Query and-combination issue

In cloud code, I made a query using this sort of code:
theMainQuery = new Parse.Query("myClass");
theMainQuery.equalTo("fieldOne", "champion");
theSubQuery = new Parse.Query("myClass");
theSubQuery.equalTo("fieldTwo", "USA");
the2ndSubQuery = new Parse.Query("myClass");
the2ndSubQuery.equalTo("fieldTwo", "BRASIL");
theSubQuery = Parse.Query.or(theSubQuery,the2ndSubQuery);
theMainQuery = Parse.Query.and(theMainQuery,theSubQuery);
In other words I want a query based on this condition:
((fieldOne equals "champion") and ((fieldTwo equals "USA") or (fieldTwo equals "BRASIL")))
In usual C style writing I want to select records matching:
((fieldOne == "champion") && ((fieldTwo == "USA") || (fieldTwo == "BRASIL")))
The problem is that it does not work, I suppose my Parse.Query.and is wrong. Then how can I get the result I want?
Of course, I would be happy to avoid reformulating the query in this long format:
(((fieldOne == "champion") && (fieldTwo == "USA")) || ((fieldOne == "champion") && (fieldTwo == "BRASIL")))
Okay so what you want to do can be done within one Query object.
I feel what your looking for is 'containedIn'... So you specify the key 'fieldTwo' and pass in an array of values to 'or' with.
So heres what I think it should look like, I implemented this in Objective-C but not javascript. but heres my javascript version
var query = new Parse.Query('myclass');
query.equalTo('fieldOne', 'champion');
query.containedIn('fieldTwo', ['USA', 'Brazil']);
query.find();
I hope this was what your looking for... By the way, I was able to find this in the docs, https://parse.com/docs/js_guide#queries. There docs are very helpful but sometimes doesn't help me :P

Categories