"
(file, bookmark) ->
md = fs.readFileSync "#{sectionsSourceFolder}/#{file}.md", 'utf-8'
md = md.replace /<%= releaseHeader %>/g, releaseHeader
md = md.replace /<%= majorVersion %>/g, majorVersion
md = md.replace /<%= fullVersion %>/g, CoffeeScript.VERSION
- html = marked md, renderer: markdownRenderer
+ html = markdownRenderer.render md
html = _.template(html)
codeFor: codeFor()
releaseHeader: releaseHeader
diff --git a/docs/v1/annotated-source/grammar.html b/docs/v1/annotated-source/grammar.html
index 231a291b..eb724d82 100644
--- a/docs/v1/annotated-source/grammar.html
+++ b/docs/v1/annotated-source/grammar.html
@@ -968,6 +968,7 @@ and optional references to the superclass.
o 'Identifier AS Identifier', ->new ExportSpecifier $1, $3
o 'Identifier AS DEFAULT', ->new ExportSpecifier $1, new Literal $3
o 'DEFAULT', ->new ExportSpecifier new Literal $1
+ o 'DEFAULT AS Identifier', ->new ExportSpecifier new Literal($1), $3
]
diff --git a/docs/v1/annotated-source/lexer.html b/docs/v1/annotated-source/lexer.html
index 1a34a187..6ae28040 100644
--- a/docs/v1/annotated-source/lexer.html
+++ b/docs/v1/annotated-source/lexer.html
@@ -219,6 +219,7 @@ it has consumed.
@seenFor = no# Used to recognize FORIN, FOROF and FORFROM tokens.
@seenImport = no# Used to recognize IMPORT FROM? AS? tokens.
@seenExport = no# Used to recognize EXPORT FROM? AS? tokens.
+ @importSpecifierList = no# Used to identify when in an IMPORT {...} FROM? ...
@exportSpecifierList = no# Used to identify when in an EXPORT {...} FROM? ...
@chunkLine =
@@ -380,10 +381,10 @@ though is means === otherwise.
if @tag() in ['DEFAULT', 'IMPORT_ALL', 'IDENTIFIER']
@token 'AS', id
return id.length
- if id is'as'and @seenExport and @tag() is'IDENTIFIER'
+ if id is'as'and @seenExport and @tag() in ['IDENTIFIER', 'DEFAULT']
@token 'AS', id
return id.length
- if id is'default'and @seenExport
+ if id is'default'and @seenExport and @tag() in ['EXPORT', 'AS']
@token 'DEFAULT', id
return id.length
@@ -742,6 +743,8 @@ can close multiple indents, so we need to know how far in we happen to be.
indent = match[0]
@seenFor = no
+ @seenImport = nounless @importSpecifierList
+ @seenExport = nounless @exportSpecifierList
size = indent.length - 1 - indent.lastIndexOf '\n'
noNewlines = @unfinished()
@@ -923,7 +926,11 @@ parentheses that indicate a method call from regular parentheses, and so on.
@error message, origin[2] if message
return value.length if skipToken
- if value is'{'and prev?[0] is'EXPORT'
+ if value is'{'and @seenImport
+ @importSpecifierList = yes
+ elseif @importSpecifierList and value is'}'
+ @importSpecifierList = no
+ elseif value is'{'and prev?[0] is'EXPORT'
@exportSpecifierList = yeselseif @exportSpecifierList and value is'}'
@exportSpecifierList = no
@@ -1571,10 +1578,14 @@ not specified, the length of value will be used.
validateEscapes: (str, options = {}) ->
- match = INVALID_ESCAPE.exec str
+ invalidEscapeRegex =
+ if options.isRegex
+ REGEX_INVALID_ESCAPE
+ else
+ STRING_INVALID_ESCAPE
+ match = invalidEscapeRegex.exec str
returnunless match
[[], before, octal, hex, unicode] = match
- returnif options.isRegex and octal and octal.charAt(0) isnt'0'
message =
if octal
"octal escape sequences are not allowed"
@@ -2040,7 +2051,7 @@ POSSIBLY_DIVISION = /// ^ /=?\s ///
The command-line version of coffee is available as a Node.js utility. The core compiler however, does not depend on Node, and can be run in any JavaScript environment, or in the browser (see Try CoffeeScript).
+
Installation
+
The command-line version of coffee is available as a Node.js utility. The core compiler however, does not depend on Node, and can be run in any JavaScript environment, or in the browser (see Try CoffeeScript).
To install, first make sure you have a working copy of the latest stable version of Node.js. You can then install CoffeeScript globally with npm:
-
-
npm install --global coffee-script
-
When you need CoffeeScript as a dependency of a project, within that project’s folder you can install it locally:
-
-
npm install --save coffee-script
-
+
npm install --global coffee-script
+
+
When you need CoffeeScript as a dependency of a project, within that project’s folder you can install it locally:
+
npm install --save coffee-script
+
+
-
Usage
Once installed, you should have access to the coffee command, which can execute scripts, compile .coffee files into .js, and provide an interactive REPL. The coffee command takes the following options:
+
Usage
+
Once installed, you should have access to the coffee command, which can execute scripts, compile .coffee files into .js, and provide an interactive REPL. The coffee command takes the following options:
-
+
+
+
Option
+
Description
+
+
-
-
-c, --compile
-
Compile a .coffee script into a .js JavaScript file of the same name.
-
-
-
-m, --map
-
Generate source maps alongside the compiled JavaScript files. Adds sourceMappingURL directives to the JavaScript as well.
-
-
-
-M, --inline-map
-
Just like --map, but include the source map directly in the compiled JavaScript files, rather than in a separate file.
-
-
-
-
-i, --interactive
-
+
-i, --interactive
Launch an interactive CoffeeScript session to try short snippets. Identical to calling coffee with no arguments.
-
-
-
-o, --output [DIR]
-
Write out all compiled JavaScript files into the specified directory. Use in conjunction with --compile or --watch.
-
-
-
-w, --watch
-
Watch files for changes, rerunning the specified command when any file is updated.
-
-
-
-p, --print
-
Instead of writing out the JavaScript as a file, print it directly to stdout.
-
-
-
-s, --stdio
-
-
Pipe in CoffeeScript to STDIN and get back JavaScript over STDOUT. Good for use with processes written in other languages. An example:
-cat src/cake.coffee | coffee -sc
-
+
Pipe in CoffeeScript to STDIN and get back JavaScript over STDOUT. Good for use with processes written in other languages. An example: cat src/cake.coffee | coffee -sc
-
-
-l, --literate
-
Parses the code as Literate CoffeeScript. You only need to specify this when passing in code directly over stdio, or using some sort of extension-less file name.
-
-
-
-e, --eval
-
-
Compile and print a little snippet of CoffeeScript directly from the command line. For example:
-coffee -e "console.log num for num in [10..1]"
-
+
Compile and print a little snippet of CoffeeScript directly from the command line. For example: coffee -e "console.log num for num in [10..1]"
-
-
-
-r, --require [MODULE]
-
+
-r, --require [MODULE]
require() the given module before starting the REPL or evaluating the code given with the --eval flag.
Instead of parsing the CoffeeScript, just lex it, and print out the token stream:
-[IDENTIFIER square] [= =] [PARAM_START (] ...
-
+
Instead of parsing the CoffeeScript, just lex it, and print out the token stream. Used for debugging the compiler.
-
-
-n, --nodes
-
-
Instead of compiling the CoffeeScript, just lex and parse it, and print out the parse tree:
-
-Block
- Assign
- Value IdentifierLiteral: square
- Code
- Param IdentifierLiteral: x
- Block
- Op *
- Value IdentifierLiteral: x
- Value IdentifierLiteral: x
-
-
+
Instead of compiling the CoffeeScript, just lex and parse it, and print out the parse tree. Used for debugging the compiler.
-
-
--nodejs
-
-
The node executable has some useful options you can set, such as
---debug, --debug-brk, --max-stack-size, and --expose-gc. Use this flag to forward options directly to Node.js. To pass multiple flags, use --nodejs multiple times.
-
+
The node executable has some useful options you can set, such as --debug, --debug-brk, --max-stack-size, and --expose-gc. Use this flag to forward options directly to Node.js. To pass multiple flags, use --nodejs multiple times.
-
-
--no-header
-
Suppress the “Generated by CoffeeScript” header.
-
-
-
-
-
Examples:
+
Examples:
+
Compile a directory tree of .coffee files in src into a parallel tree of .js files in lib: coffee --compile --output lib/ src/
Watch a file for changes, and recompile it every time the file is saved:
@@ -908,19 +840,22 @@ cubes = (function() {
-
Literate CoffeeScript
Besides being used as an ordinary programming language, CoffeeScript may also be written in “literate” mode. If you name your file with a .litcoffee extension, you can write it as a Markdown document — a document that also happens to be executable CoffeeScript code. The compiler will treat any indented blocks (Markdown’s way of indicating source code) as code, and ignore the rest as comments.
+
Literate CoffeeScript
+
Besides being used as an ordinary programming language, CoffeeScript may also be written in “literate” mode. If you name your file with a .litcoffee extension, you can write it as a Markdown document — a document that also happens to be executable CoffeeScript code. The compiler will treat any indented blocks (Markdown’s way of indicating source code) as code, and ignore the rest as comments.
I’m fairly excited about this direction for the language, and am looking forward to writing (and more importantly, reading) more programs in this style. More information about Literate CoffeeScript, including an example program, are available in this blog post.
-
Language Reference
This reference is structured so that it can be read from top to bottom, if you like. Later sections use ideas and syntax previously introduced. Familiarity with JavaScript is assumed. In all of the following examples, the source CoffeeScript is provided on the left, and the direct compilation into JavaScript is on the right.
+
Language Reference
+
This reference is structured so that it can be read from top to bottom, if you like. Later sections use ideas and syntax previously introduced. Familiarity with JavaScript is assumed. In all of the following examples, the source CoffeeScript is provided on the left, and the direct compilation into JavaScript is on the right.
Many of the examples can be run (where it makes sense) by pressing the run button on the right, and can be loaded into the “Try CoffeeScript” console by pressing the load button on the left.
First, the basics: CoffeeScript uses significant whitespace to delimit blocks of code. You don’t need to use semicolons ; to terminate expressions, ending the line will do just as well (although semicolons can still be used to fit multiple expressions onto a single line). Instead of using curly braces { } to surround blocks of code in functions, if-statements, switch, and try/catch, use indentation.
You don’t need to use parentheses to invoke a function if you’re passing arguments. The implicit call wraps forward to the end of the line or block expression. console.log sys.inspect object → console.log(sys.inspect(object));
-
Functions
Functions are defined by an optional list of parameters in parentheses, an arrow, and the function body. The empty function looks like this: ->
+
Functions
+
Functions are defined by an optional list of parameters in parentheses, an arrow, and the function body. The empty function looks like this: ->
square = (x) -> x * x
cube = (x) -> square(x) * x
var cube, square;
@@ -962,7 +897,8 @@ fill = function(container, liquid) {
};
;alert(fill("cup"));">run: fill("cup")
-
Objects and Arrays
The CoffeeScript literals for objects and arrays look very similar to their JavaScript cousins. When each property is listed on its own line, the commas are optional. Objects may be created using indentation instead of explicit braces, similar to YAML.
+
Objects and Arrays
+
The CoffeeScript literals for objects and arrays look very similar to their JavaScript cousins. When each property is listed on its own line, the commas are optional. Objects may be created using indentation instead of explicit braces, similar to YAML.
song = ["do", "re", "mi", "fa", "so"]
singers = {Jagger: "Rock", Elvis: "Roll"}
@@ -1054,7 +990,8 @@ turtle = {
output = turtle.name + " wears an " + turtle.mask + " mask. Watch out for his " + turtle.weapon + "!";
load
-
Lexical Scoping and Variable Safety
The CoffeeScript compiler takes care to make sure that all of your variables are properly declared within lexical scope — you never need to write var yourself.
+
Lexical Scoping and Variable Safety
+
The CoffeeScript compiler takes care to make sure that all of your variables are properly declared within lexical scope — you never need to write var yourself.
If you’d like to create top-level variables for other scripts to use, attach them as properties on window; attach them as properties on the exports object in CommonJS; or use an export statement. If you’re targeting both CommonJS and the browser, the existential operator (covered below), gives you a reliable way to figure out where to add them: exports ? this
-
If, Else, Unless, and Conditional Assignment
If/else statements can be written without the use of parentheses and curly brackets. As with functions and other block expressions, multi-line conditionals are delimited by indentation. There’s also a handy postfix form, with the if or unless at the end.
+
If, Else, Unless, and Conditional Assignment
+
If/else statements can be written without the use of parentheses and curly brackets. As with functions and other block expressions, multi-line conditionals are delimited by indentation. There’s also a handy postfix form, with the if or unless at the end.
CoffeeScript can compile if statements into JavaScript expressions, using the ternary operator when possible, and closure wrapping otherwise. There is no explicit ternary statement in CoffeeScript — you simply use a regular if statement on a single line.
mood = greatlyImproved if singing
@@ -1115,7 +1053,8 @@ date = if friday then
date = friday ? sue : jill;
load
-
Splats…
The JavaScript arguments object is a useful way to work with functions that accept variable numbers of arguments. CoffeeScript provides splats ..., both for function definition as well as invocation, making variable numbers of arguments a little bit more palatable.
+
Splats…
+
The JavaScript arguments object is a useful way to work with functions that accept variable numbers of arguments. CoffeeScript provides splats ..., both for function definition as well as invocation, making variable numbers of arguments a little bit more palatable.
Most of the loops you’ll write in CoffeeScript will be comprehensions over arrays, objects, and ranges. Comprehensions replace (and compile into) for loops, with optional guard clauses and the value of the current array index. Unlike for loops, array comprehensions are expressions, and can be returned and assigned.
+
Loops and Comprehensions
+
Most of the loops you’ll write in CoffeeScript will be comprehensions over arrays, objects, and ranges. Comprehensions replace (and compile into) for loops, with optional guard clauses and the value of the current array index. Unlike for loops, array comprehensions are expressions, and can be returned and assigned.
Ranges can also be used to extract slices of arrays. With two dots (3..6), the range is inclusive (3, 4, 5, 6); with three dots (3...6), the range excludes the end (3, 4, 5). Slices indices have useful defaults. An omitted first index defaults to zero and an omitted second index defaults to the size of the array.
+
Array Slicing and Splicing with Ranges
+
Ranges can also be used to extract slices of arrays. With two dots (3..6), the range is inclusive (3, 4, 5, 6); with three dots (3...6), the range excludes the end (3, 4, 5). Slices indices have useful defaults. An omitted first index defaults to zero and an omitted second index defaults to the size of the array.
Note that JavaScript strings are immutable, and can’t be spliced.
-
Everything is an Expression (at least, as much as possible)
You might have noticed how even though we don’t add return statements to CoffeeScript functions, they nonetheless return their final value. The CoffeeScript compiler tries to make sure that all statements in the language can be used as expressions. Watch how the return gets pushed down into each possible branch of execution in the function below.
+
Everything is an Expression (at least, as much as possible)
+
You might have noticed how even though we don’t add return statements to CoffeeScript functions, they nonetheless return their final value. The CoffeeScript compiler tries to make sure that all statements in the language can be used as expressions. Watch how the return gets pushed down into each possible branch of execution in the function below.
There are a handful of statements in JavaScript that can’t be meaningfully converted into expressions, namely break, continue, and return. If you make use of them within a block of code, CoffeeScript won’t try to perform the conversion.
-
Operators and Aliases
Because the == operator frequently causes undesirable coercion, is intransitive, and has a different meaning than in other languages, CoffeeScript compiles == into ===, and != into !==. In addition, is compiles into ===, and isnt into !==.
+
Operators and Aliases
+
Because the == operator frequently causes undesirable coercion, is intransitive, and has a different meaning than in other languages, CoffeeScript compiles == into ===, and != into !==. In addition, is compiles into ===, and isnt into !==.
You can use not as an alias for !.
For logic, and compiles to &&, and or into ||.
Instead of a newline or semicolon, then can be used to separate conditions from expressions, in while, if/else, and switch/when statements.
@@ -1540,126 +1483,68 @@ modulo(-7, 5) ===
load
All together now:
-
-
-
-
+
+
-
CoffeeScript
-
JavaScript
-
-
+
+
-
is
-
===
-
-
-
isnt
-
!==
-
-
-
not
-
!
-
-
-
and
-
&&
-
-
-
or
-
||
-
-
-
true, yes, on
-
true
-
-
-
-
false, no, off
-
+
false, no, off
false
-
-
-
@, this
-
this
-
-
-
of
-
in
-
-
-
in
-
-
no JS equivalent
-
+
no JS equivalent
-
-
a ** b
-
Math.pow(a, b)
-
-
-
a // b
-
Math.floor(a / b)
-
-
-
a %% b
-
(a % b + b) % b
-
-
-
-
launch() if ignition ison
volume = 10if band isnt SpinalTap
@@ -1696,7 +1581,8 @@ winner = yesif pick <
print(inspect("My name is " + this.name));
load
-
The Existential Operator
It’s a little difficult to check for the existence of a variable in JavaScript. if (variable) … comes close, but fails for zero, the empty string, and false. CoffeeScript’s existential operator ? returns true unless a variable is null or undefined, which makes it analogous to Ruby’s nil?
+
The Existential Operator
+
It’s a little difficult to check for the existence of a variable in JavaScript. if (variable) … comes close, but fails for zero, the empty string, and false. CoffeeScript’s existential operator ? returns true unless a variable is null or undefined, which makes it analogous to Ruby’s nil?
It can also be used for safer conditional assignment than ||= provides, for cases where you may be handling numbers or strings.
JavaScript’s prototypal inheritance has always been a bit of a brain-bender, with a whole family tree of libraries that provide a cleaner syntax for classical inheritance on top of JavaScript’s prototypes: Base2, Prototype.js, JS.Class, etc. The libraries provide syntactic sugar, but the built-in inheritance would be completely usable if it weren’t for a couple of small exceptions: it’s awkward to call super (the prototype object’s implementation of the current function), and it’s awkward to correctly set the prototype chain.
+
Classes, Inheritance, and Super
+
JavaScript’s prototypal inheritance has always been a bit of a brain-bender, with a whole family tree of libraries that provide a cleaner syntax for classical inheritance on top of JavaScript’s prototypes: Base2, Prototype.js, JS.Class, etc. The libraries provide syntactic sugar, but the built-in inheritance would be completely usable if it weren’t for a couple of small exceptions: it’s awkward to call super (the prototype object’s implementation of the current function), and it’s awkward to correctly set the prototype chain.
Instead of repetitively attaching functions to a prototype, CoffeeScript provides a basic class structure that allows you to name your class, set the superclass, assign prototypal properties, and define the constructor, in a single assignable expression.
Constructor functions are named, to better support helpful stack traces. In the first class in the example below, this.constructor.name is "Animal".
Finally, class definitions are blocks of executable code, which make for interesting metaprogramming possibilities. Because in the context of a class definition, this is the class object itself (the constructor function), you can assign static properties by using
-@property: value, and call functions defined in parent classes: @attr 'title', type: 'text'
+@property: value, and call functions defined in parent classes: @attr 'title', type: 'text'
-
Destructuring Assignment
Just like JavaScript (since ES2015), CoffeeScript has destructuring assignment syntax. When you assign an array or object literal to a value, CoffeeScript breaks up and matches both sides against each other, assigning the values on the right to the variables on the left. In the simplest case, it can be used for parallel assignment:
+
Destructuring Assignment
+
Just like JavaScript (since ES2015), CoffeeScript has destructuring assignment syntax. When you assign an array or object literal to a value, CoffeeScript breaks up and matches both sides against each other, assigning the values on the right to the variables on the left. In the simplest case, it can be used for parallel assignment:
The above example also demonstrates that if properties are missing in the destructured object or array, you can, just like in JavaScript, provide defaults. The difference with JavaScript is that CoffeeScript, as always, treats both null and undefined the same.
-
Bound Functions, Generator Functions
In JavaScript, the this keyword is dynamically scoped to mean the object that the current function is attached to. If you pass a function as a callback or attach it to a different object, the original value of this will be lost. If you’re not familiar with this behavior, this Digital Web article gives a good overview of the quirks.
+
Bound Functions, Generator Functions
+
In JavaScript, the this keyword is dynamically scoped to mean the object that the current function is attached to. If you pass a function as a callback or attach it to a different object, the original value of this will be lost. If you’re not familiar with this behavior, this Digital Web article gives a good overview of the quirks.
The fat arrow => can be used to both define a function, and to bind it to the current value of this, right on the spot. This is helpful when using callback-based libraries like Prototype or jQuery, for creating iterator functions to pass to each, or event-handler functions to use with on. Functions created with the fat arrow are able to access properties of the this where they’re defined.
Hopefully, you’ll never need to use it, but if you ever need to intersperse snippets of JavaScript within your CoffeeScript, you can use backticks to pass it straight through.
+
Embedded JavaScript
+
Hopefully, you’ll never need to use it, but if you ever need to intersperse snippets of JavaScript within your CoffeeScript, you can use backticks to pass it straight through.
hi = `function() {
return [document.title, "Hello JavaScript"].join(": ");
}`
@@ -2206,7 +2096,8 @@ function time() {
;alert(time());">run: time()
-
Switch/When/Else
Switch statements in JavaScript are a bit awkward. You need to remember to break at the end of every case statement to avoid accidentally falling through to the default case. CoffeeScript prevents accidental fall-through, and can convert the switch into a returnable, assignable expression. The format is: switch condition, when clauses, else the default case.
+
Switch/When/Else
+
Switch statements in JavaScript are a bit awkward. You need to remember to break at the end of every case statement to avoid accidentally falling through to the default case. CoffeeScript prevents accidental fall-through, and can convert the switch into a returnable, assignable expression. The format is: switch condition, when clauses, else the default case.
As in Ruby, switch statements in CoffeeScript can take multiple values for each when clause. If any of the values match, the clause runs.
switch day
when"Mon"then go work
@@ -2270,7 +2161,8 @@ grade = (function(
load
-
Try/Catch/Finally
Try-expressions have the same semantics as try-statements in JavaScript, though in CoffeeScript, you may omit both the catch and finally parts. The catch part may also omit the error parameter if it is not needed.
+
Try/Catch/Finally
+
Try-expressions have the same semantics as try-statements in JavaScript, though in CoffeeScript, you may omit both the catch and finally parts. The catch part may also omit the error parameter if it is not needed.
String Interpolation, Block Strings, and Block Comments
Ruby-style string interpolation is included in CoffeeScript. Double-quoted strings allow for interpolated values, using #{ … }, and single-quoted strings are literal. You may even use interpolation in object keys.
+
String Interpolation, Block Strings, and Block Comments
+
Ruby-style string interpolation is included in CoffeeScript. Double-quoted strings allow for interpolated values, using #{ … }, and single-quoted strings are literal. You may even use interpolation in object keys.
author = "Wittgenstein"
quote = "A picture is a fact. -- #{ author }"
@@ -2365,7 +2259,8 @@ Released under the MIT License
load
-
Tagged Template Literals
CoffeeScript supports ES2015 tagged template literals, which enable customized string interpolation. If you immediately prefix a string with a function name (no space between the two), CoffeeScript will output this “function plus string” combination as an ES2015 tagged template literal, which will behave accordingly: the function is called, with the parameters being the input text and expression parts that make up the interpolated string. The function can then assemble these parts into an output string, providing custom string interpolation.
+
Tagged Template Literals
+
CoffeeScript supports ES2015 tagged template literals, which enable customized string interpolation. If you immediately prefix a string with a function name (no space between the two), CoffeeScript will output this “function plus string” combination as an ES2015 tagged template literal, which will behave accordingly: the function is called, with the parameters being the input text and expression parts that make up the interpolated string. The function can then assemble these parts into an output string, providing custom string interpolation.
Be aware that the CoffeeScript compiler is outputting ES2015 syntax for this feature, so your target JavaScript runtime(s) must support this syntax for your code to work; or you could use tools like Babel or Traceur Compiler to convert this ES2015 syntax into compatible JavaScript.
Similar to block strings and comments, CoffeeScript supports block regexes — extended regular expressions that ignore internal whitespace and can contain comments and interpolation. Modeled after Perl’s /x modifier, CoffeeScript’s block regexes are delimited by /// and go a long way towards making complex regular expressions readable. To quote from the CoffeeScript source:
+
Block Regular Expressions
+
Similar to block strings and comments, CoffeeScript supports block regexes — extended regular expressions that ignore internal whitespace and can contain comments and interpolation. Modeled after Perl’s /x modifier, CoffeeScript’s block regexes are delimited by /// and go a long way towards making complex regular expressions readable. To quote from the CoffeeScript source:
Note that the CoffeeScript compiler does not resolve modules; writing an import or export statement in CoffeeScript will produce an import or export statement in the resulting output. It is your responsibility attach another transpiler, such as Traceur Compiler, Babel or Rollup, to convert this ES2015 syntax into code that will work in your target runtimes.
+
load
Note that the CoffeeScript compiler does not resolve modules; writing an import or export statement in CoffeeScript will produce an import or export statement in the resulting output. It is your responsibility attach another transpiler, such as Traceur Compiler, Babel or Rollup, to convert this ES2015 syntax into code that will work in your target runtimes.
Also note that any file with an import or export statement will be output without a top-level function safety wrapper; in other words, importing or exporting modules will automatically trigger bare mode for that file. This is because per the ES2015 spec, import or export statements must occur at the topmost scope.
-
Cake, and Cakefiles
CoffeeScript includes a (very) simple build system similar to Make and Rake. Naturally, it’s called Cake, and is used for the tasks that build and test the CoffeeScript language itself. Tasks are defined in a file named Cakefile, and can be invoked by running cake [task] from within the directory. To print a list of all the tasks and options, just type cake.
+
Cake, and Cakefiles
+
CoffeeScript includes a (very) simple build system similar to Make and Rake. Naturally, it’s called Cake, and is used for the tasks that build and test the CoffeeScript language itself. Tasks are defined in a file named Cakefile, and can be invoked by running cake [task] from within the directory. To print a list of all the tasks and options, just type cake.
Task definitions are written in CoffeeScript, so you can put arbitrary code in your Cakefile. Define a task with a name, a long description, and the function to invoke when the task is run. If your task takes a command-line option, you can define the option with short and long flags, and it will be made available in the options object. Here’s a task that uses the Node.js API to rebuild CoffeeScript’s parser:
If you need to invoke one task before another — for example, running build before test, you can use the invoke function: invoke 'build'. Cake tasks are a minimal way to expose your CoffeeScript functions to the command line, so don’t expect any fanciness built-in. If you need dependencies, or async callbacks, it’s best to put them in your code itself — not the cake task.
+
load
If you need to invoke one task before another — for example, running build before test, you can use the invoke function: invoke 'build'. Cake tasks are a minimal way to expose your CoffeeScript functions to the command line, so don’t expect any fanciness built-in. If you need dependencies, or async callbacks, it’s best to put them in your code itself — not the cake task.
-
Source Maps
CoffeeScript 1.6.1 and above include support for generating source maps, a way to tell your JavaScript engine what part of your CoffeeScript program matches up with the code being evaluated. Browsers that support it can automatically use source maps to show your original source code in the debugger. To generate source maps alongside your JavaScript files, pass the --map or -m flag to the compiler.
+
Source Maps
+
CoffeeScript 1.6.1 and above include support for generating source maps, a way to tell your JavaScript engine what part of your CoffeeScript program matches up with the code being evaluated. Browsers that support it can automatically use source maps to show your original source code in the debugger. To generate source maps alongside your JavaScript files, pass the --map or -m flag to the compiler.
For a full introduction to source maps, how they work, and how to hook them up in your browser, read the HTML5 Tutorial.
-
"text/coffeescript" Script Tags
While it’s not recommended for serious use, CoffeeScripts may be included directly within the browser using <script type="text/coffeescript"> tags. The source includes a compressed and minified version of the compiler (Download current version here, 51k when gzipped) as v1/browser-compiler/coffee-script.js. Include this file on a page with inline CoffeeScript tags, and it will compile and evaluate them in order.
+
“text/coffeescript” Script Tags
+
While it’s not recommended for serious use, CoffeeScripts may be included directly within the browser using <script type="text/coffeescript"> tags. The source includes a compressed and minified version of the compiler (Download current version here, 51k when gzipped) as v1/browser-compiler/coffee-script.js. Include this file on a page with inline CoffeeScript tags, and it will compile and evaluate them in order.
In fact, the little bit of glue script that runs “Try CoffeeScript” above, as well as the jQuery for the menu, is implemented in just this way. View source and look at the bottom of the page to see the example. Including the script also gives you access to CoffeeScript.compile() so you can pop open Firebug and try compiling some strings.
The usual caveats about CoffeeScript apply — your inline scripts will run within a closure wrapper, so if you want to expose global variables or functions, attach them to the window object.
-
Books
There are a number of excellent resources to help you get started with CoffeeScript, some of which are freely available online.
+
Books
+
There are a number of excellent resources to help you get started with CoffeeScript, some of which are freely available online.
Smooth CoffeeScript is a reimagination of the excellent book Eloquent JavaScript, as if it had been written in CoffeeScript instead. Covers language features as well as the functional and object oriented programming styles. By E. Hoigaard.
@@ -2562,14 +2463,16 @@ task('build:parser', 'rebuild t
Meet CoffeeScript is a 75-minute long screencast by PeepCode. Highly memorable for its animations which demonstrate transforming CoffeeScript into the equivalent JS.
If you’re looking for less of a time commitment, RailsCasts’ CoffeeScript Basics should have you covered, hitting all of the important notes about CoffeeScript in 11 minutes.
Source Code
Use bin/coffee to test your changes, bin/cake test to run the test suite, bin/cake build to rebuild the full CoffeeScript compiler, and bin/cake build:except-parser to recompile much faster if you’re not editing grammar.coffee.
git checkout lib && bin/cake build:full is a good command to run when you’re working on the core language. It’ll refresh the lib folder (in case you broke something), build your altered compiler, use that to rebuild itself (a good sanity test) and then run all of the tests. If they pass, there’s a good chance you’ve made a successful change.
-
Browser Tests
-Run CoffeeScript’s test suite in your current browser.
-
CoffeeScript Issues
-Bug reports, feature proposals, and ideas for changes to the language belong here.
-
CoffeeScript Google Group
-If you’d like to ask a question, the mailing list is a good place to get help.
The FAQ
-Perhaps your CoffeeScript-related question has been asked before. Check the FAQ first.
-
JS2Coffee
-Is a very well done reverse JavaScript-to-CoffeeScript compiler. It’s not going to be perfect (infer what your JavaScript classes are, when you need bound functions, and so on…) — but it’s a great starting point for converting simple scripts.
-
High-Rez Logo
-The CoffeeScript logo is available in SVG for use in presentations.
+
+
Browser Tests
+Run CoffeeScript’s test suite in your current browser.
+
+
+
CoffeeScript Issues
+Bug reports, feature proposals, and ideas for changes to the language belong here.
+
+
+
CoffeeScript Google Group
+If you’d like to ask a question, the mailing list is a good place to get help.
The FAQ
+Perhaps your CoffeeScript-related question has been asked before. Check the FAQ first.
+
+
+
JS2Coffee
+Is a very well done reverse JavaScript-to-CoffeeScript compiler. It’s not going to be perfect (infer what your JavaScript classes are, when you need bound functions, and so on…) — but it’s a great starting point for converting simple scripts.
+
+
+
High-Rez Logo
+The CoffeeScript logo is available in SVG for use in presentations.
+
-
Web Chat (IRC)
Quick help and advice can usually be found in the CoffeeScript IRC room. Join #coffeescript on irc.freenode.net, or click the button below to open a webchat session on this page.
-
+
Web Chat (IRC)
+
Quick help and advice can usually be found in the CoffeeScript IRC room. Join #coffeescript on irc.freenode.net, or click the button below to open a webchat session on this page.
Better handling of default, from, as and * within import and export statements. You can now import or export a member named default and the compiler won’t interpret it as the default keyword.
+
Fixed a bug where invalid octal escape sequences weren’t throwing errors in the compiler.
+
+
1.12.4 —
@@ -2644,7 +2573,7 @@ The CoffeeScript logo is available in SVG for use in presentations.
You can now import a module member named default, e.g. import { default } from 'lib'. Though like in ES2015, you cannot import an entire module and name it default (so import default from 'lib' is not allowed).
+
You can now import a module member named default, e.g. import { default } from 'lib'. Though like in ES2015, you cannot import an entire module and name it default (so import default from 'lib' is not allowed).
Fix regression where from as a variable name was breaking for loop declarations. For the record, from is not a reserved word in CoffeeScript; you may use it for variable names. from behaves like a keyword within the context of import and export statements, and in the declaration of a for loop; though you should also be able to use variables named from in those contexts, and the compiler should be able to tell the difference.
@@ -2676,33 +2605,55 @@ The CoffeeScript logo is available in SVG for use in presentations.
1.11.0 —
Added the -M, --inline-map flag to the compiler, allowing you embed the source map directly into the output JavaScript, rather than as a separate file.
Added the -M, --inline-map flag to the compiler, allowing you embed the source map directly into the output JavaScript, rather than as a separate file.
+
+
+
A bunch of fixes for yield:
-
yield return can no longer mistakenly be used as an expression.
-
yield now mirrors return in that it can be used stand-alone as well as with expressions. Where you previously wrote yield undefined, you may now write simply yield. However, this means also inheriting the same syntax limitations that return has, so these examples no longer compile:
-
doubles = ->
+
+
yield return can no longer mistakenly be used as an expression.
+
+
+
yield now mirrors return in that it can be used stand-alone as well as with expressions. Where you previously wrote yield undefined, you may now write simply yield. However, this means also inheriting the same syntax limitations that return has, so these examples no longer compile:
+
doubles = ->
yield for i in [1..3]
i * 2
-six = ->
+six = ->
yield
- 2 * 3
-
The JavaScript output is a bit nicer, with unnecessary parentheses and spaces, double indentation and double semicolons around yield no longer present.
+ 2 * 3
+
+
+
+
The JavaScript output is a bit nicer, with unnecessary parentheses and spaces, double indentation and double semicolons around yield no longer present.
-
&&=, ||=, and= and or= no longer accidentally allow a space before the equals sign.
-
Improved several error messages.
-
Just like undefined compiles to void 0, NaN now compiles into 0/0 and Infinity into 2e308.
-
Bugfix for renamed destructured parameters with defaults. ({a: b = 1}) -> no longer crashes the compiler.
-
Improved the internal representation of a CoffeeScript program. This is only noticeable to tools that use CoffeeScript.tokens or CoffeeScript.nodes. Such tools need to update to take account for changed or added tokens and nodes.
-
Several minor bug fixes, including:
+
+
&&=, ||=, and= and or= no longer accidentally allow a space before the equals sign.
+
+
+
Improved several error messages.
+
+
+
Just like undefined compiles to void 0, NaN now compiles into 0/0 and Infinity into 2e308.
+
+
+
Bugfix for renamed destructured parameters with defaults. ({a: b = 1}) -> no longer crashes the compiler.
+
+
+
Improved the internal representation of a CoffeeScript program. This is only noticeable to tools that use CoffeeScript.tokens or CoffeeScript.nodes. Such tools need to update to take account for changed or added tokens and nodes.
+
+
+
Several minor bug fixes, including:
The caught error in catch blocks is no longer declared unnecessarily, and no longer mistakenly named undefined for catch-less try blocks.
Unassignable parameter destructuring no longer crashes the compiler.
Source maps are now used correctly for errors thrown from .coffee.md files.
-
coffee -e 'throw null' no longer crashes.
+
coffee -e 'throw null' no longer crashes.
The REPL no longer crashes when using .exit to exit it.
Invalid JavaScript is no longer output when lots of for loops are used in the same scope.
CoffeeScript now supports ES2015-style destructuring defaults.
-
(offsetHeight: height) -> no longer compiles. That syntax was accidental and partly broken. Use ({offsetHeight: height}) -> instead. Object destructuring always requires braces.
-
Several minor bug fixes, including:
+
+
CoffeeScript now supports ES2015-style destructuring defaults.
+
+
+
(offsetHeight: height) -> no longer compiles. That syntax was accidental and partly broken. Use ({offsetHeight: height}) -> instead. Object destructuring always requires braces.
+
+
+
Several minor bug fixes, including:
A bug where the REPL would sometimes report valid code as invalid, based on what you had typed earlier.
A problem with multiple JS contexts in the jest test framework.
@@ -2782,7 +2738,7 @@ six = ->
Fixed a slight formatting error in CoffeeScript’s source map-patched stack traces.
The %% operator now coerces its right operand only once.
It is now possible to require CoffeeScript files from Cakefiles without having to register the compiler first.
-
The CoffeeScript REPL is now exported and can be required using require 'coffee-script/repl'.
+
The CoffeeScript REPL is now exported and can be required using require 'coffee-script/repl'.
When requiring CoffeeScript files in Node you must now explicitly register the compiler. This can be done with require 'coffee-script/register' or CoffeeScript.register(). Also for configuration such as Mocha’s, use coffee-script/register.
+
When requiring CoffeeScript files in Node you must now explicitly register the compiler. This can be done with require 'coffee-script/register' or CoffeeScript.register(). Also for configuration such as Mocha’s, use coffee-script/register.
Improved error messages, source maps and stack traces. Source maps now use the updated //# syntax.
Leading . now closes all open calls, allowing for simpler chaining syntax.
@@ -2912,7 +2868,7 @@ six = ->
Ahh, whitespace. CoffeeScript’s compiled JS now tries to space things out and keep it readable, as you can see in the examples on this page.
You can now call super in class level methods in class bodies, and bound class methods now preserve their correct context.
JavaScript has always supported octal numbers 010 is 8, and hexadecimal numbers 0xf is 15, but CoffeeScript now also supports binary numbers: 0b10 is 2.
-
The CoffeeScript module has been nested under a subdirectory to make it easier to require individual components separately, without having to use npm. For example, after adding the CoffeeScript folder to your path: require('coffee-script/lexer')
+
The CoffeeScript module has been nested under a subdirectory to make it easier to require individual components separately, without having to use npm. For example, after adding the CoffeeScript folder to your path: require('coffee-script/lexer')
There’s a new “link” feature in Try CoffeeScript on this webpage. Use it to get a shareable permalink for your example script.
The coffee --watch feature now only works on Node.js 0.6.0 and higher, but now also works properly on Windows.
The official CoffeeScript extension is now .coffee instead of .cs, which properly belongs to C#). Due to popular demand, you can now also use = to assign. Unlike JavaScript, = can also be used within object literals, interchangeably with :. Made a grammatical fix for chained function calls like func(1)(2)(3)(4). Inheritance and super no longer use __proto__, so they should be IE-compatible now.
+
The official CoffeeScript extension is now .coffee instead of .cs, which properly belongs to C#. Due to popular demand, you can now also use = to assign. Unlike JavaScript, = can also be used within object literals, interchangeably with :. Made a grammatical fix for chained function calls like func(1)(2)(3)(4). Inheritance and super no longer use __proto__, so they should be IE-compatible now.
0.1.3
diff --git a/docs/v1/test.html b/docs/v1/test.html
index 280fcf95..4ff822ff 100644
--- a/docs/v1/test.html
+++ b/docs/v1/test.html
@@ -3882,6 +3882,13 @@ test "octal escapes", ->
/a\\0\\tb\\\\\\07c/
\ \ \ \ ^\^^
'''
+ assertErrorFormat '''
+ /a\\1\\tb\\\\\\07c/
+ ''', '''
+ [stdin]:1:10: error: octal escape sequences are not allowed \\07
+ /a\\1\\tb\\\\\\07c/
+ \ \ \ \ ^\^^
+ '''
assertErrorFormat '''
///a
#{b} \\01///
@@ -8310,7 +8317,7 @@ test "export an aliased member named default", ->
};"""
eq toJS(input), output
-test "export an imported member named default", ->
+test "import an imported member named default", ->
input = "import { default } from 'lib'"
output = """
import {
@@ -8318,7 +8325,7 @@ test "export an imported member named default", ->
} from 'lib';"""
eq toJS(input), output
-test "export an imported aliased member named default", ->
+test "import an imported aliased member named default", ->
input = "import { default as def } from 'lib'"
output = """
import {
@@ -8326,6 +8333,22 @@ test "export an imported aliased member named default", ->
} from 'lib';"""
eq toJS(input), output
+test "export an imported member named default", ->
+ input = "export { default } from 'lib'"
+ output = """
+ export {
+ default
+ } from 'lib';"""
+ eq toJS(input), output
+
+test "export an imported aliased member named default", ->
+ input = "export { default as def } from 'lib'"
+ output = """
+ export {
+ default as def
+ } from 'lib';"""
+ eq toJS(input), output
+
test "#4394: export shouldn't prevent variable declarations", ->
input = """
x = 1
@@ -8342,6 +8365,121 @@ test "#4394: export shouldn't prevent variable declarations", ->
"""
eq toJS(input), output
+test "#4451: `default` in an export statement is only treated as a keyword when it follows `export` or `as`", ->
+ input = "export default { default: 1 }"
+ output = """
+ export default {
+ "default": 1
+ };
+ """
+ eq toJS(input), output
+
+test "#4491: import- and export-specific lexing should stop after import/export statement", ->
+ input = """
+ import {
+ foo,
+ bar as baz
+ } from 'lib'
+
+ foo as
+ 3 * as 4
+ from 'foo'
+ """
+ output = """
+ import {
+ foo,
+ bar as baz
+ } from 'lib';
+
+ foo(as);
+
+ 3 * as(4);
+
+ from('foo');
+ """
+ eq toJS(input), output
+
+ input = """
+ import { foo, bar as baz } from 'lib'
+
+ foo as
+ 3 * as 4
+ from 'foo'
+ """
+ output = """
+ import {
+ foo,
+ bar as baz
+ } from 'lib';
+
+ foo(as);
+
+ 3 * as(4);
+
+ from('foo');
+ """
+ eq toJS(input), output
+
+ input = """
+ import * as lib from 'lib'
+
+ foo as
+ 3 * as 4
+ from 'foo'
+ """
+ output = """
+ import * as lib from 'lib';
+
+ foo(as);
+
+ 3 * as(4);
+
+ from('foo');
+ """
+ eq toJS(input), output
+
+ input = """
+ export {
+ foo,
+ bar
+ }
+
+ foo as
+ 3 * as 4
+ from 'foo'
+ """
+ output = """
+ export {
+ foo,
+ bar
+ };
+
+ foo(as);
+
+ 3 * as(4);
+
+ from('foo');
+ """
+ eq toJS(input), output
+
+ input = """
+ export * from 'lib'
+
+ foo as
+ 3 * as 4
+ from 'foo'
+ """
+ output = """
+ export * from 'lib';
+
+ foo(as);
+
+ 3 * as(4);
+
+ from('foo');
+ """
+ eq toJS(input), output
+