Babel plugin - How to transform JSX without react - javascript

I have wrote my own module which takes a JSX string as a parameter and turns it into a javascript object, so I call it like so:
import parser from 'own-parser'
console.log(parser("<h1>Hello world</h1>"))
This works, but what I actually need is to transform the JSX into the object when it compiles, so I could write it like a normal JSX expression:
var jsx = <h1>Hello World</h1>
and get the result from my function as output like so:
var jsx = {element: 'h1', children:[/*...*/]}
I undrestand there are many babel plugins like "babel-plugin-transform-jsx" which can accomplish this, but I want to learn about babel plugins and how they work so I can make my own.
I've tried to analize the code of the plugin mentioned above but still cannot understand how things work, for example, how does the plugin know that he is working with a JSXElement?
The only thing I am trying to do is to extract that JSX, put it inside my function and transform it into the function's return
How can I do that? Thanks

I've figured it out, turns out you can get the code of a node with path.toString(), for example to declare a visitor like that:
JSXElement(path, state) {
if (path.parentPath.type != "JSXElement") {
const parsed = parser(path.toString())
path.replaceWithSourceString(JSON.stringify(parsed))
}
}
This is not present in the babel plugin handbook, I suppose this is a bad practice, but anyways it is a quick solution in case anyone wondered

Related

Javascript function .toString() in webpack

In my webpack developing case, I need to output function as strings by function.toString(). But webpack may translate some statements into module styles.
const myFunc = function{
this.methods.log(Date.now())
}
myFunc.toString()
"myFunc(){this.methods.log(_Users_xxx_Desktop_designer_web_node_modules_babel_runtime_corejs2_core_js_date_now__WEBPACK_IMPORTED_MODULE_3___default()());}"
What I need:
"myFunc(){this.methods.log(Date.now())}"
I handled this pointer to correct object. I just want webkit to ignore this function.
For this particular case the transformation is done first by babel, cus you use transform-runtime plugin, it decides that the Date API needs to come from core-js. Webpack steps in later because it sees Date now refer to a imported lib, so it transform the import statement to WEBPACK_IMPORT_MODULE.
You either tune babel to disallow it transform Date, or you can do the reverse. You write a string of function, then eval it to get a real function.
const myFuncStr = `function (){
this.methods.log(Date.now())
}`
const myFunc = eval(myFuncStr)

How do I export a regex as a const in es6?

