⬆️ ⬇️

Another JavaScript preprocessor

Are you interested in the possibility of writing such things in JavaScript?



$ ('.btn-toogle').onclick (lambda $ (this).toggleClass ('active')); 


 var chars = Array.prototype.forEach.call ('0123456789abcdef', lambda arg.charCodeAt (0)); 


 function fn (arg1 = 100, arg2 = 'test'){ ... } 


 var html = h` <div> <a href="...">link</a> </div>`; 


 for (var key, value in object) console.log (key + ' = ' + value); 




Then perhaps this article will interest you.



I will not paint any boring things like stories or why I did this thing. Better try to briefly tell how it works and what it can do.

')

The preprocessor is written in Node.JS, and the PEG.js parser generator is used to parse JavaScript. By the way, one of the strengths of the preprocessor (well, for me personally) is that regular JavaScript code parses perfectly. Well, if, of course, there are no keywords in the code like lambda, module, import or export.



Of course, the JavaScript parser does not differ in performance, but, fortunately, caching quite compensates for this.



Most of the features already described above, but now I will try to talk about them in more detail.



1. Abbreviated recording of functions.



 var way0 = lambda arg.charCodeAt (0), way1 = lambda (arg) arg.charCodeAt (0), way2 = lambda { return arg.charCodeAt (0) }, way3 = lambda (arg){ arg.charCodeAt (0) }, result = function (arg){ return arg.charCodeAt (0) }; 


All four recording methods give the same result. The arg argument is added to functions that lack the usual arguments. If the whole body of the function consists of a single operation (statement; to be honest, I don’t know how to correctly speak Russian), the function will return the result of this operation.



Here are a couple of examples:

 var //     example0 = lambda (a, b, c, d) a + b + c + d, //   forEach example1 = lambda (a, fn) for (var i = 0; i < a.length; i ++) fn (a [i]), //     a  b. example2 = lambda { a: arg * 2, b: arg }; 




2. Arguments of functions by default.



Nothing particularly, the headline already speaks for itself.

 function fn (arg1 = 100, arg2 = 'test'){ ... } 


Arguments will be compared (without type casting) with undefined. If suddenly they are equal, they will be set to default values.



3. Multi-line strings (I apologize for such an ugly expression).



For starters, this is just a way to write strings using the “` ”character as quotes. You can finally stop placing "\" at the ends of lines (although, I confess, no one usually writes so that multi-line strings are needed). But that is not all. Depending on the character before the opening quote, the preprocessor can somehow process the text inside in a special way. Write “h” and the preprocessor will compress the string as html-code, “c” - as css-code, “s” - remove consecutive spaces, “l” - convert LESS inside the string into CSS (well, also compress), and lp ”is my favorite :) - not only will convert LESS to CSS, but also leave the possibility to further define properties through JavaScript. Pretty comfortable.



4. Modules.



In short, it is in some sense an analogue of classes from the same Java. But by no means ordinary classes. JavaScript already has prototypes, right?



Modules replace what is commonly called static classes in other languages ​​(I hope this term exists).



An example of a simple module:


 module Example { function init (){ // ... } } 


The "init" function will be called when the script starts (well, more on that later).



And two modules look like this, if one of them is used by the other:


 module First { export function test (){ console.log ('    .'); } function init (){ console.log (' — .'); } } module Second { import First; function init (){ console.log ('   — ,       ,   .'); First.test (); } } 




If you put in front of the name of the imported class "@", the imported class can be initialized and later imported. It helps if each of the two classes suddenly needs to import another, although, of course, architecturally this structure looks repulsive.



Well, there are also exported variables available only for reading:

 module First { import @Second; export function test (){ console.log ('    «1024»: ' + Second.value); } } module Second { import First; export var value = 1024; function init (){ First.test (); } } 




By the way, it is not necessary to use modules by other modules. Although desirable. :)



5. Preprocessor options.



To customize the build code, you can use tricky comments at the beginning of the file:

 // ==Jsx== // @target web:onload // @build-to build/ // @define __VERSION__ 1.00 // @import utils/string.format // @include jquery.min.js // ==/Jsx== 


(Approximately in the same style comments for UserScript are written.)







These are not all parameters, as well as not all features, but, in my opinion, the article has already turned out to be too big for a brief description.



Download the current version from here . I apologize in advance for all possible errors and thank you for your attention. :)

Source: https://habr.com/ru/post/191858/



All Articles