From 3353d27ba20103c37fa8c7ee999077a3363b9ea0 Mon Sep 17 00:00:00 2001 From: Onoshko Dan Date: Tue, 15 Apr 2014 19:22:58 +0700 Subject: [PATCH] ColaScript README.md --- README.md | 929 ++++++++++++++++++------------------------------------ 1 file changed, 301 insertions(+), 628 deletions(-) diff --git a/README.md b/README.md index 27d06cd6..37bfa223 100644 --- a/README.md +++ b/README.md @@ -1,640 +1,313 @@ -UglifyJS 2 -========== -[![Build Status](https://travis-ci.org/mishoo/UglifyJS2.png)](https://travis-ci.org/mishoo/UglifyJS2) - -UglifyJS is a JavaScript parser, minifier, compressor or beautifier toolkit. - -This page documents the command line utility. For -[API and internals documentation see my website](http://lisperator.net/uglifyjs/). -There's also an -[in-browser online demo](http://lisperator.net/uglifyjs/#demo) (for Firefox, -Chrome and probably Safari). - -Install -------- - -First make sure you have installed the latest version of [node.js](http://nodejs.org/) -(You may need to restart your computer after this step). - -From NPM for use as a command line app: - - npm install uglify-js -g - -From NPM for programmatic use: - - npm install uglify-js - -From Git: - - git clone git://github.com/mishoo/UglifyJS2.git - cd UglifyJS2 - npm link . - -Usage ------ - - uglifyjs [input files] [options] - -UglifyJS2 can take multiple input files. It's recommended that you pass the -input files first, then pass the options. UglifyJS will parse input files -in sequence and apply any compression options. The files are parsed in the -same global scope, that is, a reference from a file to some -variable/function declared in another file will be matched properly. - -If you want to read from STDIN instead, pass a single dash instead of input -files. - -The available options are: - -``` - --source-map Specify an output file where to generate source map. - [string] - --source-map-root The path to the original source to be included in the - source map. [string] - --source-map-url The path to the source map to be added in //# - sourceMappingURL. Defaults to the value passed with - --source-map. [string] - --source-map-include-sources - Pass this flag if you want to include the content of - source files in the source map as sourcesContent - property. [boolean] - --in-source-map Input source map, useful if you're compressing JS that was - generated from some other original code. - --screw-ie8 Pass this flag if you don't care about full compliance - with Internet Explorer 6-8 quirks (by default UglifyJS - will try to be IE-proof). [boolean] - --expr Parse a single expression, rather than a program (for - parsing JSON) [boolean] - -p, --prefix Skip prefix for original filenames that appear in source - maps. For example -p 3 will drop 3 directories from file - names and ensure they are relative paths. You can also - specify -p relative, which will make UglifyJS figure out - itself the relative paths between original sources, the - source map and the output file. [string] - -o, --output Output file (default STDOUT). - -b, --beautify Beautify output/specify output options. [string] - -m, --mangle Mangle names/pass mangler options. [string] - -r, --reserved Reserved names to exclude from mangling. - -c, --compress Enable compressor/pass compressor options. Pass options - like -c hoist_vars=false,if_return=false. Use -c with no - argument to use the default compression options. [string] - -d, --define Global definitions [string] - -e, --enclose Embed everything in a big function, with a configurable - parameter/argument list. [string] - --comments Preserve copyright comments in the output. By default this - works like Google Closure, keeping JSDoc-style comments - that contain "@license" or "@preserve". You can optionally - pass one of the following arguments to this flag: - - "all" to keep all comments - - a valid JS regexp (needs to start with a slash) to keep - only comments that match. - Note that currently not *all* comments can be kept when - compression is on, because of dead code removal or - cascading statements into sequences. [string] - --preamble Preamble to prepend to the output. You can use this to - insert a comment, for example for licensing information. - This will not be parsed, but the source map will adjust - for its presence. - --stats Display operations run time on STDERR. [boolean] - --acorn Use Acorn for parsing. [boolean] - --spidermonkey Assume input files are SpiderMonkey AST format (as JSON). - [boolean] - --self Build itself (UglifyJS2) as a library (implies - --wrap=UglifyJS --export-all) [boolean] - --wrap Embed everything in a big function, making the “exports” - and “global” variables available. You need to pass an - argument to this option to specify the name that your - module will take when included in, say, a browser. - [string] - --export-all Only used when --wrap, this tells UglifyJS to add code to - automatically export all globals. [boolean] - --lint Display some scope warnings [boolean] - -v, --verbose Verbose [boolean] - -V, --version Print version number and exit. [boolean] -``` - -Specify `--output` (`-o`) to declare the output file. Otherwise the output -goes to STDOUT. - -## Source map options - -UglifyJS2 can generate a source map file, which is highly useful for -debugging your compressed JavaScript. To get a source map, pass -`--source-map output.js.map` (full path to the file where you want the -source map dumped). - -Additionally you might need `--source-map-root` to pass the URL where the -original files can be found. In case you are passing full paths to input -files to UglifyJS, you can use `--prefix` (`-p`) to specify the number of -directories to drop from the path prefix when declaring files in the source -map. - -For example: - - uglifyjs /home/doe/work/foo/src/js/file1.js \ - /home/doe/work/foo/src/js/file2.js \ - -o foo.min.js \ - --source-map foo.min.js.map \ - --source-map-root http://foo.com/src \ - -p 5 -c -m - -The above will compress and mangle `file1.js` and `file2.js`, will drop the -output in `foo.min.js` and the source map in `foo.min.js.map`. The source -mapping will refer to `http://foo.com/src/js/file1.js` and -`http://foo.com/src/js/file2.js` (in fact it will list `http://foo.com/src` -as the source map root, and the original files as `js/file1.js` and -`js/file2.js`). - -### Composed source map - -When you're compressing JS code that was output by a compiler such as -CoffeeScript, mapping to the JS code won't be too helpful. Instead, you'd -like to map back to the original code (i.e. CoffeeScript). UglifyJS has an -option to take an input source map. Assuming you have a mapping from -CoffeeScript → compiled JS, UglifyJS can generate a map from CoffeeScript → -compressed JS by mapping every token in the compiled JS to its original -location. - -To use this feature you need to pass `--in-source-map -/path/to/input/source.map`. Normally the input source map should also point -to the file containing the generated JS, so if that's correct you can omit -input files from the command line. - -## Mangler options - -To enable the mangler you need to pass `--mangle` (`-m`). The following -(comma-separated) options are supported: - -- `sort` — to assign shorter names to most frequently used variables. This - saves a few hundred bytes on jQuery before gzip, but the output is - _bigger_ after gzip (and seems to happen for other libraries I tried it - on) therefore it's not enabled by default. - -- `toplevel` — mangle names declared in the toplevel scope (disabled by - default). - -- `eval` — mangle names visible in scopes where `eval` or `with` are used - (disabled by default). - -When mangling is enabled but you want to prevent certain names from being -mangled, you can declare those names with `--reserved` (`-r`) — pass a -comma-separated list of names. For example: - - uglifyjs ... -m -r '$,require,exports' - -to prevent the `require`, `exports` and `$` names from being changed. - -## Compressor options - -You need to pass `--compress` (`-c`) to enable the compressor. Optionally -you can pass a comma-separated list of options. Options are in the form -`foo=bar`, or just `foo` (the latter implies a boolean option that you want -to set `true`; it's effectively a shortcut for `foo=true`). - -- `sequences` -- join consecutive simple statements using the comma operator - -- `properties` -- rewrite property access using the dot notation, for - example `foo["bar"] → foo.bar` - -- `dead_code` -- remove unreachable code - -- `drop_debugger` -- remove `debugger;` statements +![logo](http://trigen.pro/colalogo.png) -- `unsafe` (default: false) -- apply "unsafe" transformations (discussion below) +ColaScript is a language that compiles in JavaScript. This language is similar to Dart, CoffeeScript, Python and PHP, with some original ideas. Compiler based on [UglifyJS2](https://github.com/mishoo/UglifyJS2). In present time compiler in development. Play with language you can in `lib/index.html`. -- `conditionals` -- apply optimizations for `if`-s and conditional - expressions +# to do: -- `comparisons` -- apply certain optimizations to binary nodes, for example: - `!(a <= b) → a > b` (only when `unsafe`), attempts to negate binary nodes, - e.g. `a = !b && !c && !d && !e → a=!(b||c||d||e)` etc. +- semicolon is always required, status: done -- `evaluate` -- attempt to evaluate constant expressions +## Operators: -- `booleans` -- various optimizations for boolean context, for example `!!a - ? b : c → a ? b : c` +### Unary +- `varname?` -- `loops` -- optimizations for `do`, `while` and `for` loops when we can - statically determine the condition + bool exist = SOME?; -- `unused` -- drop unreferenced functions and variables -- `hoist_funs` -- hoist function declarations +### Binary +- `**`, status: done -- `hoist_vars` (default: false) -- hoist `var` declarations (this is `false` - by default because it seems to increase the size of the output in general) + int pow = 5 ** 2; // 25 + +- `%%`, status: done -- `if_return` -- optimizations for if/return and if/continue + int modulo = 5 %% 3; // 2 + +- `?=`, status: done -- `join_vars` -- join consecutive `var` statements + var undef, def = 5; + + def ?= undef; // def == 5 + undef = 6; + def ?= undef; // def == 6 + +- `a ? b` -- `cascade` -- small optimization for sequences, transform `x, x` into `x` - and `x = something(), x` into `x = something()` - -- `warnings` -- display warnings when dropping unreachable code or unused - declarations etc. - -- `negate_iife` -- negate "Immediately-Called Function Expressions" - where the return value is discarded, to avoid the parens that the - code generator would insert. - -- `pure_getters` -- the default is `false`. If you pass `true` for - this, UglifyJS will assume that object property access - (e.g. `foo.bar` or `foo["bar"]`) doesn't have any side effects. - -- `pure_funcs` -- default `null`. You can pass an array of names and - UglifyJS will assume that those functions do not produce side - effects. DANGER: will not check if the name is redefined in scope. - An example case here, for instance `var q = Math.floor(a/b)`. If - variable `q` is not used elsewhere, UglifyJS will drop it, but will - still keep the `Math.floor(a/b)`, not knowing what it does. You can - pass `pure_funcs: [ 'Math.floor' ]` to let it know that this - function won't produce any side effect, in which case the whole - statement would get discarded. The current implementation adds some - overhead (compression will be slower). - -- `drop_console` -- default `false`. Pass `true` to discard calls to - `console.*` functions. - -### The `unsafe` option - -It enables some transformations that *might* break code logic in certain -contrived cases, but should be fine for most code. You might want to try it -on your own code, it should reduce the minified size. Here's what happens -when this flag is on: - -- `new Array(1, 2, 3)` or `Array(1, 2, 3)` → `[1, 2, 3 ]` -- `new Object()` → `{}` -- `String(exp)` or `exp.toString()` → `"" + exp` -- `new Object/RegExp/Function/Error/Array (...)` → we discard the `new` -- `typeof foo == "undefined"` → `foo === void 0` -- `void 0` → `undefined` (if there is a variable named "undefined" in - scope; we do it because the variable name will be mangled, typically - reduced to a single character). - -### Conditional compilation - -You can use the `--define` (`-d`) switch in order to declare global -variables that UglifyJS will assume to be constants (unless defined in -scope). For example if you pass `--define DEBUG=false` then, coupled with -dead code removal UglifyJS will discard the following from the output: -```javascript -if (DEBUG) { - console.log("debug stuff"); -} -``` - -UglifyJS will warn about the condition being always false and about dropping -unreachable code; for now there is no option to turn off only this specific -warning, you can pass `warnings=false` to turn off *all* warnings. - -Another way of doing that is to declare your globals as constants in a -separate file and include it into the build. For example you can have a -`build/defines.js` file with the following: -```javascript -const DEBUG = false; -const PRODUCTION = true; -// etc. -``` - -and build your code like this: - - uglifyjs build/defines.js js/foo.js js/bar.js... -c - -UglifyJS will notice the constants and, since they cannot be altered, it -will evaluate references to them to the value itself and drop unreachable -code as usual. The possible downside of this approach is that the build -will contain the `const` declarations. - - -## Beautifier options - -The code generator tries to output shortest code possible by default. In -case you want beautified output, pass `--beautify` (`-b`). Optionally you -can pass additional arguments that control the code output: - -- `beautify` (default `true`) -- whether to actually beautify the output. - Passing `-b` will set this to true, but you might need to pass `-b` even - when you want to generate minified code, in order to specify additional - arguments, so you can use `-b beautify=false` to override it. -- `indent-level` (default 4) -- `indent-start` (default 0) -- prefix all lines by that many spaces -- `quote-keys` (default `false`) -- pass `true` to quote all keys in literal - objects -- `space-colon` (default `true`) -- insert a space after the colon signs -- `ascii-only` (default `false`) -- escape Unicode characters in strings and - regexps -- `inline-script` (default `false`) -- escape the slash in occurrences of - ` 10 ? b; // a == 5 + a = 11; + a = a > 10 ? b; // a == 3 + +- `is`, status: done + + bool isRegExp = /[^\d]+/g is RegExp; // true + +- `isnt`, status: done + + bool isntString = 3.14 isnt String; // true + + + + +### Multiple +- `..:` + + Object profile = { + name : "dan", + nick : "dan", + friends : [ + { name : "eric", nick : "eric" } + ], + "info" : "coder" + } + ..name += "iil" + ..nick += "green" + ..friends[0]: + ..name = profile.friends[0].name.capitalize() + ..nick += "bro"; + ..info += ", student"; + + +- `a > b > c` + + if( 0 < x < 100 ) console.log("x E (0; 100)"); + + +### Compilator +- `@require` + + @require "./library/jquery.js", "./library/underscore.js" + +- `@use` + + @use strict, typing + @use asmjs + +- `@if @end_if @else` + + @if target == 'web' + @require './main.cola' + @else + @require './mobile/main.cola' + @end_if + + +## Expressins +- `switch` assigmention + + String weather = switch(temperature){ + case -10: 'cold'; + case 20: 'normal'; + case 35: 'hot'; + }; + +- `with` scoping, status: its need?? + + with(document.body.querySelector('ul').childNodes){ + var txt = 'text'; + + forEach((li){ + li.innerHTML = txt; + }); + } + + console.log(txt); // undefined + + +## Vars +- declaration with type + + int b = 584; + Array arr = []; + Object obj = {}; + String str = ""; + +- multiple assigment + + [a, b, c] = [b, c, a]; + {poet: {String name, address: [street, city]}} = futurists; + [a, ..., b] = someArray; + + +### bool +- aliases, status: done + + yes === on === true; + no === off === false; + + +### String +- \` new string \`, status: done + + String name = `dangreen`; + +- multiline, status: done + + String ml = " + + Lorem ipsum, + Lorem ipsum. + + "; + +- raw, status: done + + String str = r"\n \r"; // "\\n \\r" + +- templating, status : done + + String name = "dan"; + + console.log("My name is @name."); // My name is dan. + name = "eric"; + console.log("My name is @name."); // My name is eric. + console.log("My name is @{name.capitalize()} or {{name.capitalize()}}"); // My name is Eric. + +### RegExp +- multiline ( and x flag ), status: done + + RegExp re = / + ([^\d]+)- + (\w+) + /gx; + + +### Arrays +- pushing + + var arr = [3, 5, 6, 7]; + arr[] = 4; // [3, 5, 6, 7, 4] + +- part assigment + + arr[0..2] = [0,1]; // [0, 1, 7, 4] + arr[0..2] = []; // [7, 4] + +- inline array ranging + + arr = [10..1]; // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] + arr = [1..10]; // [10, 9, 8, 7, 6, 5, 4, 3, 2, 1] + +### Functions +- without `function` keyword + + void main(){ + console.log('Hello World!'); + } + +- binding toplevel `main` functions to onload event + + // lib.cola + + main(){ + console.log('Hello World from lib.cola!'); + } + + // main.cola + + require "./lib.cola"; + + main(){ + console.log('Hello World!'); + } + +- arrow functions + + print(str) => console.log(str); + + +- named arguments + + hello(String name:) => console.log("Hello @name!"); + hello(name: 'dangreen'); // Hello dangreen! + + hello(name: "World") => console.log("Hello @name!"); + hello(); // Hello World! + +- defaults for positional arguments + + hello(String name = "World!") => console.log("Hello @name!"); + hello('dangreen'); // Hello dangreen! + hello(); // Hello World! + +- some arguments into array + + main(name, skills...){ + console.log("My name is @name, my skills:"); + skills.forEach((skill) => console.log("@skill,")); + } + + +## Classes +- classes +- singletones +- injectors + + class A { + + private int a = 123; + protected var o = {}; + + readonly String about = "class"; + + A(a){ + about = "some else"; + } + + static Hello() => "hello!"; + + public String about() => about; + } + + class B extends A { + + B(){ + parent(); + about += "!"; + } + + B.anotherConstructor(){ + about = "ups!"; + } + + get some => "some " + about; + set some(val) => about += val; + } + + singleton S { // in fact this is object + int x = 45; + String s = "txt"; + + say(some){ + alert(some); + } + + int operator[](int index) => index + 584; + operator[]=(int index, int val) => x = index + val; + + String operator.(String key) => key + "!"; + operator.(String key, String value) => s = "@key @value"; + + } + + injector String { + String replaceAll(a, b){ + String res = this; + while(res.indexOf(a) != -1) res = res.replace(a, b); + return res; + } + } + + // or + + String String::replaceAll(a, b){ + String res = this; + while(res.indexOf(a) != -1) res = res.replace(a, b); + return res; + } + +### Statistic + +- 30 feature ( without classes ) +- 12 done