I have a regex which is repeatedly used in a number of classes. It's a violation of DRY and a potential pain if it needs to be changed in the future. Therefore I decided to move it to a common js and export it. Below is the code:
const CommonValues = {
TEXT_FILTER_REGEX: /^[,.?!:"—]$/
};
export CommonValues;
After importing CommonValues, I use it like this:
let result = CommonValues.TEXT_FILTER_REGEX.test('foo,bar'));
But no matter what I try, I keep getting this error in the console:
Uncaught Error: Module parse failed: 'const' can not be used as shorthand property (5:2)
You may need an appropriate loader to handle this file type.
I also tried exporting an integer and string the same way, they both worked without any trouble. This makes me wonder if regex is somehow treated differently when it comes to exporting?
This appears to have fixed itself miraculously. I'm totally baffled. I guess would be a temporary babel glitch.
Thanks for any advise.
I go it working by doing the below.
I'm not sure what your RegExp '/^[,.?!:"—]$/' does, but I tried with a digit RegEx =^[0-9]$ and got the expected result;
The error I got is about string type not having a test() defined on its prototype in TypeScript. Only RegExp has.
export const Constants = {
TEXT_FILTER_REGEX: new RegExp('^[,.?!:"—]$')
}
A working plunker is here
Test can be done the exact same way. You need to trim the /s and make it a RegExp object using a
new RegExp('UrRegexHere')

Does TypeScript have an equivalent of ES6 "Sets"

I want to extract all the unique properties from an array of objects, you can do so in ES6 very cleanly using the spread operator and the Set so:
var arr = [ {foo:1, bar:2}, {foo:2, bar:3}, {foo:3, bar:3} ]
const uniqueBars = [... new Set(arr.map(obj => obj.bar))];
>> [2, 3]
However, in TypeScript 1.8.31 this gives me the build error:
Cannot find name 'Set'
I know I can force VS to ignore it by using
declare var Set;
But I'm hoping for something TypeScript will compile into non-ES6 so that it could be used on older systems.
Does anyone know if there's such a feature I could use?
Edit:
Actually, even when I use declare var Set;, the above code compiles but throws this error repeatedly, so I'm not sure how to use it even without compiling down:
Uncaught TypeError: (intermediate value).slice is not a function
How can I update my code to use Set in TypeScript?
This worked for me.
One of the issues appears to be that typescript trys to use
ERROR TypeError: (intermediate value).slice is not a function
instead of Array.from();
in any event this code worked for me in my Angular 4 applicaiton
Array.from(new Set(Array)).sort(this.compareNumbers)
hope this helps someone
No. If you compile to ES5 or older Typescript only adds the syntactic changes from ES6. It doesn't add any of the standard library objects.
If you want those I suggest you look into something like core.js
You can use this type script library. Or maybe create your one set class using reference from this library

JS - Call function by name (in object notation)

I want to clean up some old code and optimize it, which often uses the same code. (with only different names of functions to call)
I make a easier example and no, I don't write on a game. But this example looks more comprehensible to explaination of my issue.
character.sleep(1);
character.changeName(name);
character.useItm(1423);
Easier Example:
object.function(parameters)
Target was something like this:
myFunc(funcName,value) {
character.{funcName}(value);
}
$('.btn_sleep') { myfunc('sleep','1'); }
$('.btn_cName') { myfunc('changeName','Harold'); }
$('.btn_uItem') { myfunc('useItem','1423'); }
First I thought about to use eval(), because no user-input will come near of this functions. But I dislike this idea because of the performance lost.
Then I looked around for alternatives and found window[] and new function() as solution.
But I dont get an idea how to use it, when I want to dynamcially call a function by name in an object-notation. (Or in worser cases, when you've to get the result for an if-condtion from a function, which you called with object-notation.)
Could anyone help?
The best way I know how to dynamically call functions is using bracket notation because it allows you to set your object path with a variable
function myFunc(funcName,value) {
character[funcName](value);
}
myfunc('sleep','1');

Is there a map() function in ExtJS?

ExtJS has Ext.each() function, but is there a map() also hidden somewhere?
I have tried hard, but haven't found anything that could fill this role. It seems to be something simple and trivial, that a JS library so large as Ext clearly must have.
Or when Ext really doesn't include it, what would be the best way to add it to Ext. Sure, I could just write:
Ext.map = function(arr, f) { ... };
But is this really the correct way to do this?
As of at least Ext4, Ext.Array.map is included.
http://docs.sencha.com/extjs/5.0.1/#!/api/Ext.Array-method-map
Since map is more of a utility than anything, I don't see why there would be any special way of plugging it into the Ext namespace; the way you propose would work well enough, though you might want to do it thusly:
if(Ext && typeof(Ext.map) == "undefined") { // only if Ext exists & map isn't already defined
Ext.map = function(arr, f) { ... };
}
Seems like that would be fine...but then, I don't use ExtJS, so I don't know. I did take a gander at their docs and it doesn't seem like there is anything special to do in this case.
It appears, that my colleges here are using ext-basex, which extends Array.prototype with map() and other methods.
So I can just write:
[1, 2, 3].map( function(){ ... } );
Problem solved.
What about using one of the hybrid libraries like Ext+Prototype or Ext+Jquery. I've been using Extjs+Prototypejs for a while now and it helped me a lot to work into the Extjs code with having the more familiar prototypejs along for the ride as well.
http://extjs.com/products/extjs/build/ will build a custom tar/zip file of all the files you need to run extjs and (prototypejs|jquery|yahooUI).
ExtJS doesn't replace Javascript language itself. Array functions aren't in the focus of ExtJS core. However there is a special Ext.Array object type. You can extend it on your own.
EDIT: Not Ext.Array, but just extended Array object.

Categories