Compare commits

...

84 Commits

Author SHA1 Message Date
Geoffrey Booth
64b8dd486a 2.0.3 (#4795)
* Fix #4775: Remove no-longer-correct mention of the docs using text/coffeescript

* 2.0.3 changelog

* Update output for 2.0.3

* Bump date
2017-11-26 19:29:08 -08:00
Geoffrey Booth
7864acabc3 Fix #4790: Double-check that we're not creating a bound generator function, even if the yield got stuffed inside a compiler-generated IIFE (#4792) 2017-11-21 17:14:32 -08:00
zdenko
9812d28748 Fix #4787: Destructuring of objects within arrays can generate invalid JavaScript (#4791)
* Fix #4787

* simplify condition
2017-11-20 20:00:27 -08:00
zdenko
555c22af58 fix #4580 (#4793) 2017-11-20 09:15:19 -08:00
Geoffrey Booth
3f4b03bcff Fix #4763: Comments at beginning or end of REPL input shouldn't throw errors (#4764) 2017-11-19 11:37:08 -08:00
Geoffrey Booth
a706a64a6d Fix #4765: .map file should always have the same output base filename as the generated .js file (#4784) 2017-11-16 13:30:40 -08:00
Geoffrey Booth
637fe305a6 Fix #4774: export default followed by an object should always work, even if the object contains braces. default shouldn't suppress a newline, we should handle it in the grammar the same way returning an implicit object is handled (#4783) 2017-11-15 21:38:05 -08:00
Geoffrey Booth
bd824c73dd Fix #4780: Don't mutate the options object when compiling and transpiling, so that options are correct on subsequent iterations (#4785) 2017-11-14 08:13:22 -08:00
Geoffrey Booth
cbc695b831 2.0.2 (#4758)
* Give the notes about `super` and `this` their own section in the docs

* 2.0.2 changelog

* 2.0.2 release output

* Rewrite
2017-10-26 18:29:45 -07:00
Geoffrey Booth
f3375e798c Fix #4756: When moving comments from the children of an Existence, we need to search all its descendants, not just the immediate children (#4757) 2017-10-25 22:15:40 -07:00
Geoffrey Booth
e2308093e4 Fix #4752: Error on calling super with @params in a derived class constructor (#4754)
* Fix #4752: Error on calling super with @params in a derived class constructor

* Catch calls to super with not-top-level @params
2017-10-25 22:15:05 -07:00
Geoffrey Booth
0dc4755920 Fix #4747: Flow local variables (#4753)
* Fix #4706: Comments before a PARAM_START token stay before that token

* Simplify nodes

* Add function-in-function test

* Fix #4706: Comments after class name should go after the identifier that's after `class`, not the variable assigned to

* Fix #4706: Top-level identifiers with trailing comments get wrapped in parentheses (around the comment too) so that Flow doesn't interpret it as a JavaScript label

* Cleanup

* If the source has parentheses wrapping an identifier followed by a block comment, output those parentheses rather than optimizing them away; this is a requirement of Flow, to distinguish from JavaScript labels

* More tests for Flow comments

* For local variables with trailing inline herecomments, output the comments up in the variable declarations line for Flow compatibility
2017-10-19 06:56:59 -07:00
Geoffrey Booth
6faa7f2b35 Fix #4706: Flow generics (#4736)
* Fix #4706: Comments before a PARAM_START token stay before that token

* Simplify nodes

* Add function-in-function test

* Fix #4706: Comments after class name should go after the identifier that's after `class`, not the variable assigned to

* Fix #4706: Top-level identifiers with trailing comments get wrapped in parentheses (around the comment too) so that Flow doesn't interpret it as a JavaScript label

* Cleanup

* If the source has parentheses wrapping an identifier followed by a block comment, output those parentheses rather than optimizing them away; this is a requirement of Flow, to distinguish from JavaScript labels

* More tests for Flow comments
2017-10-18 17:22:02 -07:00
geebo
063c2d1f56 Fix import/export list bug with aliased keywords (#4744) 2017-10-12 11:47:12 -07:00
Chris Connelly
4d4e47bfb2 Fix #4724 (#4737)
The handling of hoisted nodes in class bodies was incorrect, as the node
was being unwrapped *before* checking if it was hoisted, meaning nodes
that should have been hoisted would be output normally.

This affected `PassthroughLiteral`s as they were wrapped in a `Value`.
2017-10-07 11:32:43 -07:00
Geoffrey Booth
22fb31e317 Transpile REPL (#4729)
* Fix #4725: apply transpile option to require’d .coffee files

* Use the current module’s options if it has any, before going searching up the tree

* Don’t mutate passed-in options object

* If the REPL is run with `--transpile`, turn transpilation on for both the current REPL input and any files imported by that input

* Use the command.coffee machinery for parsing arguments

* Fix test for Windows
2017-10-04 17:50:25 -07:00
Geoffrey Booth
a2037e799f Fix #4725: apply transpile option to require’d .coffee files (#4728)
* Fix #4725: apply transpile option to require’d .coffee files

* Use the current module’s options if it has any, before going searching up the tree

* Don’t mutate passed-in options object
2017-10-04 17:49:59 -07:00
Geoffrey Booth
694e69d872 Fix #4727: Tests failing in Windows (#4731)
* ?

* ??

* Revert the coffee.EXE approach

* Explicitly define the PATH to include only the folders we need

* Get spawnSync working in Windows

* Simplify test to be cross-platform
2017-10-02 22:19:32 -07:00
Matthew Ryan
bb2871fdde Allow applying 'get'/'set' property to a bracketless object (#4730) 2017-10-02 11:10:43 -07:00
Geoffrey Booth
08e00331dd Fix #3440: --stdio and --map don’t make sense to use together (#4721) 2017-09-27 00:02:30 -07:00
Geoffrey Booth
0b0a9ef2c4 2.0.1 (#4719)
* 2.0.1 changelog

* Version bump to 2.0.1
2017-09-26 20:16:16 -07:00
Geoffrey Booth
9df1457c55 Fix #4703, 4713: Transpile fixes (#4717)
* Show an appropriate error if the user tries to use --transpile via the CLI and babel-core isn’t installed

* Update documentation around global/local

* Fix #4713: Use Babel’s built-in `filename` option to let Babel search for its options, rather than us doing so

* Improve transpilation docs

* Colons are good

* Docs cleanup

* Rewrite transpilation docs

* Better identifier for compiled scripts that didn’t come from files; better resolving of paths
2017-09-26 09:20:13 -07:00
James Kyle
22f92f23ae Add example of comment include type annotation (#4705)
* Add example of comment include type annotation

* build website
2017-09-25 18:25:55 -07:00
Easy Bills
cd516b954f Update ASCII logo (#4718)
Attempt to reproduce the official logo in ASCII :)
2017-09-25 12:13:30 -07:00
Chris Connelly
27eff5ca77 Fix #4464: backticked expressions in class body (#4712)
* Fix #4464: backticked expressions in class body should be left in the body, not hoisted

* Fix #4464: backticked expressions in class body should be left in the body, not hoisted

* Simplify fix for #4464

This uses more of the existing machinery for moving class body
expressions into the initializer.

* Clarify the purpose of Class::addInitializerExpression

* Further clarify the purpose of Class::addInitializerExpression

* Add reference to class fields; format
 comment wrapping

* Reapply 1d3af8c432, that got lost because of rebase/force-push shenanigans

* Updated output
2017-09-20 19:11:05 -07:00
Geoffrey Booth
5cbd25f5d4 Docs fixes (#4707)
* Mobile Safari needs the code to be >= 16px

* Buttons that just run the code shouldn’t have a label, since in all the other examples the label signifies the command to be run

* Use Bootstrap’s breakpoints

* Use Bootstrap’s styling for the <code> element, to avoid misaligned baseline

* Updated output

* Fix #4704: use replaceState, so that back/forward only happen for user clicks on links; opening and closing Try CoffeeScript doesn’t count as a new history entry, and closing it retrieves the previous URL

* Fix #4702: Some changelog entries are more equal than others

* Updated output

* Eliminate the 1px jitter when initializing code editors

* On first time opening Try CoffeeScript, use just #try as the hash

* Update output

* Increase general body line spacing

* Code styling per Jeremy

* Don’t let the main text column grow unreasonably wide

* Give list items some modest bottom margin (and use ems whenever possible)

* Updated output
2017-09-20 13:10:48 -07:00
Jeremy Ashkenas
eb127923a7 Merge pull request #4708 from jz5/master
Fix link to logo
2017-09-19 11:37:06 -04:00
jz5
42da56deb1 Fix link to logo 2017-09-19 16:47:32 +09:00
Jeremy Ashkenas
81260bff7d boom 2017-09-18 18:23:27 -04:00
Jeremy Ashkenas
35f784bcdf Fixes #4703 — Don't depend on Babel in package.json 2017-09-18 17:14:01 -04:00
Jeremy Ashkenas
c17b6b8863 fix the code popping 2017-09-18 16:06:11 -04:00
Jeremy Ashkenas
1965996933 slightly less cramped code 2017-09-18 14:06:45 -04:00
Jeremy Ashkenas
a67dfae985 Tweaking font sizes. 2017-09-18 14:04:04 -04:00
Jeremy Ashkenas
1cb733989c Removing slightly defensive and slightly incorrect 'why coffeescript' section 2017-09-18 13:56:02 -04:00
Geoffrey Booth
a2a2e769c3 Update docs output for 2.0.0 2017-09-18 08:31:07 -07:00
Geoffrey Booth
19231dbcad 2.0.0 (#4701)
* Bump version to 2.0.0; bump dependencies versions

* Make v2 docs the primary docs; jettison the v1 docs’ source: whenever the v1 docs need to be rebuild in the future, that can be done on the `1` branch and copied over; simplify folder tree

* Updated v1 docs that reflect that v2 is out and have updated paths to reflect that the v2 docs are now the primary docs, and the v1 docs only live under /v1/

* Add Google Analytics; track navigation, editing code and running code

* 2.0.0 changelog

* Fix link to root docs

* No more @next; installing local copy should be --save-dev

* Analytics on the browser-based tests page should prove fascinating . . .

* Update annotated source

* Add note to changelog clarifying scope
2017-09-18 08:19:19 -07:00
Geoffrey Booth
aecc115c79 Fix #4686: if a CSX interpolation contains comments, not just inner CSX (JSX) tags, it needs to be wrapped in braces (#4689) 2017-09-16 12:03:33 -07:00
Geoffrey Booth
4c41831474 CoffeeScript 2 announcement (#4695)
* CoffeeScript 2 announcement, first draft

* Lydell's notes

* Jeremy’s notes; Rollup is not a transpiler

* Revise “unsupported features” section

* Fix links, invalid HTML

* Announcing CoffeeScript 2 HTML page

* Link to the announcement

* Add some references

* Fix anchors

* Better example
2017-09-16 11:57:18 -07:00
Geoffrey Booth
659f1b3c4c Update transpilation docs (#4700) 2017-09-16 09:32:48 -07:00
Geoffrey Booth
f51c1a150b Option to transpile with Babel (#4697)
* Upgrade Babeli (now babel-minify) which fixes the bug that was forcing us to run Babel twice for transpilation

* Add --transpile option (WIP)

* Node API always compiles a string, so it doesn’t need the option to pass a path to an options file, it can always just pass an object to `transpile`; get `transpile` working with `eval`

* Not allowing argument to `--transpile` so don’t need to cover so many cases

* Don’t need to worry about `sourceMaps` option to pass to Babel, `inputSourceMap` overrides it

* Rewrite Webpack test to use Node API

* Make the compiler safe again for browsers and Webpack/Browserify

* Node version of CoffeeScript.compile passes reference to Babel if transpile is requested

* Test Node API for transpile option

* Test for merged source maps

* Test for Node API error message

* Only stop searching for Babel options if a package.json has a truthy "babel" key

* Update docs
2017-09-15 06:58:18 -07:00
Geoffrey Booth
970f31c292 Fix #4342: Always output sourcesContent property as part of source map, whether inline map or written-to-disk map (#4698) 2017-09-11 22:38:48 -07:00
Geoffrey Booth
d172405244 First pass at using Travis CI (#4690) 2017-09-08 22:01:11 -07:00
Geoffrey Booth
44ebfdb764 Merge branch '2'
# Conflicts:
#	lib/coffee-script/nodes.js
#	src/nodes.coffee
#	test/arrays.coffee
2017-09-07 21:08:04 -07:00
Julian Rosse
1b8f1af287 [CS2] Fix destructuring bugs #4673 and #4657 (#4683)
* destructuring fixes [Fixes #4673] [Fixes #4657]

* test for destructured @prop

* Add another test to cover #4657 cases

* don't declare actual params
2017-09-07 10:06:35 -07:00
Geoffrey Booth
e7073bc5d9 Update CS2 docs per #4688 2017-09-07 08:05:04 -07:00
Geoffrey Booth
63d3b699d7 [CS2] Fix CS2 docs mobile issues, improve performance (#4688)
* Get rid of offcanvas slide-in; fix sidebar

* We need to transpile docs.coffee, since Safari 9 throws an error on it and that’s too new a browser not to support; but this should also speed things up

* Fix some tabs

* Fix scrollbar

* Use Highlight.js to format placeholder code (during compilation, not rendering) before CodeMirror loads; match Highlight.js styles to CodeMirror styles as best we can

* Improve hash management

* Initialize CodeMirror on demand, on mouseover a particular code example, rather than all examples on startup

* Replace highlight.js with Prism for placeholder syntax highlighting

* Scratch Prism, use CodeMirror itself to do Node-based syntax highlighting, so that on CodeMirror initialization there’s no flash from mismatched highlighting

* Update packages; there’s a new version of Jison! (doesn’t change much)

* Fix mobile issues: use SVG play button icon, to avoid iOS blue square play button; make the code editor text 16px size explicit, to avoid unwanted mobile zoom; make the ‘code play’ buttons work even if the code examples are in placeholder (non-editable) mode, in case a user hasn’t moused over/tapped them

* Update docs output

* Whoops, CodeMirror is only a devDependency
2017-09-07 08:01:12 -07:00
Geoffrey Booth
458440e57b 2.0.0-beta5 docs 2017-09-02 12:55:56 -07:00
Geoffrey Booth
df9d4a2343 [CS2] 2.0.0-beta5 (#4682)
* Upgrade docs to Bootstrap 4 beta, including refactoring styles; upgrade docs jQuery and CodeMirror

* Better style the docs for mobile, including Try CoffeeScript

* Fix #4642, erroneous statement about named functions

* Update packages

* 2.0.0-beta5
2017-09-02 12:48:38 -07:00
Geoffrey Booth
9e043bbae7 [CS2] Fix async tests (#4680)
* Get `coffee` command working again in Node 6, by converting the ‘await’ wrapper in the REPL to use a Promise instead of the ‘await’ keyword; add tests for REPL ‘await’ wrapper, including test to skip async tests if the runtime doesn’t support them

* Fix async tests: now if a test function is a Promise (which an `await` function is), we add it to an array of async test functions and wait for them all to resolve before finishing the test run, so that if any async tests fail we see those failures in the output

* Code review

* Unnecessary

* Let's support Node 6+ if we can

* Simplify the returned promise

* Simplify async check
2017-09-01 12:26:47 -07:00
Geoffrey Booth
671486989f [CS2] Don’t require async/await support to run coffee (#4679)
* Get `coffee` command working again in Node 6, by converting the ‘await’ wrapper in the REPL to use a Promise instead of the ‘await’ keyword; add tests for REPL ‘await’ wrapper, including test to skip async tests if the runtime doesn’t support them

* Code review

* Let's support Node 6+ if we can
2017-09-01 12:19:15 -07:00
Geoffrey Booth
4a4f752204 Fix #3098: Suppressed newline should be unsuppressed by semicolon (#4669) 2017-09-01 07:09:36 -07:00
Julian Rosse
b20e52da99 [CS2] use _extends utility instead of Object.assign() for object spreads (#4675)
* _extends utility instead of Object.assign()

* eqJS test for _extends

* Test that a user-defined function named `_extends` doesn’t conflict with our utility function

* IE8 polyfill note in docs
2017-09-01 07:09:16 -07:00
Chris Connelly
5525b2ba01 Merge pull request #4652 from GeoffreyBooth/bug-fix-4651
[CS2] Fix #4651: object spread destructuring bug
2017-09-01 13:10:49 +01:00
Geoffrey Booth
fe5ff39ca2 [CS2] Fix v3 source map (#4671)
* Per discussion in #3075: if `sourceFiles` is unspecified, but `filename` is, use `filename`; output null instead of an empty string for `sources` or `sourceRoot`

* Update source map tests to reflect that now we return null instead of empty strings; check generated sources array

* Update source map documentation; still leave more obscure options undocumented

* Follow the TypeScript compiler’s example regarding v3SourceMap, but output empty strings instead of made-up filenames

* Have `sources` default to ‘<anonymous>’
2017-09-01 01:06:45 -07:00
Geoffrey Booth
906bedf93a Fix #1768: Ignore space after :: (#4670) 2017-08-30 22:43:17 -07:00
Julian Rosse
6f961a20dd [CS2] Refine #4666: add parens to chained do IIFE with params (#4672)
* add parens to chained do iife [Fixes #3736]

* remove debug code

* fixes from code review

* handle iife with params

* add test w/ destructured param from code review
2017-08-30 22:42:50 -07:00
Julian Rosse
e54b8a1009 [CS2] add parens to chained do IIFE (#4666)
* add parens to chained do iife [Fixes #3736]

* remove debug code

* fixes from code review
2017-08-29 14:17:56 -07:00
Geoffrey Booth
d7d69a4a18 Fix #4576: Allow accessing a property of a function literal (like .call) via chaining syntax (#4665) 2017-08-28 13:16:22 -07:00
Geoffrey Booth
eb38dba5d6 Only unescape newlines for CSX; updated compiled output 2017-08-27 21:37:21 -07:00
zdenko
6cea181ff1 [CS1] fix #4260 and #1349: splat error with soak properties or expressions (#4643)
* fix splat error with soak properties or expressions

* Add test based on #4260

* Add test based on #1349

* remove 'void 0' replacement; add Splat::compileNode
2017-08-27 16:25:13 -07:00
Geoffrey Booth
9ff82fe17b Fix #4589: Unquote all interpolated strings, not just CSX ones, so that quotation marks are not unnecessarily escaped in backtick-delimited strings/template literals (#4660) 2017-08-27 15:16:31 -07:00
zdenko
5713b7eb6c [CS2] Fix #4260 and #1349: Splat error with soak properties or expressions (#4644)
* fix splat error with soak properties or expressions

* Add test based on #4260

* Add test based on #1349

* tests for the leading splat variant

* test for spaced prefix ...

* fixed 'if' statement in parens

* fixed replacing 'void 0' with '[]'

* remove 'void 0' replacement; add Splat::compileNode

* Use LEVEL_OP; follow style better
2017-08-27 15:11:14 -07:00
Geoffrey Booth
7c627f9dfd [CS2] Fix #3709, #3789: ‘throw’ an ‘if’, ‘for’, ‘switch’, ‘while’ (#4664)
* Fix #3709: throwing an if, for, switch or while should throw the returned value of the statement/loop

* Fix #3789: don’t throw a throw (unless it’s in a closure)

* LEVEL_LIST works better than a list of node types
2017-08-25 11:11:10 -07:00
Geoffrey Booth
c81e2d4767 Fix #4575: Check for the previous token’s existence before comparing against it (#4663) 2017-08-24 00:05:26 -07:00
Geoffrey Booth
3dd458267b [CS2] Fix #2870: Allow specifying output filename (#4661)
* Fix #2870: If --output ends with a filename, and the input is a file and not a path, save as the desired filename

* If an output path ends in a slash, force saving into an output folder even if that folder name would contain a period (e.g. /scripts.js/); if output filename is only periods, treat it as a path

* Restrict exceptions
2017-08-24 00:03:57 -07:00
Geoffrey Booth
892c4699dd Fix #4578: Never look back past the start of the token stream (#4662) 2017-08-24 00:02:57 -07:00
Geoffrey Booth
40c351135a [CS2] Fix #4629: interpolations (whether in strings or CSX tags) with only comments (#4659)
* Fix #4629: interpolations (whether in strings or CSX tags) that contain nothing but comments should not be optimized out

* Template literals need an expression inside their interpolations, so if we only have a comment to put in there, toss in an empty string as well
2017-08-23 23:34:59 -07:00
Geoffrey Booth
a3b08e1bef [CS2] Fix #4209: --require for filenames that are invalid identifiers (#4658)
* When using --require, check that the variable we’re creating from the required file/module is a valid identifier name before assigning to it; fixes #4209

* We don’t need no stinkin’ regex
2017-08-23 06:51:14 -07:00
Geoffrey Booth
44a27c6204 Fix #4558: Stack trace line numbers for scripts that compile CoffeeScript (#4645)
* Don't throw an error in the console when loading a try: URL

* Handle the possibility of compiling multiple scripts with the same filename, or multiple anonymous scripts

* Fix #4558: Much more robust caching of sources and source maps, more careful lookup of source maps especially for CoffeeScript code compiled within a Coffee script (. . . within a Coffee script, etc.)

* Reimplement `cake release` to just use the shell to avoid the issues plaguing that command (something to do with module caching perhaps)
2017-08-23 06:50:46 -07:00
Zdenko Vujasinovic
c212e6e9ab refactor 2017-08-22 21:19:56 +02:00
Zdenko Vujasinovic
5a709ed4a8 improve variable declaration 2017-08-22 10:48:12 +02:00
Zdenko Vujasinovic
2491d3286d fix assign in nested properties
fix assign in nested properties
2017-08-21 21:16:28 +02:00
Julian Rosse
1a6477adec resolve merge conflicts 2017-08-21 10:39:46 -04:00
Julian Rosse
2149c3561b ensure Value; breaking test for {a={b...}} = c 2017-08-21 10:34:33 -04:00
Zdenko Vujasinovic
232041db2a fixed issue with nested properties 2017-08-21 16:22:17 +02:00
Ben Drechsel
4623bf5bba Docs: Define functions used in loop examples (#4653)
* Cherrypick changes from messy branch

* Reorder function defs
2017-08-18 17:15:52 -07:00
Zdenko Vujasinovic
2664c2c108 small fix 2017-08-18 08:51:11 +02:00
Zdenko Vujasinovic
f9367bacf1 fix object spread destructuring bug: #4651 2017-08-18 04:06:37 +02:00
zdenko
aef54aeaf7 [CS2] Fix #4631: Expansion that becomes rest parameter causes runtime error (#4634)
* expansion-rest bug fix

* tests; improved implicit call recognition with dots on the left in the `rewriter`

* whitespace cleanup

* more tests
2017-08-17 13:13:52 -07:00
Chris Connelly
eff160eeb7 Merge pull request #4640 from GeoffreyBooth/generated-variables-in-function-parameters
[CS2] Fix #4413: Generated variables in function parameters
2017-08-15 14:19:21 +01:00
Geoffrey Booth
911c21f7be Update test to prove that there's no collision in generated variables 2017-08-14 03:06:38 +00:00
Geoffrey Booth
52795587ec If compiling a function parameter creates any generated variables (e.g. ref), shift the declarations for those variables into the parent scope; fixes #4413 2017-08-14 03:00:01 +00:00
Geoffrey Booth
3a6ffa6a85 Clean up function parameter compilation to get name for scope 2017-08-14 02:42:01 +00:00
Geoffrey Booth
e3c2c0397a 2.0.0-beta4 docs 2017-08-03 18:18:31 -07:00
132 changed files with 9454 additions and 4565 deletions

3
.babelrc Normal file
View File

@@ -0,0 +1,3 @@
{
"presets": ["env"]
}

18
.travis.yml Normal file
View File

@@ -0,0 +1,18 @@
language: node_js
node_js:
- 6
- 8
cache:
directories:
- node_modules
script:
- node ./bin/cake build:except-parser
- node ./bin/cake build:parser
- node ./bin/cake build:full
- node ./bin/cake build:browser
- node ./bin/cake test
- node ./bin/cake test:browser
- node ./bin/cake test:integrations

162
Cakefile
View File

@@ -66,6 +66,20 @@ build = (callback) ->
buildParser()
buildExceptParser callback
transpile = (code) ->
babel = require 'babel-core'
presets = []
# Exclude the `modules` plugin in order to not break the `}(this));`
# at the end of the `build:browser` code block.
presets.push ['env', {modules: no}] unless process.env.TRANSFORM is 'false'
presets.push 'minify' unless process.env.MINIFY is 'false'
babelOptions =
compact: process.env.MINIFY isnt 'false'
presets: presets
sourceType: 'script'
{ code } = babel.transform code, babelOptions unless presets.length is 0
code
testBuiltCode = (watch = no) ->
csPath = './lib/coffeescript'
csDir = path.dirname require.resolve csPath
@@ -79,7 +93,7 @@ testBuiltCode = (watch = no) ->
buildAndTest = (includingParser = yes, harmony = no) ->
process.stdout.write '\x1Bc' # Clear terminal screen.
execSync 'git checkout lib/*', stdio: [0,1,2] # Reset the generated compiler.
execSync 'git checkout lib/*', stdio: 'inherit' # Reset the generated compiler.
buildArgs = ['bin/cake']
buildArgs.push if includingParser then 'build' else 'build:except-parser'
@@ -141,24 +155,7 @@ task 'build:browser', 'merge the built scripts into a single file for use in a b
}
}(this));
"""
babel = require 'babel-core'
presets = []
# Exclude the `modules` plugin in order to not break the `}(this));`
# at the end of the above code block.
presets.push ['env', {modules: no}] unless process.env.TRANSFORM is 'false'
babelOptions =
presets: presets
sourceType: 'script'
{ code } = babel.transform code, babelOptions unless presets.length is 0
# Running Babel twice due to https://github.com/babel/babili/issues/614.
# Once that issue is fixed, move the `babili` preset back up into the
# `presets` array and run Babel once with both presets together.
presets = if process.env.MINIFY is 'false' then [] else ['babili']
babelOptions =
compact: process.env.MINIFY isnt 'false'
presets: presets
sourceType: 'script'
{ code } = babel.transform code, babelOptions unless presets.length is 0
code = transpile code
outputFolder = "docs/v#{majorVersion}/browser-compiler"
fs.mkdirSync outputFolder unless fs.existsSync outputFolder
fs.writeFileSync "#{outputFolder}/coffeescript.js", header + '\n' + code
@@ -177,11 +174,11 @@ task 'build:watch:harmony', 'watch and continually rebuild the CoffeeScript comp
buildDocs = (watch = no) ->
# Constants
indexFile = 'documentation/index.html'
versionedSourceFolder = "documentation/v#{majorVersion}"
indexFile = 'documentation/site/index.html'
siteSourceFolder = "documentation/site"
sectionsSourceFolder = 'documentation/sections'
examplesSourceFolder = 'documentation/examples'
outputFolder = "docs/v#{majorVersion}"
outputFolder = "docs/v#{majorVersion}"
# Helpers
releaseHeader = (date, version, prevVersion) ->
@@ -199,7 +196,7 @@ buildDocs = (watch = no) ->
</h2>
"""
codeFor = require "./documentation/v#{majorVersion}/code.coffee"
codeFor = require "./documentation/site/code.coffee"
htmlFor = ->
hljs = require 'highlight.js'
@@ -236,9 +233,17 @@ buildDocs = (watch = no) ->
codeFor: codeFor()
releaseHeader: releaseHeader
includeScript = ->
(file) ->
file = "#{siteSourceFolder}/#{file}" unless '/' in file
code = fs.readFileSync file, 'utf-8'
code = CoffeeScript.compile code
code = transpile code
code
include = ->
(file) ->
file = "#{versionedSourceFolder}/#{file}" if file.indexOf('/') is -1
file = "#{siteSourceFolder}/#{file}" unless '/' in file
output = fs.readFileSync file, 'utf-8'
if /\.html$/.test(file)
render = _.template output
@@ -249,6 +254,7 @@ buildDocs = (watch = no) ->
htmlFor: htmlFor()
codeFor: codeFor()
include: include()
includeScript: includeScript()
output
# Task
@@ -263,7 +269,7 @@ buildDocs = (watch = no) ->
catch exception
if watch
for target in [indexFile, versionedSourceFolder, examplesSourceFolder, sectionsSourceFolder]
for target in [indexFile, siteSourceFolder, examplesSourceFolder, sectionsSourceFolder]
fs.watch target, interval: 200, renderIndex
log 'watching...', green
@@ -276,9 +282,9 @@ task 'doc:site:watch', 'watch and continually rebuild the documentation for the
buildDocTests = (watch = no) ->
# Constants
testFile = 'documentation/test.html'
testFile = 'documentation/site/test.html'
testsSourceFolder = 'test'
outputFolder = "docs/v#{majorVersion}"
outputFolder = "docs/v#{majorVersion}"
# Included in test.html
testHelpers = fs.readFileSync('test/support/helpers.coffee', 'utf-8').replace /exports\./g, '@'
@@ -341,11 +347,15 @@ task 'doc:source:watch', 'watch and continually rebuild the annotated source doc
task 'release', 'build and test the CoffeeScript source, and build the documentation', ->
invoke 'build:full'
invoke 'build:browser:full'
invoke 'doc:site'
invoke 'doc:test'
invoke 'doc:source'
execSync '''
cake build:full
cake build:browser
cake test:browser
cake test:integrations
cake doc:site
cake doc:test
cake doc:source''', stdio: 'inherit'
task 'bench', 'quick benchmark of compilation time', ->
{Rewriter} = require './lib/coffeescript/rewriter'
@@ -372,7 +382,6 @@ task 'bench', 'quick benchmark of compilation time', ->
# Run the CoffeeScript test suite.
runTests = (CoffeeScript) ->
CoffeeScript.register() unless global.testingBrowser
startTime = Date.now()
# These are attached to `global` so that theyre accessible from within
# `test/async.coffee`, which has an async-capable version of
@@ -392,18 +401,35 @@ runTests = (CoffeeScript) ->
global.yellow = yellow
global.reset = reset
asyncTests = []
onFail = (description, fn, err) ->
failures.push
filename: global.currentFile
error: err
description: description
source: fn.toString() if fn.toString?
# Our test helper function for delimiting different test cases.
global.test = (description, fn) ->
try
fn.test = {description, currentFile}
fn.call(fn)
++passedTests
catch e
failures.push
filename: currentFile
error: e
description: description if description?
source: fn.toString() if fn.toString?
result = fn.call(fn)
if result instanceof Promise # An async test.
asyncTests.push result
result.then ->
passedTests++
.catch (err) ->
onFail description, fn, err
else
passedTests++
catch err
onFail description, fn, err
global.supportsAsync = try
new Function('async () => {}')()
yes
catch
no
helpers.extend global, require './test/support/helpers'
@@ -424,7 +450,10 @@ runTests = (CoffeeScript) ->
# Run every test in the `test` folder, recording failures.
files = fs.readdirSync 'test'
unless global.supportsAsync # Except for async tests, if async isnt supported.
files = files.filter (filename) -> filename isnt 'async.coffee'
startTime = Date.now()
for file in files when helpers.isCoffee file
literate = helpers.isLiterate file
currentFile = filename = path.join 'test', file
@@ -433,12 +462,13 @@ runTests = (CoffeeScript) ->
CoffeeScript.run code.toString(), {filename, literate}
catch error
failures.push {filename, error}
return !failures.length
Promise.all(asyncTests).then ->
Promise.reject() if failures.length isnt 0
task 'test', 'run the CoffeeScript language test suite', ->
testResults = runTests CoffeeScript
process.exit 1 unless testResults
runTests(CoffeeScript).catch -> process.exit 1
task 'test:browser', 'run the test suite against the merged browser script', ->
@@ -446,8 +476,8 @@ task 'test:browser', 'run the test suite against the merged browser script', ->
result = {}
global.testingBrowser = yes
(-> eval source).call result
testResults = runTests result.CoffeeScript
process.exit 1 unless testResults
runTests(CoffeeScript).catch -> process.exit 1
task 'test:integrations', 'test the module integrated with other libraries and environments', ->
# Tools like Webpack and Browserify generate builds intended for a browser
@@ -457,20 +487,28 @@ task 'test:integrations', 'test the module integrated with other libraries and e
# Node modules are required as part of the compiler (as opposed to the tests)
# and that therefore the compiler will run in a browser environment.
tmpdir = os.tmpdir()
try
buildLog = execSync "./node_modules/webpack/bin/webpack.js
--entry=./
--output-library=CoffeeScript
--output-library-target=commonjs2
--output-path=#{tmpdir}
--output-filename=coffeescript.js"
catch exception
console.error buildLog.toString()
throw exception
webpack = require 'webpack'
webpack {
entry: './'
output:
path: tmpdir
filename: 'coffeescript.js'
library: 'CoffeeScript'
libraryTarget: 'commonjs2'
}, (err, stats) ->
if err or stats.hasErrors()
if err
console.error err.stack or err
console.error err.details if err.details
if stats.hasErrors()
console.error error for error in stats.compilation.errors
if stats.hasWarnings()
console.warn warning for warning in stats.compilation.warnings
process.exit 1
builtCompiler = path.join tmpdir, 'coffeescript.js'
CoffeeScript = require builtCompiler
global.testingBrowser = yes
testResults = runTests CoffeeScript
fs.unlinkSync builtCompiler
process.exit 1 unless testResults
builtCompiler = path.join tmpdir, 'coffeescript.js'
CoffeeScript = require builtCompiler
global.testingBrowser = yes
testResults = runTests CoffeeScript
fs.unlinkSync builtCompiler
process.exit 1 unless testResults

View File

@@ -1,22 +1,27 @@
{
} } {
{ { } }
} }{ {
{ }{ } } _____ __ __
{ }{ }{ { } / ____| / _|/ _|
.- { { } { }} -. | | ___ | |_| |_ ___ ___
( { } { } { } } ) | | / _ \| _| _/ _ \/ _ \
|`-..________ ..-'| | |___| (_) | | | || __/ __/
| | \_____\___/|_| |_| \___|\___|
| ;--.
| (__ \ _____ _ _
| | ) ) / ____| (_) | |
| |/ / | (___ ___ _ __ _ _ __ | |_
| ( / \___ \ / __| '__| | '_ \| __|
| |/ ____) | (__| | | | |_) | |_
| | |_____/ \___|_| |_| .__/ \__|
`-.._________..-' | |
|_|
@@@@@@@ @@@@ @@@@@
{ @@@@@@@@@@ @@@ @@@
} } { @@@@ @@ @@@ @@@
{ { } } @@@@ @@@@@@@ @@@ @@@ @@@@@@ @@@@@@
} }{ { @@@@ @@@ @@ @@@@@ @@@@@@ @@@ @@ @@@@ @@
{ }{ } } @@@@ @@@@ @@ @@@ @@@ @@@ @@@ @@@ @@@
{ }{ }{ { } @@@@ @@@@ @@ @@@ @@@ @@@@@@@@ @@@@@@@@
{ { } { } { } } @@@@@ @@@@ @@ @@@ @@@ @@@ @@@
{ } { } { } @@@@@@@@@@ @@@@@@@@ @@@ @@@ @@@@@@@@ @@@@@@@@
@@@@@@ { } { } @@@@@@@ @@@@@ @@@ @@@ @@@@@ @@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@ @@@
@@ @@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@ @@@ @@@
@@ @@@@@@@@@@@@@@@@@@@@@@@@ @@@@ @@ @@@ @@@@
@@@ @@@@@@@@@@@@@@@@@@@@@ @@@@ @@@ @@ @@@@
@@@ @@@@@@@@@@@@@@@@@@ @@@@@ @@@@@ @@ @@ @@@ @@@@@@@ @@@@@
@@@ @@@@@@@@@@@@@@@@ @@@@@ @@@ @@@ @@@@@@@@ @@@@ @@@@ @@@@@@@
@@@@@@@@@@@@@@ @@@@@ @@@ @@@@ @@@@ @@@ @@@ @@@
@@@@@ @@@@ @@@@ @@@@ @@@@ @@@@ @@@@ @@@@
@@@ @@@@ @@@ @@@@ @@@@ @@@ @@@@ @@@@
@@@ @@@@ @@@@ @@@@ @@@@ @@@@ @@@@ @@@@
@@@@@@@@@ @@@@@@ @@@@ @@@@ @@@@@@@@@ @@@@
@@@ @@@@
@@@
@@@
CoffeeScript is a little language that compiles into JavaScript.

1
docs/annotated-source Symbolic link
View File

@@ -0,0 +1 @@
v2/annotated-source

View File

@@ -0,0 +1 @@
v2/announcing-coffeescript-2

1
docs/browser-compiler Symbolic link
View File

@@ -0,0 +1 @@
v2/browser-compiler

View File

@@ -1 +1 @@
v1/index.html
v2/index.html

View File

@@ -1,5 +1,6 @@
{
"name": "",
"name": "CoffeeScript",
"description": "Unfancy JavaScript",
"icons": [
{
"src": "\/android-chrome-192x192.png",

1
docs/test.html Symbolic link
View File

@@ -0,0 +1 @@
v2/test.html

View File

@@ -594,18 +594,18 @@ pre .xml .cdata {
Annotated Source
</div>
<div class="contents menu">
<a href="/v1/annotated-source/grammar.html">Grammar Rules — src/grammar</a>
<a href="/v1/annotated-source/lexer.html">Lexing Tokens — src/lexer</a>
<a href="/v1/annotated-source/rewriter.html">The Rewriter — src/rewriter</a>
<a href="/v1/annotated-source/nodes.html">The Syntax Tree — src/nodes</a>
<a href="/v1/annotated-source/scope.html">Lexical Scope — src/scope</a>
<a href="/v1/annotated-source/helpers.html">Helpers &amp; Utility Functions — src/helpers</a>
<a href="/v1/annotated-source/coffee-script.html">The CoffeeScript Module — src/coffee-script</a>
<a href="/v1/annotated-source/cake.html">Cake &amp; Cakefiles — src/cake</a>
<a href="/v1/annotated-source/command.html">“coffee” Command-Line Utility — src/command</a>
<a href="/v1/annotated-source/optparse.html">Option Parsing — src/optparse</a>
<a href="/v1/annotated-source/repl.html">Interactive REPL — src/repl</a>
<a href="/v1/annotated-source/sourcemap.html">Source Maps — src/sourcemap</a>
<a href="annotated-source/grammar.html">Grammar Rules — src/grammar</a>
<a href="annotated-source/lexer.html">Lexing Tokens — src/lexer</a>
<a href="annotated-source/rewriter.html">The Rewriter — src/rewriter</a>
<a href="annotated-source/nodes.html">The Syntax Tree — src/nodes</a>
<a href="annotated-source/scope.html">Lexical Scope — src/scope</a>
<a href="annotated-source/helpers.html">Helpers &amp; Utility Functions — src/helpers</a>
<a href="annotated-source/coffee-script.html">The CoffeeScript Module — src/coffee-script</a>
<a href="annotated-source/cake.html">Cake &amp; Cakefiles — src/cake</a>
<a href="annotated-source/command.html">“coffee” Command-Line Utility — src/command</a>
<a href="annotated-source/optparse.html">Option Parsing — src/optparse</a>
<a href="annotated-source/repl.html">Interactive REPL — src/repl</a>
<a href="annotated-source/sourcemap.html">Source Maps — src/sourcemap</a>
</div>
</div>
</div>
@@ -615,10 +615,10 @@ pre .xml .cdata {
<p><strong>CoffeeScript is a little language that compiles into JavaScript.</strong> Underneath that awkward Java-esque patina, JavaScript has always had a gorgeous heart. CoffeeScript is an attempt to expose the good parts of JavaScript in a simple way.</p>
<p>The golden rule of CoffeeScript is: <em>“Its just JavaScript”</em>. The code compiles one-to-one into the equivalent JS, and there is no interpretation at runtime. You can use any existing JavaScript library seamlessly from CoffeeScript (and vice-versa). The compiled output is readable, pretty-printed, and tends to run as fast or faster than the equivalent handwritten JavaScript.</p>
<p>The CoffeeScript compiler goes to great lengths to generate output JavaScript that runs in every JavaScript runtime, but there are exceptions. Use <a href="#generator-functions">generator functions</a>, <a href="#generator-iteration"><code>for…from</code></a>, or <a href="#tagged-template-literals">tagged template literals</a> only if you know that your <a href="http://kangax.github.io/compat-table/es6/">target runtimes can support them</a>. If you use <a href="#modules">modules</a>, you will need to <a href="#modules-note">use an additional tool to resolve them</a>.</p>
<p><strong>Latest Version:</strong> <a href="https://github.com/jashkenas/coffeescript/tarball/1.12.7">1.12.7</a></p>
<p><strong>Latest 1.x Version:</strong> <a href="https://github.com/jashkenas/coffeescript/tarball/1.12.7">1.12.7</a></p>
<blockquote class="uneditable-code-block"><pre><code class="language-bash">npm install -g coffeescript
</code></pre>
</blockquote><p><strong>CoffeeScript 2 is coming!</strong> It adds support for <a href="/v2/#classes">ES2015 classes</a>, <a href="/v2/#fat-arrow"><code>async</code>/<code>await</code></a>, <a href="/v2/#jsx">JSX</a>, <span class="nowrap"><a href="/v2/#splats">object rest/spread syntax</a></span>, and JavaScript generated using ES2015+ syntax. <a href="/v2/">Learn more</a>.</p>
</blockquote><p><strong>Upgrade to CoffeeScript 2!</strong> It adds support for <a href="/#classes">ES2015 classes</a>, <a href="/#async-functions"><code>async</code>/<code>await</code></a>, <a href="/#jsx">JSX</a>, <span class="nowrap"><a href="/#splats">object rest/spread syntax</a></span>, and <a href="/#coffeescript-2">JavaScript generated using modern syntax</a>. <a href="/announcing-coffeescript-2/">Learn more</a>.</p>
<h2>Overview</h2>
<p><em>CoffeeScript on the left, compiled JavaScript output on the right.</em></p>
@@ -741,7 +741,7 @@ cubes = (function() {
;alert(cubes);">run: cubes</div><br class='clear' /></div>
<span class="bookmark" id="installation"></span>
<h2>Installation</h2>
<p>The command-line version of <code>coffee</code> is available as a <a href="https://nodejs.org/">Node.js</a> utility. The <a href="/v1/browser-compiler/coffee-script.js">core compiler</a> however, does not depend on Node, and can be run in any JavaScript environment, or in the browser (see <a href="#try">Try CoffeeScript</a>).</p>
<p>The command-line version of <code>coffee</code> is available as a <a href="https://nodejs.org/">Node.js</a> utility. The <a href="browser-compiler/coffee-script.js">core compiler</a> however, does not depend on Node, and can be run in any JavaScript environment, or in the browser (see <a href="#try">Try CoffeeScript</a>).</p>
<p>To install, first make sure you have a working copy of the latest stable version of <a href="https://nodejs.org/">Node.js</a>. You can then install CoffeeScript globally with <a href="https://www.npmjs.com/">npm</a>:</p>
<blockquote class="uneditable-code-block"><pre><code class="language-bash">npm install --global coffeescript
</code></pre>
@@ -2441,7 +2441,7 @@ task(<span class="string">'build:parser'</span>, <span class="string">'rebuild t
dir = options.output || <span class="string">'lib'</span>;
<span class="keyword">return</span> fs.writeFile(dir + <span class="string">"/parser.js"</span>, code);
});
</code></pre><script>window.example1 = "fs = require 'fs'\n\noption '-o', '--output [DIR]', 'directory for compiled code'\n\ntask 'build:parser', 'rebuild the Jison parser', (options) ->\n require 'jison'\n code = require('./lib/grammar').parser.generate()\n dir = options.output or 'lib'\n fs.writeFile \"#{dir}/parser.js\", code\n"</script><div class='minibutton load' onclick='javascript: loadConsole(example1);'>load</div><br class='clear' /></div><p>If you need to invoke one task before another — for example, running <code>build</code> before <code>test</code>, you can use the <code>invoke</code> function: <code>invoke 'build'</code>. Cake tasks are a minimal way to expose your CoffeeScript functions to the command line, so <a href="/v1/annotated-source/cake.html">dont expect any fanciness built-in</a>. If you need dependencies, or async callbacks, its best to put them in your code itself — not the cake task.</p>
</code></pre><script>window.example1 = "fs = require 'fs'\n\noption '-o', '--output [DIR]', 'directory for compiled code'\n\ntask 'build:parser', 'rebuild the Jison parser', (options) ->\n require 'jison'\n code = require('./lib/grammar').parser.generate()\n dir = options.output or 'lib'\n fs.writeFile \"#{dir}/parser.js\", code\n"</script><div class='minibutton load' onclick='javascript: loadConsole(example1);'>load</div><br class='clear' /></div><p>If you need to invoke one task before another — for example, running <code>build</code> before <code>test</code>, you can use the <code>invoke</code> function: <code>invoke 'build'</code>. Cake tasks are a minimal way to expose your CoffeeScript functions to the command line, so <a href="annotated-source/cake.html">dont expect any fanciness built-in</a>. If you need dependencies, or async callbacks, its best to put them in your code itself — not the cake task.</p>
<span class="bookmark" id="source-maps"></span>
<h2>Source Maps</h2>
@@ -2450,7 +2450,7 @@ task(<span class="string">'build:parser'</span>, <span class="string">'rebuild t
<span class="bookmark" id="scripts"></span>
<h2>“text/coffeescript” Script Tags</h2>
<p>While its not recommended for serious use, CoffeeScripts may be included directly within the browser using <code>&lt;script type=&quot;text/coffeescript&quot;&gt;</code> tags. The source includes a compressed and minified version of the compiler (<a href="/v1/browser-compiler/coffee-script.js">Download current version here, 51k when gzipped</a>) as <code>v1/browser-compiler/coffee-script.js</code>. Include this file on a page with inline CoffeeScript tags, and it will compile and evaluate them in order.</p>
<p>While its not recommended for serious use, CoffeeScripts may be included directly within the browser using <code>&lt;script type=&quot;text/coffeescript&quot;&gt;</code> tags. The source includes a compressed and minified version of the compiler (<a href="browser-compiler/coffee-script.js">Download current version here, 51k when gzipped</a>) as <code>docs/v1/browser-compiler/coffee-script.js</code>. Include this file on a page with inline CoffeeScript tags, and it will compile and evaluate them in order.</p>
<p>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 <code>CoffeeScript.compile()</code> so you can pop open Firebug and try compiling some strings.</p>
<p>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 <code>window</code> object.</p>
@@ -2501,7 +2501,7 @@ Use <code>bin/coffee</code> to test your changes,<br>
<p><code>git checkout lib &amp;&amp; bin/cake build:full</code> is a good command to run when youre working on the core language. Itll refresh the <code>lib</code> 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, theres a good chance youve made a successful change.</p>
</li>
<li>
<p><a href="/v1/test.html">Browser Tests</a><br>
<p><a href="test.html">Browser Tests</a><br>
Run CoffeeScripts test suite in your current browser.</p>
</li>
<li>
@@ -2592,7 +2592,7 @@ The CoffeeScript logo is available in SVG for use in presentations.</p>
<li>The browser compiler can once again be built unminified via <code>MINIFY=false cake build:browser</code>.</li>
<li>The error-prone patched version of <code>Error.prepareStackTrace</code> has been removed.</li>
<li>Command completion in the REPL (pressing tab to get suggestions) has been fixed for Node 6.9.1+.</li>
<li>The <a href="/v1/test.html">browser-based tests</a> now include all the tests as the Node-based version.</li>
<li>The <a href="test.html">browser-based tests</a> now include all the tests as the Node-based version.</li>
</ul>
<div class="anchor" id="1.12.1"></div>
<h2 class="header">
@@ -2611,7 +2611,7 @@ The CoffeeScript logo is available in SVG for use in presentations.</p>
<li>CoffeeScript now provides a <a href="#generator-iteration"><code>for…from</code></a> syntax for outputting ES2015 <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of"><code>for…of</code></a>. (Sorry they couldnt match, but we came up with <code>for…of</code> first for something else.) This allows iterating over generators or any other iterable object. Note that using <code>for…from</code> in your code makes you responsible for ensuring that either your runtime supports <code>for…of</code> or that you transpile the output JavaScript further to a version your target runtime(s) support.</li>
<li>Triple backticks (<code>```</code>) allow the creation of embedded JavaScript blocks where escaping single backticks is not required, which should improve interoperability with ES2015 template literals and with Markdown.</li>
<li>Within single-backtick embedded JavaScript, backticks can now be escaped via <code>\`</code>.</li>
<li>The browser tests now run in the browser again, and are accessible <a href="/v1/test.html">here</a> if you would like to test your browser.</li>
<li>The browser tests now run in the browser again, and are accessible <a href="test.html">here</a> if you would like to test your browser.</li>
<li>CoffeeScript-only keywords in ES2015 <code>import</code>s and <code>export</code>s are now ignored.</li>
<li>The compiler now throws an error on trying to export an anonymous class.</li>
<li>Bugfixes related to tokens and location data, for better source maps and improved compatibility with downstream tools.</li>
@@ -3016,7 +3016,7 @@ used to parse as <code>result = (i for i in list)</code> by default … it now p
<a href="https://github.com/jashkenas/coffeescript/compare/0.5.1...0.5.2">0.5.2</a>
<span class="timestamp"> &mdash; <time datetime="2010-02-25">February 25, 2010</time></span>
</h2><p>Added a compressed version of the compiler for inclusion in web pages as
<code>/v1/browser-compiler/coffee-script.js</code>. Itll automatically run any script tags with type <code>text/coffeescript</code> for you. Added a <code>--stdio</code> option to the <code>coffee</code> command, for piped-in compiles.</p>
<code>browser-compiler/coffee-script.js</code>. Itll automatically run any script tags with type <code>text/coffeescript</code> for you. Added a <code>--stdio</code> option to the <code>coffee</code> command, for piped-in compiles.</p>
<div class="anchor" id="0.5.1"></div>
<h2 class="header">
<a href="https://github.com/jashkenas/coffeescript/compare/0.5.0...0.5.1">0.5.1</a>
@@ -3222,7 +3222,7 @@ compileSource()
</script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script src="v1/browser-compiler/coffee-script.js"></script>
<script src="browser-compiler/coffee-script.js"></script>
</body>
</html>

View File

@@ -159,7 +159,7 @@ evaluated from <code>lib/coffeescript</code>.</p>
<div class="content"><div class='highlight'><pre>exports.VERSION = packageJson.version
exports.FILE_EXTENSIONS = [<span class="hljs-string">'.coffee'</span>, <span class="hljs-string">'.litcoffee'</span>, <span class="hljs-string">'.coffee.md'</span>]</pre></div></div>
exports.FILE_EXTENSIONS = FILE_EXTENSIONS = [<span class="hljs-string">'.coffee'</span>, <span class="hljs-string">'.litcoffee'</span>, <span class="hljs-string">'.coffee.md'</span>]</pre></div></div>
</li>
@@ -252,7 +252,7 @@ didnt create a source map (faster) but something went wrong and we need
a stack trace. Assuming that most of the time, code isnt throwing
exceptions, its probably more efficient to compile twice only when we
need a stack trace, rather than always generating a source map even when
its not likely to be used. Save in form of <code>filename</code>: <code>(source)</code></p>
its not likely to be used. Save in form of <code>filename</code>: [<code>(source)</code>]</p>
</div>
@@ -267,7 +267,7 @@ its not likely to be used. Save in form of <code>filename</code>: <code>(sour
<div class="pilwrap ">
<a class="pilcrow" href="#section-9">&#182;</a>
</div>
<p>Also save source maps if generated, in form of <code>filename</code>: <code>(source map)</code>.</p>
<p>Also save source maps if generated, in form of <code>(source)</code>: [<code>(source map)</code>].</p>
</div>
@@ -293,9 +293,7 @@ doing programmatic lookups.</p>
</div>
<div class="content"><div class='highlight'><pre>exports.compile = compile = withPrettyErrors (code, options) -&gt;
{merge, extend} = helpers
options = extend {}, options</pre></div></div>
<div class="content"><div class='highlight'><pre>exports.compile = compile = withPrettyErrors (code, options = {}) -&gt;</pre></div></div>
</li>
@@ -306,6 +304,21 @@ doing programmatic lookups.</p>
<div class="pilwrap ">
<a class="pilcrow" href="#section-11">&#182;</a>
</div>
<p>Clone <code>options</code>, to avoid mutating the <code>options</code> object passed in.</p>
</div>
<div class="content"><div class='highlight'><pre> options = Object.assign {}, options</pre></div></div>
</li>
<li id="section-12">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-12">&#182;</a>
</div>
<p>Always generate a source map if no filename is passed in, since without a
a filename we have no way to retrieve this source later in the event that
we need to recompile it to get a source map for <code>prepareStackTrace</code>.</p>
@@ -317,7 +330,8 @@ we need to recompile it to get a source map for <code>prepareStackTrace</code>.<
checkShebangLine filename, code
sources[filename] = code
sources[filename] ?= []
sources[filename].push code
map = <span class="hljs-keyword">new</span> SourceMap <span class="hljs-keyword">if</span> generateSourceMap
tokens = lexer.tokenize code, options</pre></div></div>
@@ -325,11 +339,11 @@ we need to recompile it to get a source map for <code>prepareStackTrace</code>.<
</li>
<li id="section-12">
<li id="section-13">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-12">&#182;</a>
<a class="pilcrow" href="#section-13">&#182;</a>
</div>
<p>Pass a list of referenced variables, so that generated variables wont get
the same name.</p>
@@ -343,11 +357,11 @@ the same name.</p>
</li>
<li id="section-13">
<li id="section-14">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-13">&#182;</a>
<a class="pilcrow" href="#section-14">&#182;</a>
</div>
<p>Check for import or export; if found, force bare mode.</p>
@@ -371,11 +385,11 @@ the same name.</p>
</li>
<li id="section-14">
<li id="section-15">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-14">&#182;</a>
<a class="pilcrow" href="#section-15">&#182;</a>
</div>
<p>Update the sourcemap with data from each fragment.</p>
@@ -386,11 +400,11 @@ the same name.</p>
</li>
<li id="section-15">
<li id="section-16">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-15">&#182;</a>
<a class="pilcrow" href="#section-16">&#182;</a>
</div>
<p>Do not include empty, whitespace, or semicolon-only fragments.</p>
@@ -411,11 +425,11 @@ the same name.</p>
</li>
<li id="section-16">
<li id="section-17">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-16">&#182;</a>
<a class="pilcrow" href="#section-17">&#182;</a>
</div>
<p>Copy the code from each fragment into the final JavaScript.</p>
@@ -428,8 +442,69 @@ the same name.</p>
js = <span class="hljs-string">"// <span class="hljs-subst">#{header}</span>\n<span class="hljs-subst">#{js}</span>"</span>
<span class="hljs-keyword">if</span> generateSourceMap
v3SourceMap = map.generate(options, code)
sourceMaps[filename] = map
v3SourceMap = map.generate options, code
sourceMaps[filename] ?= []
sourceMaps[filename].push map
<span class="hljs-keyword">if</span> options.transpile
<span class="hljs-keyword">if</span> <span class="hljs-keyword">typeof</span> options.transpile <span class="hljs-keyword">isnt</span> <span class="hljs-string">'object'</span></pre></div></div>
</li>
<li id="section-18">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-18">&#182;</a>
</div>
<p>This only happens if run via the Node API and <code>transpile</code> is set to
something other than an object.</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> Error <span class="hljs-string">'The transpile option must be given an object with options to pass to Babel'</span></pre></div></div>
</li>
<li id="section-19">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-19">&#182;</a>
</div>
<p>Get the reference to Babel that we have been passed if this compiler
is run via the CLI or Node API.</p>
</div>
<div class="content"><div class='highlight'><pre> transpiler = options.transpile.transpile
<span class="hljs-keyword">delete</span> options.transpile.transpile
transpilerOptions = Object.assign {}, options.transpile</pre></div></div>
</li>
<li id="section-20">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-20">&#182;</a>
</div>
<p>See <a href="https://github.com/babel/babel/issues/827#issuecomment-77573107">https://github.com/babel/babel/issues/827#issuecomment-77573107</a>:
Babel can take a v3 source map object as input in <code>inputSourceMap</code>
and it will return an <em>updated</em> v3 source map object in its output.</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> v3SourceMap <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> transpilerOptions.inputSourceMap?
transpilerOptions.inputSourceMap = v3SourceMap
transpilerOutput = transpiler js, transpilerOptions
js = transpilerOutput.code
<span class="hljs-keyword">if</span> v3SourceMap <span class="hljs-keyword">and</span> transpilerOutput.map
v3SourceMap = transpilerOutput.map
<span class="hljs-keyword">if</span> options.inlineMap
encoded = base64encode JSON.stringify v3SourceMap
@@ -449,11 +524,11 @@ the same name.</p>
</li>
<li id="section-17">
<li id="section-21">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-17">&#182;</a>
<a class="pilcrow" href="#section-21">&#182;</a>
</div>
<p>Tokenize a string of CoffeeScript code, and return the array of tokens.</p>
@@ -465,11 +540,11 @@ the same name.</p>
</li>
<li id="section-18">
<li id="section-22">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-18">&#182;</a>
<a class="pilcrow" href="#section-22">&#182;</a>
</div>
<p>Parse a string of CoffeeScript code or an array of lexed tokens, and
return the AST. You can then compile it by calling <code>.compile()</code> on the root,
@@ -486,11 +561,11 @@ or traverse it by using <code>.traverseChildren()</code> with a callback.</p>
</li>
<li id="section-19">
<li id="section-23">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-19">&#182;</a>
<a class="pilcrow" href="#section-23">&#182;</a>
</div>
<p>This file used to export these methods; leave stubs that throw warnings
instead. These methods have been moved into <code>index.coffee</code> to provide
@@ -506,11 +581,11 @@ environment.</p>
</li>
<li id="section-20">
<li id="section-24">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-20">&#182;</a>
<a class="pilcrow" href="#section-24">&#182;</a>
</div>
<p>Instantiate a Lexer for our use here.</p>
@@ -521,11 +596,11 @@ environment.</p>
</li>
<li id="section-21">
<li id="section-25">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-21">&#182;</a>
<a class="pilcrow" href="#section-25">&#182;</a>
</div>
<p>The real Lexer produces a generic stream of tokens. This object provides a
thin wrapper around it, compatible with the Jison API. We can then pass it
@@ -551,11 +626,11 @@ directly as a “Jison lexer”.</p>
</li>
<li id="section-22">
<li id="section-26">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-22">&#182;</a>
<a class="pilcrow" href="#section-26">&#182;</a>
</div>
<p>Make all the AST nodes visible to the parser.</p>
@@ -566,11 +641,11 @@ directly as a “Jison lexer”.</p>
</li>
<li id="section-23">
<li id="section-27">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-23">&#182;</a>
<a class="pilcrow" href="#section-27">&#182;</a>
</div>
<p>Override Jisons default error handling function.</p>
@@ -581,11 +656,11 @@ directly as a “Jison lexer”.</p>
</li>
<li id="section-24">
<li id="section-28">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-24">&#182;</a>
<a class="pilcrow" href="#section-28">&#182;</a>
</div>
<p>Disregard Jisons message, it contains redundant line number information.
Disregard the token, we take its value directly from the lexer in case
@@ -609,11 +684,11 @@ the error is caused by a generated token which might refer to its origin.</p>
</li>
<li id="section-25">
<li id="section-29">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-25">&#182;</a>
<a class="pilcrow" href="#section-29">&#182;</a>
</div>
<p>The second argument has a <code>loc</code> property, which should have the location
data for this token. Unfortunately, Jison seems to send an outdated <code>loc</code>
@@ -627,11 +702,11 @@ from the lexer.</p>
</li>
<li id="section-26">
<li id="section-30">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-26">&#182;</a>
<a class="pilcrow" href="#section-30">&#182;</a>
</div>
<p>Based on <a href="http://v8.googlecode.com/svn/branches/bleeding_edge/src/messages.js">http://v8.googlecode.com/svn/branches/bleeding_edge/src/messages.js</a>
Modified to handle sourceMap</p>
@@ -659,11 +734,11 @@ Modified to handle sourceMap</p>
</li>
<li id="section-27">
<li id="section-31">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-27">&#182;</a>
<a class="pilcrow" href="#section-31">&#182;</a>
</div>
<p>Check for a sourceMap position</p>
@@ -701,29 +776,87 @@ Modified to handle sourceMap</p>
<span class="hljs-keyword">else</span>
fileLocation
<span class="hljs-function">
<span class="hljs-title">getSourceMap</span> = <span class="hljs-params">(filename)</span> -&gt;</span>
<span class="hljs-keyword">if</span> sourceMaps[filename]?
sourceMaps[filename]</pre></div></div>
<span class="hljs-title">getSourceMap</span> = <span class="hljs-params">(filename, line, column)</span> -&gt;</span></pre></div></div>
</li>
<li id="section-28">
<li id="section-32">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-28">&#182;</a>
<a class="pilcrow" href="#section-32">&#182;</a>
</div>
<p>CoffeeScript compiled in a browser may get compiled with <code>options.filename</code>
of <code>&lt;anonymous&gt;</code>, but the browser may request the stack trace with the
filename of the script file.</p>
<p>Skip files that we didnt compile, like Node system files that appear in
the stack trace, as they never have source maps.</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> sourceMaps[<span class="hljs-string">'&lt;anonymous&gt;'</span>]?
sourceMaps[<span class="hljs-string">'&lt;anonymous&gt;'</span>]
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> sources[filename]?
answer = compile sources[filename],
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span> <span class="hljs-keyword">unless</span> filename <span class="hljs-keyword">is</span> <span class="hljs-string">'&lt;anonymous&gt;'</span> <span class="hljs-keyword">or</span> filename.slice(filename.lastIndexOf(<span class="hljs-string">'.'</span>)) <span class="hljs-keyword">in</span> FILE_EXTENSIONS
<span class="hljs-keyword">if</span> filename <span class="hljs-keyword">isnt</span> <span class="hljs-string">'&lt;anonymous&gt;'</span> <span class="hljs-keyword">and</span> sourceMaps[filename]?
<span class="hljs-keyword">return</span> sourceMaps[filename][sourceMaps[filename].length - <span class="hljs-number">1</span>]</pre></div></div>
</li>
<li id="section-33">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-33">&#182;</a>
</div>
<p>CoffeeScript compiled in a browser or via <code>CoffeeScript.compile</code> or <code>.run</code>
may get compiled with <code>options.filename</code> thats missing, which becomes
<code>&lt;anonymous&gt;</code>; but the runtime might request the stack trace with the
filename of the script file. See if we have a source map cached under
<code>&lt;anonymous&gt;</code> that matches the error.</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> sourceMaps[<span class="hljs-string">'&lt;anonymous&gt;'</span>]?</pre></div></div>
</li>
<li id="section-34">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-34">&#182;</a>
</div>
<p>Work backwards from the most recent anonymous source maps, until we find
one that works. This isnt foolproof; there is a chance that multiple
source maps will have line/column pairs that match. But we have no other
way to match them. <code>frame.getFunction().toString()</code> doesnt always work,
and its not foolproof either.</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">for</span> map <span class="hljs-keyword">in</span> sourceMaps[<span class="hljs-string">'&lt;anonymous&gt;'</span>] <span class="hljs-keyword">by</span> <span class="hljs-number">-1</span>
sourceLocation = map.sourceLocation [line - <span class="hljs-number">1</span>, column - <span class="hljs-number">1</span>]
<span class="hljs-keyword">return</span> map <span class="hljs-keyword">if</span> sourceLocation?[<span class="hljs-number">0</span>]? <span class="hljs-keyword">and</span> sourceLocation[<span class="hljs-number">1</span>]?</pre></div></div>
</li>
<li id="section-35">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-35">&#182;</a>
</div>
<p>If all else fails, recompile this source to get a source map. We need the
previous section (for <code>&lt;anonymous&gt;</code>) despite this option, because after it
gets compiled we will still need to look it up from
<code>sourceMaps[&#39;&lt;anonymous&gt;&#39;]</code> in order to find and return it. Thats why we
start searching from the end in the previous block, because most of the
time the source map we want is the last one.</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> sources[filename]?
answer = compile sources[filename][sources[filename].length - <span class="hljs-number">1</span>],
filename: filename
sourceMap: <span class="hljs-literal">yes</span>
literate: helpers.isLiterate filename
@@ -734,11 +867,11 @@ filename of the script file.</p>
</li>
<li id="section-29">
<li id="section-36">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-29">&#182;</a>
<a class="pilcrow" href="#section-36">&#182;</a>
</div>
<p>Based on <a href="http://goo.gl/ZTx1p">michaelficarra/CoffeeScriptRedux</a>
NodeJS / V8 have no support for transforming positions in stack traces using
@@ -749,7 +882,7 @@ positions.</p>
<div class="content"><div class='highlight'><pre>Error.prepareStackTrace = <span class="hljs-function"><span class="hljs-params">(err, stack)</span> -&gt;</span>
<span class="hljs-function"> <span class="hljs-title">getSourceMapping</span> = <span class="hljs-params">(filename, line, column)</span> -&gt;</span>
sourceMap = getSourceMap filename
sourceMap = getSourceMap filename, line, column
answer = sourceMap.sourceLocation [line - <span class="hljs-number">1</span>, column - <span class="hljs-number">1</span>] <span class="hljs-keyword">if</span> sourceMap?
<span class="hljs-keyword">if</span> answer? <span class="hljs-keyword">then</span> [answer[<span class="hljs-number">0</span>] + <span class="hljs-number">1</span>, answer[<span class="hljs-number">1</span>] + <span class="hljs-number">1</span>] <span class="hljs-keyword">else</span> <span class="hljs-literal">null</span>

View File

@@ -199,25 +199,26 @@ useWinPathSep = path.sep <span class="hljs-keyword">is</span> <span class="hljs
</div>
<div class="content"><div class='highlight'><pre>SWITCHES = [
[<span class="hljs-string">'-b'</span>, <span class="hljs-string">'--bare'</span>, <span class="hljs-string">'compile without a top-level function wrapper'</span>]
[<span class="hljs-string">'-c'</span>, <span class="hljs-string">'--compile'</span>, <span class="hljs-string">'compile to JavaScript and save as .js files'</span>]
[<span class="hljs-string">'-e'</span>, <span class="hljs-string">'--eval'</span>, <span class="hljs-string">'pass a string from the command line as input'</span>]
[<span class="hljs-string">'-h'</span>, <span class="hljs-string">'--help'</span>, <span class="hljs-string">'display this help message'</span>]
[<span class="hljs-string">'-i'</span>, <span class="hljs-string">'--interactive'</span>, <span class="hljs-string">'run an interactive CoffeeScript REPL'</span>]
[<span class="hljs-string">'-j'</span>, <span class="hljs-string">'--join [FILE]'</span>, <span class="hljs-string">'concatenate the source CoffeeScript before compiling'</span>]
[<span class="hljs-string">'-m'</span>, <span class="hljs-string">'--map'</span>, <span class="hljs-string">'generate source map and save as .js.map files'</span>]
[<span class="hljs-string">'-M'</span>, <span class="hljs-string">'--inline-map'</span>, <span class="hljs-string">'generate source map and include it directly in output'</span>]
[<span class="hljs-string">'-n'</span>, <span class="hljs-string">'--nodes'</span>, <span class="hljs-string">'print out the parse tree that the parser produces'</span>]
[ <span class="hljs-string">'--nodejs [ARGS]'</span>, <span class="hljs-string">'pass options directly to the "node" binary'</span>]
[ <span class="hljs-string">'--no-header'</span>, <span class="hljs-string">'suppress the "Generated by" header'</span>]
[<span class="hljs-string">'-o'</span>, <span class="hljs-string">'--output [DIR]'</span>, <span class="hljs-string">'set the output directory for compiled JavaScript'</span>]
[<span class="hljs-string">'-p'</span>, <span class="hljs-string">'--print'</span>, <span class="hljs-string">'print out the compiled JavaScript'</span>]
[<span class="hljs-string">'-b'</span>, <span class="hljs-string">'--bare'</span>, <span class="hljs-string">'compile without a top-level function wrapper'</span>]
[<span class="hljs-string">'-c'</span>, <span class="hljs-string">'--compile'</span>, <span class="hljs-string">'compile to JavaScript and save as .js files'</span>]
[<span class="hljs-string">'-e'</span>, <span class="hljs-string">'--eval'</span>, <span class="hljs-string">'pass a string from the command line as input'</span>]
[<span class="hljs-string">'-h'</span>, <span class="hljs-string">'--help'</span>, <span class="hljs-string">'display this help message'</span>]
[<span class="hljs-string">'-i'</span>, <span class="hljs-string">'--interactive'</span>, <span class="hljs-string">'run an interactive CoffeeScript REPL'</span>]
[<span class="hljs-string">'-j'</span>, <span class="hljs-string">'--join [FILE]'</span>, <span class="hljs-string">'concatenate the source CoffeeScript before compiling'</span>]
[<span class="hljs-string">'-m'</span>, <span class="hljs-string">'--map'</span>, <span class="hljs-string">'generate source map and save as .js.map files'</span>]
[<span class="hljs-string">'-M'</span>, <span class="hljs-string">'--inline-map'</span>, <span class="hljs-string">'generate source map and include it directly in output'</span>]
[<span class="hljs-string">'-n'</span>, <span class="hljs-string">'--nodes'</span>, <span class="hljs-string">'print out the parse tree that the parser produces'</span>]
[ <span class="hljs-string">'--nodejs [ARGS]'</span>, <span class="hljs-string">'pass options directly to the "node" binary'</span>]
[ <span class="hljs-string">'--no-header'</span>, <span class="hljs-string">'suppress the "Generated by" header'</span>]
[<span class="hljs-string">'-o'</span>, <span class="hljs-string">'--output [PATH]'</span>, <span class="hljs-string">'set the output path or path/filename for compiled JavaScript'</span>]
[<span class="hljs-string">'-p'</span>, <span class="hljs-string">'--print'</span>, <span class="hljs-string">'print out the compiled JavaScript'</span>]
[<span class="hljs-string">'-r'</span>, <span class="hljs-string">'--require [MODULE*]'</span>, <span class="hljs-string">'require the given module before eval or REPL'</span>]
[<span class="hljs-string">'-s'</span>, <span class="hljs-string">'--stdio'</span>, <span class="hljs-string">'listen for and compile scripts over stdio'</span>]
[<span class="hljs-string">'-l'</span>, <span class="hljs-string">'--literate'</span>, <span class="hljs-string">'treat stdio as literate style coffeescript'</span>]
[<span class="hljs-string">'-t'</span>, <span class="hljs-string">'--tokens'</span>, <span class="hljs-string">'print out the tokens that the lexer/rewriter produce'</span>]
[<span class="hljs-string">'-v'</span>, <span class="hljs-string">'--version'</span>, <span class="hljs-string">'display the version number'</span>]
[<span class="hljs-string">'-w'</span>, <span class="hljs-string">'--watch'</span>, <span class="hljs-string">'watch scripts for changes and rerun commands'</span>]
[<span class="hljs-string">'-s'</span>, <span class="hljs-string">'--stdio'</span>, <span class="hljs-string">'listen for and compile scripts over stdio'</span>]
[<span class="hljs-string">'-l'</span>, <span class="hljs-string">'--literate'</span>, <span class="hljs-string">'treat stdio as literate style coffeescript'</span>]
[<span class="hljs-string">'-t'</span>, <span class="hljs-string">'--transpile'</span>, <span class="hljs-string">'pipe generated JavaScript through Babel'</span>]
[ <span class="hljs-string">'--tokens'</span>, <span class="hljs-string">'print out the tokens that the lexer/rewriter produce'</span>]
[<span class="hljs-string">'-v'</span>, <span class="hljs-string">'--version'</span>, <span class="hljs-string">'display the version number'</span>]
[<span class="hljs-string">'-w'</span>, <span class="hljs-string">'--watch'</span>, <span class="hljs-string">'watch scripts for changes and rerun commands'</span>]
]</pre></div></div>
</li>
@@ -294,6 +295,7 @@ Many flags cause us to divert before compiling anything. Flags passed after
<div class="content"><div class='highlight'><pre> replCliOpts = useGlobal: <span class="hljs-literal">yes</span>
opts.prelude = makePrelude opts.<span class="hljs-built_in">require</span> <span class="hljs-keyword">if</span> opts.<span class="hljs-built_in">require</span>
replCliOpts.prelude = opts.prelude
replCliOpts.transpile = opts.transpile
<span class="hljs-keyword">return</span> forkNode() <span class="hljs-keyword">if</span> opts.nodejs
<span class="hljs-keyword">return</span> usage() <span class="hljs-keyword">if</span> opts.help
<span class="hljs-keyword">return</span> version() <span class="hljs-keyword">if</span> opts.version
@@ -305,7 +307,45 @@ Many flags cause us to divert before compiling anything. Flags passed after
process.argv = process.argv[<span class="hljs-number">0.</span><span class="hljs-number">.1</span>].concat literals
process.argv[<span class="hljs-number">0</span>] = <span class="hljs-string">'coffee'</span>
opts.output = path.resolve opts.output <span class="hljs-keyword">if</span> opts.output
<span class="hljs-keyword">if</span> opts.output
outputBasename = path.basename opts.output
<span class="hljs-keyword">if</span> <span class="hljs-string">'.'</span> <span class="hljs-keyword">in</span> outputBasename <span class="hljs-keyword">and</span>
outputBasename <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> [<span class="hljs-string">'.'</span>, <span class="hljs-string">'..'</span>] <span class="hljs-keyword">and</span>
<span class="hljs-keyword">not</span> helpers.ends(opts.output, path.sep)</pre></div></div>
</li>
<li id="section-9">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-9">&#182;</a>
</div>
<p>An output filename was specified, e.g. <code>/dist/scripts.js</code>.</p>
</div>
<div class="content"><div class='highlight'><pre> opts.outputFilename = outputBasename
opts.outputPath = path.resolve path.dirname opts.output
<span class="hljs-keyword">else</span></pre></div></div>
</li>
<li id="section-10">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-10">&#182;</a>
</div>
<p>An output path was specified, e.g. <code>/dist</code>.</p>
</div>
<div class="content"><div class='highlight'><pre> opts.outputFilename = <span class="hljs-literal">null</span>
opts.outputPath = path.resolve opts.output
<span class="hljs-keyword">if</span> opts.join
opts.join = path.resolve opts.join
<span class="hljs-built_in">console</span>.error <span class="hljs-string">'''
@@ -328,19 +368,19 @@ Many flags cause us to divert before compiling anything. Flags passed after
<span class="hljs-function">
<span class="hljs-title">makePrelude</span> = <span class="hljs-params">(requires)</span> -&gt;</span>
requires.map (<span class="hljs-built_in">module</span>) -&gt;
[_, name, <span class="hljs-built_in">module</span>] = match <span class="hljs-keyword">if</span> match = <span class="hljs-built_in">module</span>.match(<span class="hljs-regexp">/^(.*)=(.*)$/</span>)
name ||= helpers.baseFileName <span class="hljs-built_in">module</span>, <span class="hljs-literal">yes</span>, useWinPathSep
<span class="hljs-string">"<span class="hljs-subst">#{name}</span> = require('<span class="hljs-subst">#{<span class="hljs-built_in">module</span>}</span>')"</span>
[full, name, <span class="hljs-built_in">module</span>] = match <span class="hljs-keyword">if</span> match = <span class="hljs-built_in">module</span>.match(<span class="hljs-regexp">/^(.*)=(.*)$/</span>)
name <span class="hljs-keyword">or</span>= helpers.baseFileName <span class="hljs-built_in">module</span>, <span class="hljs-literal">yes</span>, useWinPathSep
<span class="hljs-string">"global['<span class="hljs-subst">#{name}</span>'] = require('<span class="hljs-subst">#{<span class="hljs-built_in">module</span>}</span>')"</span>
.join <span class="hljs-string">';'</span></pre></div></div>
</li>
<li id="section-9">
<li id="section-11">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-9">&#182;</a>
<a class="pilcrow" href="#section-11">&#182;</a>
</div>
<p>Compile a path, which could be a script or a directory. If a directory
is passed, recursively compile all .coffee, .litcoffee, and .coffee.md
@@ -382,7 +422,7 @@ extension source files in it and all subdirectories.</p>
code = fs.readFileSync source
<span class="hljs-keyword">catch</span> err
<span class="hljs-keyword">if</span> err.code <span class="hljs-keyword">is</span> <span class="hljs-string">'ENOENT'</span> <span class="hljs-keyword">then</span> <span class="hljs-keyword">return</span> <span class="hljs-keyword">else</span> <span class="hljs-keyword">throw</span> err
compileScript(source, code.toString(), base)
compileScript source, code.toString(), base
<span class="hljs-keyword">else</span>
notSources[source] = <span class="hljs-literal">yes</span>
<span class="hljs-function">
@@ -399,53 +439,56 @@ extension source files in it and all subdirectories.</p>
</li>
<li id="section-10">
<li id="section-12">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-10">&#182;</a>
<a class="pilcrow" href="#section-12">&#182;</a>
</div>
<p>Compile a single source script, containing the given code, according to the
requested options. If evaluating the script directly sets <code>__filename</code>,
requested options. If evaluating the script directly, set <code>__filename</code>,
<code>__dirname</code> and <code>module.filename</code> to be correct relative to the scripts path.</p>
</div>
<div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">compileScript</span> = <span class="hljs-params">(file, input, base = <span class="hljs-literal">null</span>)</span> -&gt;</span>
o = opts
options = compileOptions file, base
<span class="hljs-keyword">try</span>
t = task = {file, input, options}
task = {file, input, options}
CoffeeScript.emit <span class="hljs-string">'compile'</span>, task
<span class="hljs-keyword">if</span> o.tokens
printTokens CoffeeScript.tokens t.input, t.options
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> o.nodes
printLine CoffeeScript.nodes(t.input, t.options).toString().trim()
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> o.run
<span class="hljs-keyword">if</span> opts.tokens
printTokens CoffeeScript.tokens task.input, task.options
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> opts.nodes
printLine CoffeeScript.nodes(task.input, task.options).toString().trim()
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> opts.run
CoffeeScript.register()
CoffeeScript.eval opts.prelude, t.options <span class="hljs-keyword">if</span> opts.prelude
CoffeeScript.run t.input, t.options
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> o.join <span class="hljs-keyword">and</span> t.file <span class="hljs-keyword">isnt</span> o.join
t.input = helpers.invertLiterate t.input <span class="hljs-keyword">if</span> helpers.isLiterate file
sourceCode[sources.indexOf(t.file)] = t.input
CoffeeScript.eval opts.prelude, task.options <span class="hljs-keyword">if</span> opts.prelude
CoffeeScript.run task.input, task.options
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> opts.join <span class="hljs-keyword">and</span> task.file <span class="hljs-keyword">isnt</span> opts.join
task.input = helpers.invertLiterate task.input <span class="hljs-keyword">if</span> helpers.isLiterate file
sourceCode[sources.indexOf(task.file)] = task.input
compileJoin()
<span class="hljs-keyword">else</span>
compiled = CoffeeScript.compile t.input, t.options
t.output = compiled
<span class="hljs-keyword">if</span> o.map
t.output = compiled.js
t.sourceMap = compiled.v3SourceMap
compiled = CoffeeScript.compile task.input, task.options
task.output = compiled
<span class="hljs-keyword">if</span> opts.map
task.output = compiled.js
task.sourceMap = compiled.v3SourceMap
CoffeeScript.emit <span class="hljs-string">'success'</span>, task
<span class="hljs-keyword">if</span> o.<span class="hljs-built_in">print</span>
printLine t.output.trim()
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> o.compile <span class="hljs-keyword">or</span> o.map
writeJs base, t.file, t.output, options.jsPath, t.sourceMap
<span class="hljs-keyword">if</span> opts.<span class="hljs-built_in">print</span>
printLine task.output.trim()
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> opts.compile <span class="hljs-keyword">or</span> opts.map
saveTo = <span class="hljs-keyword">if</span> opts.outputFilename <span class="hljs-keyword">and</span> sources.length <span class="hljs-keyword">is</span> <span class="hljs-number">1</span>
path.join opts.outputPath, opts.outputFilename
<span class="hljs-keyword">else</span>
options.jsPath
writeJs base, task.file, task.output, saveTo, task.sourceMap
<span class="hljs-keyword">catch</span> err
CoffeeScript.emit <span class="hljs-string">'failure'</span>, err, task
<span class="hljs-keyword">return</span> <span class="hljs-keyword">if</span> CoffeeScript.listeners(<span class="hljs-string">'failure'</span>).length
message = err?.stack <span class="hljs-keyword">or</span> <span class="hljs-string">"<span class="hljs-subst">#{err}</span>"</span>
<span class="hljs-keyword">if</span> o.watch
<span class="hljs-keyword">if</span> opts.watch
printLine message + <span class="hljs-string">'\x07'</span>
<span class="hljs-keyword">else</span>
printWarn message
@@ -454,11 +497,11 @@ requested options. If evaluating the script directly sets <code>__filename</code
</li>
<li id="section-11">
<li id="section-13">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-11">&#182;</a>
<a class="pilcrow" href="#section-13">&#182;</a>
</div>
<p>Attach the appropriate listeners to compile scripts incoming over <strong>stdin</strong>,
and write them back to <strong>stdout</strong>.</p>
@@ -466,6 +509,9 @@ and write them back to <strong>stdout</strong>.</p>
</div>
<div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">compileStdio</span> = -&gt;</span>
<span class="hljs-keyword">if</span> opts.map
<span class="hljs-built_in">console</span>.error <span class="hljs-string">'--stdio and --map cannot be used together'</span>
process.exit <span class="hljs-number">1</span>
buffers = []
stdin = process.openStdin()
stdin.<span class="hljs-literal">on</span> <span class="hljs-string">'data'</span>, <span class="hljs-function"><span class="hljs-params">(buffer)</span> -&gt;</span>
@@ -476,11 +522,11 @@ and write them back to <strong>stdout</strong>.</p>
</li>
<li id="section-12">
<li id="section-14">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-12">&#182;</a>
<a class="pilcrow" href="#section-14">&#182;</a>
</div>
<p>If all of the source files are done being read, concatenate and compile
them together.</p>
@@ -498,11 +544,11 @@ them together.</p>
</li>
<li id="section-13">
<li id="section-15">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-13">&#182;</a>
<a class="pilcrow" href="#section-15">&#182;</a>
</div>
<p>Watch a source CoffeeScript file using <code>fs.watch</code>, recompiling it every
time the file is updated. May be used in combination with other options,
@@ -558,11 +604,11 @@ such as <code>--print</code>.</p>
</li>
<li id="section-14">
<li id="section-16">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-14">&#182;</a>
<a class="pilcrow" href="#section-16">&#182;</a>
</div>
<p>Watch a directory of files for new additions.</p>
@@ -609,11 +655,11 @@ such as <code>--print</code>.</p>
</li>
<li id="section-15">
<li id="section-17">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-15">&#182;</a>
<a class="pilcrow" href="#section-17">&#182;</a>
</div>
<p>Remove a file from our source list, and source code cache. Optionally remove
the compiled JS version as well.</p>
@@ -638,11 +684,11 @@ the compiled JS version as well.</p>
</li>
<li id="section-16">
<li id="section-18">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-16">&#182;</a>
<a class="pilcrow" href="#section-18">&#182;</a>
</div>
<p>Get the corresponding output JavaScript path for a source file.</p>
@@ -651,22 +697,22 @@ the compiled JS version as well.</p>
<div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">outputPath</span> = <span class="hljs-params">(source, base, extension=<span class="hljs-string">".js"</span>)</span> -&gt;</span>
basename = helpers.baseFileName source, <span class="hljs-literal">yes</span>, useWinPathSep
srcDir = path.dirname source
<span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> opts.output
dir = srcDir
dir = <span class="hljs-keyword">unless</span> opts.outputPath
srcDir
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> source <span class="hljs-keyword">is</span> base
dir = opts.output
opts.outputPath
<span class="hljs-keyword">else</span>
dir = path.join opts.output, path.relative base, srcDir
path.join opts.outputPath, path.relative base, srcDir
path.join dir, basename + extension</pre></div></div>
</li>
<li id="section-17">
<li id="section-19">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-17">&#182;</a>
<a class="pilcrow" href="#section-19">&#182;</a>
</div>
<p>Recursively mkdir, like <code>mkdir -p</code>.</p>
@@ -688,11 +734,11 @@ the compiled JS version as well.</p>
</li>
<li id="section-18">
<li id="section-20">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-18">&#182;</a>
<a class="pilcrow" href="#section-20">&#182;</a>
</div>
<p>Write out a JavaScript source file with the compiled code. By default, files
are written out in <code>cwd</code> as <code>.js</code> files with the same name, but the output
@@ -703,7 +749,7 @@ same directory as the <code>.js</code> file.</p>
</div>
<div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">writeJs</span> = <span class="hljs-params">(base, sourcePath, js, jsPath, generatedSourceMap = <span class="hljs-literal">null</span>)</span> -&gt;</span>
sourceMapPath = outputPath sourcePath, base, <span class="hljs-string">".js.map"</span>
sourceMapPath = <span class="hljs-string">"<span class="hljs-subst">#{jsPath}</span>.map"</span>
jsDir = path.dirname jsPath
<span class="hljs-function"> <span class="hljs-title">compile</span> = -&gt;</span>
<span class="hljs-keyword">if</span> opts.compile
@@ -726,11 +772,11 @@ same directory as the <code>.js</code> file.</p>
</li>
<li id="section-19">
<li id="section-21">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-19">&#182;</a>
<a class="pilcrow" href="#section-21">&#182;</a>
</div>
<p>Convenience for cleaner setTimeouts.</p>
@@ -741,11 +787,11 @@ same directory as the <code>.js</code> file.</p>
</li>
<li id="section-20">
<li id="section-22">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-20">&#182;</a>
<a class="pilcrow" href="#section-22">&#182;</a>
</div>
<p>When watching scripts, its useful to log changes with the timestamp.</p>
@@ -757,11 +803,11 @@ same directory as the <code>.js</code> file.</p>
</li>
<li id="section-21">
<li id="section-23">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-21">&#182;</a>
<a class="pilcrow" href="#section-23">&#182;</a>
</div>
<p>Pretty-print a stream of tokens, sans location data.</p>
@@ -777,11 +823,11 @@ same directory as the <code>.js</code> file.</p>
</li>
<li id="section-22">
<li id="section-24">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-22">&#182;</a>
<a class="pilcrow" href="#section-24">&#182;</a>
</div>
<p>Use the <a href="optparse.html">OptionParser module</a> to extract all options from
<code>process.argv</code> that are specified in <code>SWITCHES</code>.</p>
@@ -797,25 +843,121 @@ same directory as the <code>.js</code> file.</p>
</li>
<li id="section-23">
<li id="section-25">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-23">&#182;</a>
<a class="pilcrow" href="#section-25">&#182;</a>
</div>
<p>The compile-time options to pass to the CoffeeScript compiler.</p>
</div>
<div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">compileOptions</span> = <span class="hljs-params">(filename, base)</span> -&gt;</span>
answer = {
filename
<span class="hljs-keyword">if</span> opts.transpile</pre></div></div>
</li>
<li id="section-26">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-26">&#182;</a>
</div>
<p>The user has requested that the CoffeeScript compiler also transpile
via Babel. We dont include Babel as a dependency because we want to
avoid dependencies in general, and most users probably wont be relying
on us to transpile for them; we assume most users will probably either
run CoffeeScripts output without transpilation (modern Node or evergreen
browsers) or use a proper build chain like Gulp or Webpack.</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">try</span>
<span class="hljs-built_in">require</span> <span class="hljs-string">'babel-core'</span>
<span class="hljs-keyword">catch</span></pre></div></div>
</li>
<li id="section-27">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-27">&#182;</a>
</div>
<p>Give appropriate instructions depending on whether <code>coffee</code> was run
locally or globally.</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> <span class="hljs-built_in">require</span>.resolve(<span class="hljs-string">'.'</span>).indexOf(process.cwd()) <span class="hljs-keyword">is</span> <span class="hljs-number">0</span>
<span class="hljs-built_in">console</span>.error <span class="hljs-string">'''
To use --transpile, you must have babel-core installed:
npm install --save-dev babel-core
And you must save options to configure Babel in one of the places it looks to find its options.
See http://coffeescript.org/#transpilation
'''</span>
<span class="hljs-keyword">else</span>
<span class="hljs-built_in">console</span>.error <span class="hljs-string">'''
To use --transpile with globally-installed CoffeeScript, you must have babel-core installed globally:
npm install --global babel-core
And you must save options to configure Babel in one of the places it looks to find its options, relative to the file being compiled or to the current folder.
See http://coffeescript.org/#transpilation
'''</span>
process.exit <span class="hljs-number">1</span>
opts.transpile = {} <span class="hljs-keyword">unless</span> <span class="hljs-keyword">typeof</span> opts.transpile <span class="hljs-keyword">is</span> <span class="hljs-string">'object'</span></pre></div></div>
</li>
<li id="section-28">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-28">&#182;</a>
</div>
<p>Pass a reference to Babel into the compiler, so that the transpile option
is available for the CLI. We need to do this so that tools like Webpack
can <code>require(&#39;coffeescript&#39;)</code> and build correctly, without trying to
require Babel.</p>
</div>
<div class="content"><div class='highlight'><pre> opts.transpile.transpile = CoffeeScript.transpile</pre></div></div>
</li>
<li id="section-29">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-29">&#182;</a>
</div>
<p>Babel searches for its options (a <code>.babelrc</code> file, a <code>.babelrc.js</code> file,
a <code>package.json</code> file with a <code>babel</code> key, etc.) relative to the path
given to it in its <code>filename</code> option. Make sure we have a path to pass
along.</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">unless</span> opts.transpile.filename
opts.transpile.filename = filename <span class="hljs-keyword">or</span> path.resolve(base <span class="hljs-keyword">or</span> process.cwd(), <span class="hljs-string">'&lt;anonymous&gt;'</span>)
<span class="hljs-keyword">else</span>
opts.transpile = <span class="hljs-literal">no</span>
answer =
filename: filename
literate: opts.literate <span class="hljs-keyword">or</span> helpers.isLiterate(filename)
bare: opts.bare
header: opts.compile <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> opts[<span class="hljs-string">'no-header'</span>]
transpile: opts.transpile
sourceMap: opts.map
inlineMap: opts[<span class="hljs-string">'inline-map'</span>]
}
<span class="hljs-keyword">if</span> filename
<span class="hljs-keyword">if</span> base
cwd = process.cwd()
@@ -837,11 +979,11 @@ same directory as the <code>.js</code> file.</p>
</li>
<li id="section-24">
<li id="section-30">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-24">&#182;</a>
<a class="pilcrow" href="#section-30">&#182;</a>
</div>
<p>Start up a new Node.js instance with the arguments in <code>--nodejs</code> passed to
the <code>node</code> binary, preserving the other options.</p>
@@ -864,11 +1006,11 @@ the <code>node</code> binary, preserving the other options.</p>
</li>
<li id="section-25">
<li id="section-31">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-25">&#182;</a>
<a class="pilcrow" href="#section-31">&#182;</a>
</div>
<p>Print the <code>--help</code> usage message and exit. Deprecated switches are not
shown.</p>
@@ -881,11 +1023,11 @@ shown.</p>
</li>
<li id="section-26">
<li id="section-32">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-26">&#182;</a>
<a class="pilcrow" href="#section-32">&#182;</a>
</div>
<p>Print the <code>--version</code> message and exit.</p>

View File

@@ -650,7 +650,7 @@ of <strong>Block</strong> preceded by a function arrow, with an optional paramet
</div>
<div class="content"><div class='highlight'><pre> Code: [
o <span class="hljs-string">'PARAM_START ParamList PARAM_END FuncGlyph Block'</span>, <span class="hljs-function">-&gt;</span> <span class="hljs-keyword">new</span> Code $<span class="hljs-number">2</span>, $<span class="hljs-number">5</span>, $<span class="hljs-number">4</span>
o <span class="hljs-string">'PARAM_START ParamList PARAM_END FuncGlyph Block'</span>, <span class="hljs-function">-&gt;</span> <span class="hljs-keyword">new</span> Code $<span class="hljs-number">2</span>, $<span class="hljs-number">5</span>, $<span class="hljs-number">4</span>, LOC(<span class="hljs-number">1</span>)(<span class="hljs-keyword">new</span> Literal $<span class="hljs-number">1</span>)
o <span class="hljs-string">'FuncGlyph Block'</span>, <span class="hljs-function">-&gt;</span> <span class="hljs-keyword">new</span> Code [], $<span class="hljs-number">2</span>, $<span class="hljs-number">1</span>
]</pre></div></div>
@@ -788,6 +788,7 @@ that hoovers up the remaining arguments.</p>
<div class="content"><div class='highlight'><pre> SimpleAssignable: [
o <span class="hljs-string">'Identifier'</span>, <span class="hljs-function">-&gt;</span> <span class="hljs-keyword">new</span> Value $<span class="hljs-number">1</span>
o <span class="hljs-string">'Value Accessor'</span>, <span class="hljs-function">-&gt;</span> $<span class="hljs-number">1.</span>add $<span class="hljs-number">2</span>
o <span class="hljs-string">'Code Accessor'</span>, <span class="hljs-function">-&gt;</span> <span class="hljs-keyword">new</span> Value($<span class="hljs-number">1</span>).add $<span class="hljs-number">2</span>
o <span class="hljs-string">'ThisProperty'</span>
]</pre></div></div>
@@ -1006,6 +1007,7 @@ and optional references to the superclass.</p>
o <span class="hljs-string">'EXPORT Identifier = INDENT Expression OUTDENT'</span>, <span class="hljs-function">-&gt;</span> <span class="hljs-keyword">new</span> ExportNamedDeclaration <span class="hljs-keyword">new</span> Assign $<span class="hljs-number">2</span>, $<span class="hljs-number">5</span>, <span class="hljs-literal">null</span>,
moduleDeclaration: <span class="hljs-string">'export'</span>
o <span class="hljs-string">'EXPORT DEFAULT Expression'</span>, <span class="hljs-function">-&gt;</span> <span class="hljs-keyword">new</span> ExportDefaultDeclaration $<span class="hljs-number">3</span>
o <span class="hljs-string">'EXPORT DEFAULT INDENT Object OUTDENT'</span>, <span class="hljs-function">-&gt;</span> <span class="hljs-keyword">new</span> ExportDefaultDeclaration <span class="hljs-keyword">new</span> Value $<span class="hljs-number">4</span>
o <span class="hljs-string">'EXPORT EXPORT_ALL FROM String'</span>, <span class="hljs-function">-&gt;</span> <span class="hljs-keyword">new</span> ExportAllDeclaration <span class="hljs-keyword">new</span> Literal($<span class="hljs-number">2</span>), $<span class="hljs-number">4</span>
o <span class="hljs-string">'EXPORT { ExportSpecifierList OptComma } FROM String'</span>, <span class="hljs-function">-&gt;</span> <span class="hljs-keyword">new</span> ExportNamedDeclaration <span class="hljs-keyword">new</span> ExportSpecifierList($<span class="hljs-number">3</span>), $<span class="hljs-number">7</span>
]

View File

@@ -125,7 +125,11 @@ vm = <span class="hljs-built_in">require</span> <span class="hljs-str
path = <span class="hljs-built_in">require</span> <span class="hljs-string">'path'</span>
helpers = CoffeeScript.helpers
compile = CoffeeScript.compile</pre></div></div>
CoffeeScript.transpile = <span class="hljs-function"><span class="hljs-params">(js, options)</span> -&gt;</span>
<span class="hljs-keyword">try</span>
babel = <span class="hljs-built_in">require</span> <span class="hljs-string">'babel-core'</span>
<span class="hljs-keyword">catch</span></pre></div></div>
</li>
@@ -136,6 +140,73 @@ compile = CoffeeScript.compile</pre></div></div>
<div class="pilwrap ">
<a class="pilcrow" href="#section-2">&#182;</a>
</div>
<p>This error is only for Node, as CLI users will see a different error
earlier if they dont have Babel installed.</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> Error <span class="hljs-string">'To use the transpile option, you must have the \'babel-core\' module installed'</span>
babel.transform js, options</pre></div></div>
</li>
<li id="section-3">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-3">&#182;</a>
</div>
<p>The <code>compile</code> method shared by the CLI, Node and browser APIs.</p>
</div>
<div class="content"><div class='highlight'><pre>universalCompile = CoffeeScript.compile</pre></div></div>
</li>
<li id="section-4">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-4">&#182;</a>
</div>
<p>The <code>compile</code> method particular to the Node API.</p>
</div>
<div class="content"><div class='highlight'><pre>CoffeeScript.compile = <span class="hljs-function"><span class="hljs-params">(code, options)</span> -&gt;</span></pre></div></div>
</li>
<li id="section-5">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-5">&#182;</a>
</div>
<p>Pass a reference to Babel into the compiler, so that the transpile option
is available in the Node API. We need to do this so that tools like Webpack
can <code>require(&#39;coffeescript&#39;)</code> and build correctly, without trying to
require Babel.</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> options?.transpile
options.transpile.transpile = CoffeeScript.transpile
universalCompile.call CoffeeScript, code, options</pre></div></div>
</li>
<li id="section-6">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-6">&#182;</a>
</div>
<p>Compile and execute a string of CoffeeScript (on the server), correctly
setting <code>__filename</code>, <code>__dirname</code>, and relative <code>require()</code>.</p>
@@ -147,11 +218,11 @@ setting <code>__filename</code>, <code>__dirname</code>, and relative <code>requ
</li>
<li id="section-3">
<li id="section-7">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-3">&#182;</a>
<a class="pilcrow" href="#section-7">&#182;</a>
</div>
<p>Set the filename.</p>
@@ -163,11 +234,11 @@ setting <code>__filename</code>, <code>__dirname</code>, and relative <code>requ
</li>
<li id="section-4">
<li id="section-8">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-4">&#182;</a>
<a class="pilcrow" href="#section-8">&#182;</a>
</div>
<p>Clear the module cache.</p>
@@ -178,11 +249,11 @@ setting <code>__filename</code>, <code>__dirname</code>, and relative <code>requ
</li>
<li id="section-5">
<li id="section-9">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-5">&#182;</a>
<a class="pilcrow" href="#section-9">&#182;</a>
</div>
<p>Assign paths for node_modules loading</p>
@@ -197,18 +268,33 @@ setting <code>__filename</code>, <code>__dirname</code>, and relative <code>requ
</li>
<li id="section-6">
<li id="section-10">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-6">&#182;</a>
<a class="pilcrow" href="#section-10">&#182;</a>
</div>
<p>Save the options for compiling child imports.</p>
</div>
<div class="content"><div class='highlight'><pre> mainModule.options = options</pre></div></div>
</li>
<li id="section-11">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-11">&#182;</a>
</div>
<p>Compile.</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> helpers.isCoffee(mainModule.filename) <span class="hljs-keyword">or</span> <span class="hljs-built_in">require</span>.extensions
answer = compile code, options
answer = CoffeeScript.compile code, options
code = answer.js ? answer
mainModule._compile code, mainModule.filename</pre></div></div>
@@ -216,11 +302,11 @@ setting <code>__filename</code>, <code>__dirname</code>, and relative <code>requ
</li>
<li id="section-7">
<li id="section-12">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-7">&#182;</a>
<a class="pilcrow" href="#section-12">&#182;</a>
</div>
<p>Compile and evaluate a string of CoffeeScript (in a Node.js-like environment).
The CoffeeScript REPL uses this to run the input.</p>
@@ -250,11 +336,11 @@ The CoffeeScript REPL uses this to run the input.</p>
</li>
<li id="section-8">
<li id="section-13">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-8">&#182;</a>
<a class="pilcrow" href="#section-13">&#182;</a>
</div>
<p>define module/require only if they chose not to specify their own</p>
@@ -271,11 +357,11 @@ The CoffeeScript REPL uses this to run the input.</p>
</li>
<li id="section-9">
<li id="section-14">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-9">&#182;</a>
<a class="pilcrow" href="#section-14">&#182;</a>
</div>
<p>use the same hack node currently uses for their own REPL</p>
@@ -286,7 +372,7 @@ The CoffeeScript REPL uses this to run the input.</p>
o = {}
o[k] = v <span class="hljs-keyword">for</span> own k, v <span class="hljs-keyword">of</span> options
o.bare = <span class="hljs-literal">on</span> <span class="hljs-comment"># ensure return value</span>
js = compile code, o
js = CoffeeScript.compile code, o
<span class="hljs-keyword">if</span> sandbox <span class="hljs-keyword">is</span> <span class="hljs-built_in">global</span>
vm.runInThisContext js
<span class="hljs-keyword">else</span>
@@ -297,11 +383,11 @@ CoffeeScript.register = <span class="hljs-function">-&gt;</span> <span class="hl
</li>
<li id="section-10">
<li id="section-15">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-10">&#182;</a>
<a class="pilcrow" href="#section-15">&#182;</a>
</div>
<p>Throw error with deprecation warning when depending upon implicit <code>require.extensions</code> registration</p>
@@ -314,17 +400,17 @@ CoffeeScript.register = <span class="hljs-function">-&gt;</span> <span class="hl
Use CoffeeScript.register() or require the coffeescript/register module to require <span class="hljs-subst">#{ext}</span> files.
"""</span>
CoffeeScript._compileFile = <span class="hljs-function"><span class="hljs-params">(filename, sourceMap = <span class="hljs-literal">no</span>, inlineMap = <span class="hljs-literal">no</span>)</span> -&gt;</span>
CoffeeScript._compileFile = <span class="hljs-function"><span class="hljs-params">(filename, options = {})</span> -&gt;</span>
raw = fs.readFileSync filename, <span class="hljs-string">'utf8'</span></pre></div></div>
</li>
<li id="section-11">
<li id="section-16">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-11">&#182;</a>
<a class="pilcrow" href="#section-16">&#182;</a>
</div>
<p>Strip the Unicode byte order mark, if this file begins with one.</p>
@@ -332,22 +418,24 @@ CoffeeScript._compileFile = <span class="hljs-function"><span class="hljs-params
<div class="content"><div class='highlight'><pre> stripped = <span class="hljs-keyword">if</span> raw.charCodeAt(<span class="hljs-number">0</span>) <span class="hljs-keyword">is</span> <span class="hljs-number">0xFEFF</span> <span class="hljs-keyword">then</span> raw.substring <span class="hljs-number">1</span> <span class="hljs-keyword">else</span> raw
options = Object.assign {}, options,
filename: filename
literate: helpers.isLiterate filename
sourceFiles: [filename]
inlineMap: <span class="hljs-literal">yes</span> <span class="hljs-comment"># Always generate a source map, so that stack traces line up.</span>
<span class="hljs-keyword">try</span>
answer = compile stripped, {
filename, sourceMap, inlineMap
sourceFiles: [filename]
literate: helpers.isLiterate filename
}
answer = CoffeeScript.compile stripped, options
<span class="hljs-keyword">catch</span> err</pre></div></div>
</li>
<li id="section-12">
<li id="section-17">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-12">&#182;</a>
<a class="pilcrow" href="#section-17">&#182;</a>
</div>
<p>As the filename and code of a dynamically loaded file will be different
from the original file compiled with CoffeeScript.run, add that

View File

@@ -372,7 +372,6 @@ though <code>is</code> means <code>===</code> otherwise.</p>
<div class="content"><div class='highlight'><pre> idLength = id.length
poppedToken = <span class="hljs-literal">undefined</span>
<span class="hljs-keyword">if</span> id <span class="hljs-keyword">is</span> <span class="hljs-string">'own'</span> <span class="hljs-keyword">and</span> @tag() <span class="hljs-keyword">is</span> <span class="hljs-string">'FOR'</span>
@token <span class="hljs-string">'OWN'</span>, id
<span class="hljs-keyword">return</span> id.length
@@ -382,20 +381,27 @@ though <code>is</code> means <code>===</code> otherwise.</p>
<span class="hljs-keyword">if</span> id <span class="hljs-keyword">is</span> <span class="hljs-string">'as'</span> <span class="hljs-keyword">and</span> @seenImport
<span class="hljs-keyword">if</span> @value() <span class="hljs-keyword">is</span> <span class="hljs-string">'*'</span>
@tokens[@tokens.length - <span class="hljs-number">1</span>][<span class="hljs-number">0</span>] = <span class="hljs-string">'IMPORT_ALL'</span>
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> @value() <span class="hljs-keyword">in</span> COFFEE_KEYWORDS
@tokens[@tokens.length - <span class="hljs-number">1</span>][<span class="hljs-number">0</span>] = <span class="hljs-string">'IDENTIFIER'</span>
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> @value(<span class="hljs-literal">yes</span>) <span class="hljs-keyword">in</span> COFFEE_KEYWORDS
prev = @prev()
[prev[<span class="hljs-number">0</span>], prev[<span class="hljs-number">1</span>]] = [<span class="hljs-string">'IDENTIFIER'</span>, @value(<span class="hljs-literal">yes</span>)]
<span class="hljs-keyword">if</span> @tag() <span class="hljs-keyword">in</span> [<span class="hljs-string">'DEFAULT'</span>, <span class="hljs-string">'IMPORT_ALL'</span>, <span class="hljs-string">'IDENTIFIER'</span>]
@token <span class="hljs-string">'AS'</span>, id
<span class="hljs-keyword">return</span> id.length
<span class="hljs-keyword">if</span> id <span class="hljs-keyword">is</span> <span class="hljs-string">'as'</span> <span class="hljs-keyword">and</span> @seenExport <span class="hljs-keyword">and</span> @tag() <span class="hljs-keyword">in</span> [<span class="hljs-string">'IDENTIFIER'</span>, <span class="hljs-string">'DEFAULT'</span>]
@token <span class="hljs-string">'AS'</span>, id
<span class="hljs-keyword">return</span> id.length
<span class="hljs-keyword">if</span> id <span class="hljs-keyword">is</span> <span class="hljs-string">'as'</span> <span class="hljs-keyword">and</span> @seenExport
<span class="hljs-keyword">if</span> @tag() <span class="hljs-keyword">in</span> [<span class="hljs-string">'IDENTIFIER'</span>, <span class="hljs-string">'DEFAULT'</span>]
@token <span class="hljs-string">'AS'</span>, id
<span class="hljs-keyword">return</span> id.length
<span class="hljs-keyword">if</span> @value(<span class="hljs-literal">yes</span>) <span class="hljs-keyword">in</span> COFFEE_KEYWORDS
prev = @prev()
[prev[<span class="hljs-number">0</span>], prev[<span class="hljs-number">1</span>]] = [<span class="hljs-string">'IDENTIFIER'</span>, @value(<span class="hljs-literal">yes</span>)]
@token <span class="hljs-string">'AS'</span>, id
<span class="hljs-keyword">return</span> id.length
<span class="hljs-keyword">if</span> id <span class="hljs-keyword">is</span> <span class="hljs-string">'default'</span> <span class="hljs-keyword">and</span> @seenExport <span class="hljs-keyword">and</span> @tag() <span class="hljs-keyword">in</span> [<span class="hljs-string">'EXPORT'</span>, <span class="hljs-string">'AS'</span>]
@token <span class="hljs-string">'DEFAULT'</span>, id
<span class="hljs-keyword">return</span> id.length
<span class="hljs-keyword">if</span> id <span class="hljs-keyword">is</span> <span class="hljs-string">'do'</span> <span class="hljs-keyword">and</span> regExSuper = <span class="hljs-regexp">/^(\s*super)(?!\(\))/</span>.exec @chunk[<span class="hljs-number">3.</span>..]
@token <span class="hljs-string">'SUPER'</span>, <span class="hljs-string">'super'</span>
@token <span class="hljs-string">'CALL_START'</span>, <span class="hljs-string">'('</span>
@token <span class="hljs-string">'CALL_START'</span>, <span class="hljs-string">'('</span>
@token <span class="hljs-string">'CALL_END'</span>, <span class="hljs-string">')'</span>
[input, sup] = regExSuper
<span class="hljs-keyword">return</span> sup.length + <span class="hljs-number">3</span>
@@ -455,7 +461,7 @@ what CoffeeScript would normally interpret as calls to functions named
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> tag <span class="hljs-keyword">is</span> <span class="hljs-string">'PROPERTY'</span> <span class="hljs-keyword">and</span> prev
<span class="hljs-keyword">if</span> prev.spaced <span class="hljs-keyword">and</span> prev[<span class="hljs-number">0</span>] <span class="hljs-keyword">in</span> CALLABLE <span class="hljs-keyword">and</span> <span class="hljs-regexp">/^[gs]et$/</span>.test(prev[<span class="hljs-number">1</span>])
<span class="hljs-keyword">if</span> prev.spaced <span class="hljs-keyword">and</span> prev[<span class="hljs-number">0</span>] <span class="hljs-keyword">in</span> CALLABLE <span class="hljs-keyword">and</span> <span class="hljs-regexp">/^[gs]et$/</span>.test(prev[<span class="hljs-number">1</span>]) <span class="hljs-keyword">and</span> @tokens[@tokens.length - <span class="hljs-number">2</span>][<span class="hljs-number">0</span>] <span class="hljs-keyword">isnt</span> <span class="hljs-string">'.'</span>
@error <span class="hljs-string">"'<span class="hljs-subst">#{prev[<span class="hljs-number">1</span>]}</span>' cannot be used as a keyword, or as a function call without parentheses"</span>, prev[<span class="hljs-number">2</span>]
<span class="hljs-keyword">else</span>
prevprev = @tokens[@tokens.length - <span class="hljs-number">2</span>]
@@ -466,7 +472,7 @@ what CoffeeScript would normally interpret as calls to functions named
<span class="hljs-keyword">if</span> tag <span class="hljs-keyword">is</span> <span class="hljs-string">'IDENTIFIER'</span> <span class="hljs-keyword">and</span> id <span class="hljs-keyword">in</span> RESERVED
@error <span class="hljs-string">"reserved word '<span class="hljs-subst">#{id}</span>'"</span>, length: id.length
<span class="hljs-keyword">unless</span> tag <span class="hljs-keyword">is</span> <span class="hljs-string">'PROPERTY'</span>
<span class="hljs-keyword">unless</span> tag <span class="hljs-keyword">is</span> <span class="hljs-string">'PROPERTY'</span> <span class="hljs-keyword">or</span> @exportSpecifierList
<span class="hljs-keyword">if</span> id <span class="hljs-keyword">in</span> COFFEE_ALIASES
alias = id
id = COFFEE_ALIAS_MAP[id]
@@ -1000,7 +1006,7 @@ inwards past several recorded indents. Sets new @indent value.</p>
@token <span class="hljs-string">'OUTDENT'</span>, moveOut, <span class="hljs-number">0</span>, outdentLength
moveOut -= dent
@outdebt -= moveOut <span class="hljs-keyword">if</span> dent
@tokens.pop() <span class="hljs-keyword">while</span> @value() <span class="hljs-keyword">is</span> <span class="hljs-string">';'</span>
@suppressSemicolons()
@token <span class="hljs-string">'TERMINATOR'</span>, <span class="hljs-string">'\n'</span>, outdentLength, <span class="hljs-number">0</span> <span class="hljs-keyword">unless</span> @tag() <span class="hljs-keyword">is</span> <span class="hljs-string">'TERMINATOR'</span> <span class="hljs-keyword">or</span> noNewlines
@indent = decreasedIndent
@@ -1042,7 +1048,7 @@ as being “spaced”, because there are some cases where it makes a difference.
</div>
<div class="content"><div class='highlight'><pre> newlineToken: <span class="hljs-function"><span class="hljs-params">(offset)</span> -&gt;</span>
@tokens.pop() <span class="hljs-keyword">while</span> @value() <span class="hljs-keyword">is</span> <span class="hljs-string">';'</span>
@suppressSemicolons()
@token <span class="hljs-string">'TERMINATOR'</span>, <span class="hljs-string">'\n'</span>, offset, <span class="hljs-number">0</span> <span class="hljs-keyword">unless</span> @tag() <span class="hljs-keyword">is</span> <span class="hljs-string">'TERMINATOR'</span>
<span class="hljs-keyword">this</span></pre></div></div>
@@ -1278,9 +1284,10 @@ parentheses that indicate a method call from regular parentheses, and so on.</p>
@exportSpecifierList = <span class="hljs-literal">no</span>
<span class="hljs-keyword">if</span> value <span class="hljs-keyword">is</span> <span class="hljs-string">';'</span>
@error <span class="hljs-string">'unexpected ;'</span> <span class="hljs-keyword">if</span> prev?[<span class="hljs-number">0</span>] <span class="hljs-keyword">in</span> [<span class="hljs-string">'='</span>, UNFINISHED...]
@seenFor = @seenImport = @seenExport = <span class="hljs-literal">no</span>
tag = <span class="hljs-string">'TERMINATOR'</span>
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> value <span class="hljs-keyword">is</span> <span class="hljs-string">'*'</span> <span class="hljs-keyword">and</span> prev[<span class="hljs-number">0</span>] <span class="hljs-keyword">is</span> <span class="hljs-string">'EXPORT'</span>
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> value <span class="hljs-keyword">is</span> <span class="hljs-string">'*'</span> <span class="hljs-keyword">and</span> prev?[<span class="hljs-number">0</span>] <span class="hljs-keyword">is</span> <span class="hljs-string">'EXPORT'</span>
tag = <span class="hljs-string">'EXPORT_ALL'</span>
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> value <span class="hljs-keyword">in</span> MATH <span class="hljs-keyword">then</span> tag = <span class="hljs-string">'MATH'</span>
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> value <span class="hljs-keyword">in</span> COMPARE <span class="hljs-keyword">then</span> tag = <span class="hljs-string">'COMPARE'</span>
@@ -1289,11 +1296,12 @@ parentheses that indicate a method call from regular parentheses, and so on.</p>
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> value <span class="hljs-keyword">in</span> UNARY_MATH <span class="hljs-keyword">then</span> tag = <span class="hljs-string">'UNARY_MATH'</span>
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> value <span class="hljs-keyword">in</span> SHIFT <span class="hljs-keyword">then</span> tag = <span class="hljs-string">'SHIFT'</span>
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> value <span class="hljs-keyword">is</span> <span class="hljs-string">'?'</span> <span class="hljs-keyword">and</span> prev?.spaced <span class="hljs-keyword">then</span> tag = <span class="hljs-string">'BIN?'</span>
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> prev <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> prev.spaced
<span class="hljs-keyword">if</span> value <span class="hljs-keyword">is</span> <span class="hljs-string">'('</span> <span class="hljs-keyword">and</span> prev[<span class="hljs-number">0</span>] <span class="hljs-keyword">in</span> CALLABLE
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> prev
<span class="hljs-keyword">if</span> value <span class="hljs-keyword">is</span> <span class="hljs-string">'('</span> <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> prev.spaced <span class="hljs-keyword">and</span> prev[<span class="hljs-number">0</span>] <span class="hljs-keyword">in</span> CALLABLE
prev[<span class="hljs-number">0</span>] = <span class="hljs-string">'FUNC_EXIST'</span> <span class="hljs-keyword">if</span> prev[<span class="hljs-number">0</span>] <span class="hljs-keyword">is</span> <span class="hljs-string">'?'</span>
tag = <span class="hljs-string">'CALL_START'</span>
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> value <span class="hljs-keyword">is</span> <span class="hljs-string">'['</span> <span class="hljs-keyword">and</span> prev[<span class="hljs-number">0</span>] <span class="hljs-keyword">in</span> INDEXABLE
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> value <span class="hljs-keyword">is</span> <span class="hljs-string">'['</span> <span class="hljs-keyword">and</span> ((prev[<span class="hljs-number">0</span>] <span class="hljs-keyword">in</span> INDEXABLE <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> prev.spaced) <span class="hljs-keyword">or</span>
(prev[<span class="hljs-number">0</span>] <span class="hljs-keyword">is</span> <span class="hljs-string">'::'</span>)) <span class="hljs-comment"># `.prototype` cant be a method you can call.</span>
tag = <span class="hljs-string">'INDEX_START'</span>
<span class="hljs-keyword">switch</span> prev[<span class="hljs-number">0</span>]
<span class="hljs-keyword">when</span> <span class="hljs-string">'?'</span> <span class="hljs-keyword">then</span> prev[<span class="hljs-number">0</span>] = <span class="hljs-string">'INDEX_SOAK'</span>
@@ -1590,7 +1598,8 @@ of <code>&#39;NEOSTRING&#39;</code>s are converted using <code>fn</code> and tur
<span class="hljs-keyword">for</span> token, i <span class="hljs-keyword">in</span> tokens
[tag, value] = token
<span class="hljs-keyword">switch</span> tag
<span class="hljs-keyword">when</span> <span class="hljs-string">'TOKENS'</span></pre></div></div>
<span class="hljs-keyword">when</span> <span class="hljs-string">'TOKENS'</span>
<span class="hljs-keyword">if</span> value.length <span class="hljs-keyword">is</span> <span class="hljs-number">2</span></pre></div></div>
</li>
@@ -1605,7 +1614,7 @@ of <code>&#39;NEOSTRING&#39;</code>s are converted using <code>fn</code> and tur
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">continue</span> <span class="hljs-keyword">if</span> value.length <span class="hljs-keyword">is</span> <span class="hljs-number">2</span></pre></div></div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">continue</span> <span class="hljs-keyword">unless</span> value[<span class="hljs-number">0</span>].comments <span class="hljs-keyword">or</span> value[<span class="hljs-number">1</span>].comments</pre></div></div>
</li>
@@ -1616,6 +1625,59 @@ of <code>&#39;NEOSTRING&#39;</code>s are converted using <code>fn</code> and tur
<div class="pilwrap ">
<a class="pilcrow" href="#section-57">&#182;</a>
</div>
<p>There are comments (and nothing else) in this interpolation.</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> @csxDepth <span class="hljs-keyword">is</span> <span class="hljs-number">0</span></pre></div></div>
</li>
<li id="section-58">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-58">&#182;</a>
</div>
<p>This is an interpolated string, not a CSX tag; and for whatever
reason <code>`a${/*test*/}b` </code> is invalid JS. So compile to
<code>`a${/*test*/&#39;&#39;}b` </code> instead.</p>
</div>
<div class="content"><div class='highlight'><pre> placeholderToken = @makeToken <span class="hljs-string">'STRING'</span>, <span class="hljs-string">"''"</span>
<span class="hljs-keyword">else</span>
placeholderToken = @makeToken <span class="hljs-string">'JS'</span>, <span class="hljs-string">''</span></pre></div></div>
</li>
<li id="section-59">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-59">&#182;</a>
</div>
<p>Use the same location data as the first parenthesis.</p>
</div>
<div class="content"><div class='highlight'><pre> placeholderToken[<span class="hljs-number">2</span>] = value[<span class="hljs-number">0</span>][<span class="hljs-number">2</span>]
<span class="hljs-keyword">for</span> val <span class="hljs-keyword">in</span> value <span class="hljs-keyword">when</span> val.comments
placeholderToken.comments ?= []
placeholderToken.comments.push val.comments...
value.splice <span class="hljs-number">1</span>, <span class="hljs-number">0</span>, placeholderToken</pre></div></div>
</li>
<li id="section-60">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-60">&#182;</a>
</div>
<p>Push all the tokens in the fake <code>&#39;TOKENS&#39;</code> token. These already have
sane location data.</p>
@@ -1628,11 +1690,11 @@ sane location data.</p>
</li>
<li id="section-58">
<li id="section-61">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-58">&#182;</a>
<a class="pilcrow" href="#section-61">&#182;</a>
</div>
<p>Convert <code>&#39;NEOSTRING&#39;</code> into <code>&#39;STRING&#39;</code>.</p>
@@ -1643,11 +1705,11 @@ sane location data.</p>
</li>
<li id="section-59">
<li id="section-62">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-59">&#182;</a>
<a class="pilcrow" href="#section-62">&#182;</a>
</div>
<p>Optimize out empty strings. We ensure that the tokens stream always
starts with a string token, though, to make sure that the result
@@ -1664,11 +1726,11 @@ really is a string.</p>
</li>
<li id="section-60">
<li id="section-63">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-60">&#182;</a>
<a class="pilcrow" href="#section-63">&#182;</a>
</div>
<p>However, there is one case where we can optimize away a starting
empty string.</p>
@@ -1686,11 +1748,11 @@ empty string.</p>
</li>
<li id="section-61">
<li id="section-64">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-61">&#182;</a>
<a class="pilcrow" href="#section-64">&#182;</a>
</div>
<p>Create a 0-length “+” token.</p>
@@ -1723,11 +1785,11 @@ empty string.</p>
</li>
<li id="section-62">
<li id="section-65">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-62">&#182;</a>
<a class="pilcrow" href="#section-65">&#182;</a>
</div>
<p>Pairs up a closing token, ensuring that all listed pairs of tokens are
correctly balanced throughout the course of the token stream.</p>
@@ -1742,11 +1804,11 @@ correctly balanced throughout the course of the token stream.</p>
</li>
<li id="section-63">
<li id="section-66">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-63">&#182;</a>
<a class="pilcrow" href="#section-66">&#182;</a>
</div>
<p>Auto-close <code>INDENT</code> to support syntax like this:</p>
<pre><code>el.click(<span class="hljs-function"><span class="hljs-params">(event)</span> -&gt;</span>
@@ -1762,11 +1824,11 @@ correctly balanced throughout the course of the token stream.</p>
</li>
<li id="section-64">
<li id="section-67">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-64">&#182;</a>
<a class="pilcrow" href="#section-67">&#182;</a>
</div>
<h2 id="helpers">Helpers</h2>
@@ -1775,11 +1837,11 @@ correctly balanced throughout the course of the token stream.</p>
</li>
<li id="section-65">
<li id="section-68">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-65">&#182;</a>
<a class="pilcrow" href="#section-68">&#182;</a>
</div>
</div>
@@ -1787,11 +1849,11 @@ correctly balanced throughout the course of the token stream.</p>
</li>
<li id="section-66">
<li id="section-69">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-66">&#182;</a>
<a class="pilcrow" href="#section-69">&#182;</a>
</div>
<p>Returns the line and column number from an offset into the current chunk.</p>
<p><code>offset</code> is a number of characters into <code>@chunk</code>.</p>
@@ -1821,11 +1883,11 @@ correctly balanced throughout the course of the token stream.</p>
</li>
<li id="section-67">
<li id="section-70">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-67">&#182;</a>
<a class="pilcrow" href="#section-70">&#182;</a>
</div>
<p>Same as <code>token</code>, except this just returns the token without adding it
to the results.</p>
@@ -1840,11 +1902,11 @@ to the results.</p>
</li>
<li id="section-68">
<li id="section-71">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-68">&#182;</a>
<a class="pilcrow" href="#section-71">&#182;</a>
</div>
<p>Use length - 1 for the final offset - were supplying the last_line and the last_column,
so if last_column == first_column, then were looking at a character of length 1.</p>
@@ -1862,11 +1924,11 @@ so if last_column == first_column, then were looking at a character of length
</li>
<li id="section-69">
<li id="section-72">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-69">&#182;</a>
<a class="pilcrow" href="#section-72">&#182;</a>
</div>
<p>Add a token to the results.
<code>offset</code> is the offset into the current <code>@chunk</code> where the token starts.
@@ -1885,11 +1947,11 @@ not specified, the length of <code>value</code> will be used.</p>
</li>
<li id="section-70">
<li id="section-73">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-70">&#182;</a>
<a class="pilcrow" href="#section-73">&#182;</a>
</div>
<p>Peek at the last tag in the token stream.</p>
@@ -1902,28 +1964,31 @@ not specified, the length of <code>value</code> will be used.</p>
</li>
<li id="section-71">
<li id="section-74">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-71">&#182;</a>
<a class="pilcrow" href="#section-74">&#182;</a>
</div>
<p>Peek at the last value in the token stream.</p>
</div>
<div class="content"><div class='highlight'><pre> value: <span class="hljs-function">-&gt;</span>
<div class="content"><div class='highlight'><pre> value: <span class="hljs-function"><span class="hljs-params">(useOrigin = <span class="hljs-literal">no</span>)</span> -&gt;</span>
[..., token] = @tokens
token?[<span class="hljs-number">1</span>]</pre></div></div>
<span class="hljs-keyword">if</span> useOrigin <span class="hljs-keyword">and</span> token?.origin?
token.origin?[<span class="hljs-number">1</span>]
<span class="hljs-keyword">else</span>
token?[<span class="hljs-number">1</span>]</pre></div></div>
</li>
<li id="section-72">
<li id="section-75">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-72">&#182;</a>
<a class="pilcrow" href="#section-75">&#182;</a>
</div>
<p>Get the previous token in the token stream.</p>
@@ -1935,11 +2000,11 @@ not specified, the length of <code>value</code> will be used.</p>
</li>
<li id="section-73">
<li id="section-76">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-73">&#182;</a>
<a class="pilcrow" href="#section-76">&#182;</a>
</div>
<p>Are we in the midst of an unfinished expression?</p>
@@ -1967,11 +2032,11 @@ not specified, the length of <code>value</code> will be used.</p>
</li>
<li id="section-74">
<li id="section-77">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-74">&#182;</a>
<a class="pilcrow" href="#section-77">&#182;</a>
</div>
<p>surrogate pair</p>
@@ -1984,11 +2049,11 @@ not specified, the length of <code>value</code> will be used.</p>
</li>
<li id="section-75">
<li id="section-78">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-75">&#182;</a>
<a class="pilcrow" href="#section-78">&#182;</a>
</div>
<p>Replace <code>\u{...}</code> with <code>\uxxxx[\uxxxx]</code> in regexes without <code>u</code> flag</p>
@@ -2011,11 +2076,11 @@ not specified, the length of <code>value</code> will be used.</p>
</li>
<li id="section-76">
<li id="section-79">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-76">&#182;</a>
<a class="pilcrow" href="#section-79">&#182;</a>
</div>
<p>Validates escapes in strings and regexes.</p>
@@ -2043,11 +2108,11 @@ not specified, the length of <code>value</code> will be used.</p>
</li>
<li id="section-77">
<li id="section-80">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-77">&#182;</a>
<a class="pilcrow" href="#section-80">&#182;</a>
</div>
<p>Constructs a string or regex by escaping certain characters.</p>
@@ -2067,11 +2132,11 @@ not specified, the length of <code>value</code> will be used.</p>
</li>
<li id="section-78">
<li id="section-81">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-78">&#182;</a>
<a class="pilcrow" href="#section-81">&#182;</a>
</div>
<p>Ignore escaped backslashes.</p>
@@ -2085,16 +2150,21 @@ not specified, the length of <code>value</code> will be used.</p>
<span class="hljs-keyword">when</span> ls <span class="hljs-keyword">then</span> <span class="hljs-string">'\\u2028'</span>
<span class="hljs-keyword">when</span> ps <span class="hljs-keyword">then</span> <span class="hljs-string">'\\u2029'</span>
<span class="hljs-keyword">when</span> other <span class="hljs-keyword">then</span> (<span class="hljs-keyword">if</span> options.double <span class="hljs-keyword">then</span> <span class="hljs-string">"\\<span class="hljs-subst">#{other}</span>"</span> <span class="hljs-keyword">else</span> other)
<span class="hljs-string">"<span class="hljs-subst">#{options.delimiter}</span><span class="hljs-subst">#{body}</span><span class="hljs-subst">#{options.delimiter}</span>"</span></pre></div></div>
<span class="hljs-string">"<span class="hljs-subst">#{options.delimiter}</span><span class="hljs-subst">#{body}</span><span class="hljs-subst">#{options.delimiter}</span>"</span>
suppressSemicolons: <span class="hljs-function">-&gt;</span>
<span class="hljs-keyword">while</span> @value() <span class="hljs-keyword">is</span> <span class="hljs-string">';'</span>
@tokens.pop()
@error <span class="hljs-string">'unexpected ;'</span> <span class="hljs-keyword">if</span> @prev()?[<span class="hljs-number">0</span>] <span class="hljs-keyword">in</span> [<span class="hljs-string">'='</span>, UNFINISHED...]</pre></div></div>
</li>
<li id="section-79">
<li id="section-82">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-79">&#182;</a>
<a class="pilcrow" href="#section-82">&#182;</a>
</div>
<p>Throws an error at either a given offset from the current chunk or at the
location of a token (<code>token[2]</code>).</p>
@@ -2113,11 +2183,11 @@ location of a token (<code>token[2]</code>).</p>
</li>
<li id="section-80">
<li id="section-83">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-80">&#182;</a>
<a class="pilcrow" href="#section-83">&#182;</a>
</div>
<h2 id="helper-functions">Helper functions</h2>
@@ -2126,11 +2196,11 @@ location of a token (<code>token[2]</code>).</p>
</li>
<li id="section-81">
<li id="section-84">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-81">&#182;</a>
<a class="pilcrow" href="#section-84">&#182;</a>
</div>
</div>
@@ -2151,11 +2221,11 @@ exports.isUnassignable = isUnassignable</pre></div></div>
</li>
<li id="section-82">
<li id="section-85">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-82">&#182;</a>
<a class="pilcrow" href="#section-85">&#182;</a>
</div>
<p><code>from</code> isnt a CoffeeScript keyword, but it behaves like one in <code>import</code> and
<code>export</code> statements (handled above) and in the declaration line of a <code>for</code>
@@ -2170,11 +2240,11 @@ loop. Try to detect when <code>from</code> is a variable identifier and when it
</li>
<li id="section-83">
<li id="section-86">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-83">&#182;</a>
<a class="pilcrow" href="#section-86">&#182;</a>
</div>
<p><code>for i from from</code>, <code>for from from iterable</code></p>
@@ -2187,11 +2257,11 @@ loop. Try to detect when <code>from</code> is a variable identifier and when it
</li>
<li id="section-84">
<li id="section-87">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-84">&#182;</a>
<a class="pilcrow" href="#section-87">&#182;</a>
</div>
<p><code>for i from iterable</code></p>
@@ -2202,11 +2272,11 @@ loop. Try to detect when <code>from</code> is a variable identifier and when it
</li>
<li id="section-85">
<li id="section-88">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-85">&#182;</a>
<a class="pilcrow" href="#section-88">&#182;</a>
</div>
<p><code>for from…</code></p>
@@ -2218,11 +2288,11 @@ loop. Try to detect when <code>from</code> is a variable identifier and when it
</li>
<li id="section-86">
<li id="section-89">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-86">&#182;</a>
<a class="pilcrow" href="#section-89">&#182;</a>
</div>
<p><code>for {from}…</code>, <code>for [from]…</code>, <code>for {a, from}…</code>, <code>for {a: from}…</code></p>
@@ -2236,11 +2306,11 @@ loop. Try to detect when <code>from</code> is a variable identifier and when it
</li>
<li id="section-87">
<li id="section-90">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-87">&#182;</a>
<a class="pilcrow" href="#section-90">&#182;</a>
</div>
<h2 id="constants">Constants</h2>
@@ -2249,11 +2319,11 @@ loop. Try to detect when <code>from</code> is a variable identifier and when it
</li>
<li id="section-88">
<li id="section-91">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-88">&#182;</a>
<a class="pilcrow" href="#section-91">&#182;</a>
</div>
</div>
@@ -2261,11 +2331,11 @@ loop. Try to detect when <code>from</code> is a variable identifier and when it
</li>
<li id="section-89">
<li id="section-92">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-89">&#182;</a>
<a class="pilcrow" href="#section-92">&#182;</a>
</div>
<p>Keywords that CoffeeScript shares in common with JavaScript.</p>
@@ -2283,11 +2353,11 @@ loop. Try to detect when <code>from</code> is a variable identifier and when it
</li>
<li id="section-90">
<li id="section-93">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-90">&#182;</a>
<a class="pilcrow" href="#section-93">&#182;</a>
</div>
<p>CoffeeScript-only keywords.</p>
@@ -2315,11 +2385,11 @@ COFFEE_KEYWORDS = COFFEE_KEYWORDS.concat COFFEE_ALIASES</pre></div></div>
</li>
<li id="section-91">
<li id="section-94">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-91">&#182;</a>
<a class="pilcrow" href="#section-94">&#182;</a>
</div>
<p>The list of keywords that are reserved by JavaScript, but not used, or are
used by CoffeeScript internally. We throw an error when these are encountered,
@@ -2338,11 +2408,11 @@ STRICT_PROSCRIBED = [<span class="hljs-string">'arguments'</span>, <span class="
</li>
<li id="section-92">
<li id="section-95">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-92">&#182;</a>
<a class="pilcrow" href="#section-95">&#182;</a>
</div>
<p>The superset of both JavaScript keywords and reserved words, none of which may
be used as identifiers or properties.</p>
@@ -2354,11 +2424,11 @@ be used as identifiers or properties.</p>
</li>
<li id="section-93">
<li id="section-96">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-93">&#182;</a>
<a class="pilcrow" href="#section-96">&#182;</a>
</div>
<p>The character code of the nasty Microsoft madness otherwise known as the BOM.</p>
@@ -2369,11 +2439,11 @@ be used as identifiers or properties.</p>
</li>
<li id="section-94">
<li id="section-97">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-94">&#182;</a>
<a class="pilcrow" href="#section-97">&#182;</a>
</div>
<p>Token matching regexes.</p>
@@ -2427,11 +2497,11 @@ HERE_JSTOKEN = <span class="hljs-regexp">///^ ``` ((?: [^`\\] | \\[\s\S] | `
</li>
<li id="section-95">
<li id="section-98">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-95">&#182;</a>
<a class="pilcrow" href="#section-98">&#182;</a>
</div>
<p>String-matching-regexes.</p>
@@ -2465,11 +2535,11 @@ HEREDOC_INDENT = <span class="hljs-regexp">/\n+([^\n\S]*)(?=\S)/g</span></pr
</li>
<li id="section-96">
<li id="section-99">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-96">&#182;</a>
<a class="pilcrow" href="#section-99">&#182;</a>
</div>
<p>Regex-matching-regexes.</p>
@@ -2503,11 +2573,11 @@ POSSIBLY_DIVISION = <span class="hljs-regexp">/// ^ /=?\s ///</span></pre></di
</li>
<li id="section-97">
<li id="section-100">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-97">&#182;</a>
<a class="pilcrow" href="#section-100">&#182;</a>
</div>
<p>Other regexes.</p>
@@ -2550,11 +2620,11 @@ TRAILING_SPACES = <span class="hljs-regexp">/\s+$/</span></pre></div></div>
</li>
<li id="section-98">
<li id="section-101">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-98">&#182;</a>
<a class="pilcrow" href="#section-101">&#182;</a>
</div>
<p>Compound assignment tokens.</p>
@@ -2568,11 +2638,11 @@ TRAILING_SPACES = <span class="hljs-regexp">/\s+$/</span></pre></div></div>
</li>
<li id="section-99">
<li id="section-102">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-99">&#182;</a>
<a class="pilcrow" href="#section-102">&#182;</a>
</div>
<p>Unary tokens.</p>
@@ -2585,11 +2655,11 @@ UNARY_MATH = [<span class="hljs-string">'!'</span>, <span class="hljs-string">'~
</li>
<li id="section-100">
<li id="section-103">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-100">&#182;</a>
<a class="pilcrow" href="#section-103">&#182;</a>
</div>
<p>Bit-shifting tokens.</p>
@@ -2600,11 +2670,11 @@ UNARY_MATH = [<span class="hljs-string">'!'</span>, <span class="hljs-string">'~
</li>
<li id="section-101">
<li id="section-104">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-101">&#182;</a>
<a class="pilcrow" href="#section-104">&#182;</a>
</div>
<p>Comparison tokens.</p>
@@ -2615,11 +2685,11 @@ UNARY_MATH = [<span class="hljs-string">'!'</span>, <span class="hljs-string">'~
</li>
<li id="section-102">
<li id="section-105">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-102">&#182;</a>
<a class="pilcrow" href="#section-105">&#182;</a>
</div>
<p>Mathematical tokens.</p>
@@ -2630,11 +2700,11 @@ UNARY_MATH = [<span class="hljs-string">'!'</span>, <span class="hljs-string">'~
</li>
<li id="section-103">
<li id="section-106">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-103">&#182;</a>
<a class="pilcrow" href="#section-106">&#182;</a>
</div>
<p>Relational tokens that are negatable with <code>not</code> prefix.</p>
@@ -2645,11 +2715,11 @@ UNARY_MATH = [<span class="hljs-string">'!'</span>, <span class="hljs-string">'~
</li>
<li id="section-104">
<li id="section-107">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-104">&#182;</a>
<a class="pilcrow" href="#section-107">&#182;</a>
</div>
<p>Boolean tokens.</p>
@@ -2660,11 +2730,11 @@ UNARY_MATH = [<span class="hljs-string">'!'</span>, <span class="hljs-string">'~
</li>
<li id="section-105">
<li id="section-108">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-105">&#182;</a>
<a class="pilcrow" href="#section-108">&#182;</a>
</div>
<p>Tokens which could legitimately be invoked or indexed. An opening
parentheses or bracket following these tokens will be recorded as the start
@@ -2681,11 +2751,11 @@ INDEXABLE = CALLABLE.concat [
</li>
<li id="section-106">
<li id="section-109">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-106">&#182;</a>
<a class="pilcrow" href="#section-109">&#182;</a>
</div>
<p>Tokens which can be the left-hand side of a less-than comparison, i.e. <code>a&lt;b</code>.</p>
@@ -2696,11 +2766,11 @@ INDEXABLE = CALLABLE.concat [
</li>
<li id="section-107">
<li id="section-110">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-107">&#182;</a>
<a class="pilcrow" href="#section-110">&#182;</a>
</div>
<p>Tokens which a regular expression will never immediately follow (except spaced
CALLABLEs in some cases), but which a division operator can.</p>
@@ -2713,11 +2783,11 @@ CALLABLEs in some cases), but which a division operator can.</p>
</li>
<li id="section-108">
<li id="section-111">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-108">&#182;</a>
<a class="pilcrow" href="#section-111">&#182;</a>
</div>
<p>Tokens that, when immediately preceding a <code>WHEN</code>, indicate that the <code>WHEN</code>
occurs at the start of a line. We disambiguate these from trailing whens to
@@ -2730,11 +2800,11 @@ avoid an ambiguity in the grammar.</p>
</li>
<li id="section-109">
<li id="section-112">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-109">&#182;</a>
<a class="pilcrow" href="#section-112">&#182;</a>
</div>
<p>Additional indent in front of these is ignored.</p>
@@ -2745,11 +2815,11 @@ avoid an ambiguity in the grammar.</p>
</li>
<li id="section-110">
<li id="section-113">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-110">&#182;</a>
<a class="pilcrow" href="#section-113">&#182;</a>
</div>
<p>Tokens that, when appearing at the end of a line, suppress a following TERMINATOR/INDENT token</p>
@@ -2757,7 +2827,7 @@ avoid an ambiguity in the grammar.</p>
<div class="content"><div class='highlight'><pre>UNFINISHED = [<span class="hljs-string">'\\'</span>, <span class="hljs-string">'.'</span>, <span class="hljs-string">'?.'</span>, <span class="hljs-string">'?::'</span>, <span class="hljs-string">'UNARY'</span>, <span class="hljs-string">'MATH'</span>, <span class="hljs-string">'UNARY_MATH'</span>, <span class="hljs-string">'+'</span>, <span class="hljs-string">'-'</span>,
<span class="hljs-string">'**'</span>, <span class="hljs-string">'SHIFT'</span>, <span class="hljs-string">'RELATION'</span>, <span class="hljs-string">'COMPARE'</span>, <span class="hljs-string">'&amp;'</span>, <span class="hljs-string">'^'</span>, <span class="hljs-string">'|'</span>, <span class="hljs-string">'&amp;&amp;'</span>, <span class="hljs-string">'||'</span>,
<span class="hljs-string">'BIN?'</span>, <span class="hljs-string">'EXTENDS'</span>, <span class="hljs-string">'DEFAULT'</span>]</pre></div></div>
<span class="hljs-string">'BIN?'</span>, <span class="hljs-string">'EXTENDS'</span>]</pre></div></div>
</li>

File diff suppressed because it is too large Load Diff

View File

@@ -137,7 +137,8 @@ path = <span class="hljs-built_in">require</span> <span class="hljs-str
</div>
<div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">loadFile</span> = <span class="hljs-params">(<span class="hljs-built_in">module</span>, filename)</span> -&gt;</span>
answer = CoffeeScript._compileFile filename, <span class="hljs-literal">no</span>, <span class="hljs-literal">yes</span>
options = <span class="hljs-built_in">module</span>.options <span class="hljs-keyword">or</span> getRootModule(<span class="hljs-built_in">module</span>).options
answer = CoffeeScript._compileFile filename, options
<span class="hljs-built_in">module</span>._compile answer, filename</pre></div></div>
</li>
@@ -245,6 +246,22 @@ to fork both CoffeeScript files, and JavaScript files, directly.</p>
</li>
<li id="section-8">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-8">&#182;</a>
</div>
<p>Utility function to find the <code>options</code> object attached to the topmost module.</p>
</div>
<div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">getRootModule</span> = <span class="hljs-params">(<span class="hljs-built_in">module</span>)</span> -&gt;</span>
<span class="hljs-keyword">if</span> <span class="hljs-built_in">module</span>.parent <span class="hljs-keyword">then</span> getRootModule <span class="hljs-built_in">module</span>.parent <span class="hljs-keyword">else</span> <span class="hljs-built_in">module</span></pre></div></div>
</li>
</ul>
</div>
</body>

View File

@@ -126,6 +126,7 @@ CoffeeScript = <span class="hljs-built_in">require</span> <span class="hljs-stri
{merge, updateSyntaxError} = <span class="hljs-built_in">require</span> <span class="hljs-string">'./helpers'</span>
sawSIGINT = <span class="hljs-literal">no</span>
transpile = <span class="hljs-literal">no</span>
replDefaults =
prompt: <span class="hljs-string">'coffee&gt; '</span>,
@@ -223,11 +224,17 @@ Unwrap that too.</p>
<div class="pilwrap ">
<a class="pilcrow" href="#section-7">&#182;</a>
</div>
<p>Collect referenced variable names just like in <code>CoffeeScript.compile</code>.</p>
<p>Filter out tokens generated just to hold comments.</p>
</div>
<div class="content"><div class='highlight'><pre> referencedVars = (token[<span class="hljs-number">1</span>] <span class="hljs-keyword">for</span> token <span class="hljs-keyword">in</span> tokens <span class="hljs-keyword">when</span> token[<span class="hljs-number">0</span>] <span class="hljs-keyword">is</span> <span class="hljs-string">'IDENTIFIER'</span>)</pre></div></div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> tokens.length &gt;= <span class="hljs-number">2</span> <span class="hljs-keyword">and</span> tokens[<span class="hljs-number">0</span>].generated <span class="hljs-keyword">and</span>
tokens[<span class="hljs-number">0</span>].comments?.length <span class="hljs-keyword">isnt</span> <span class="hljs-number">0</span> <span class="hljs-keyword">and</span> tokens[<span class="hljs-number">0</span>][<span class="hljs-number">1</span>] <span class="hljs-keyword">is</span> <span class="hljs-string">''</span> <span class="hljs-keyword">and</span>
tokens[<span class="hljs-number">1</span>][<span class="hljs-number">0</span>] <span class="hljs-keyword">is</span> <span class="hljs-string">'TERMINATOR'</span>
tokens = tokens[<span class="hljs-number">2.</span>..]
<span class="hljs-keyword">if</span> tokens.length &gt;= <span class="hljs-number">1</span> <span class="hljs-keyword">and</span> tokens[tokens.length - <span class="hljs-number">1</span>].generated <span class="hljs-keyword">and</span>
tokens[tokens.length - <span class="hljs-number">1</span>].comments?.length <span class="hljs-keyword">isnt</span> <span class="hljs-number">0</span> <span class="hljs-keyword">and</span> tokens[tokens.length - <span class="hljs-number">1</span>][<span class="hljs-number">1</span>] <span class="hljs-keyword">is</span> <span class="hljs-string">''</span>
tokens.pop()</pre></div></div>
</li>
@@ -238,11 +245,11 @@ Unwrap that too.</p>
<div class="pilwrap ">
<a class="pilcrow" href="#section-8">&#182;</a>
</div>
<p>Generate the AST of the tokens.</p>
<p>Collect referenced variable names just like in <code>CoffeeScript.compile</code>.</p>
</div>
<div class="content"><div class='highlight'><pre> ast = CoffeeScript.nodes tokens</pre></div></div>
<div class="content"><div class='highlight'><pre> referencedVars = (token[<span class="hljs-number">1</span>] <span class="hljs-keyword">for</span> token <span class="hljs-keyword">in</span> tokens <span class="hljs-keyword">when</span> token[<span class="hljs-number">0</span>] <span class="hljs-keyword">is</span> <span class="hljs-string">'IDENTIFIER'</span>)</pre></div></div>
</li>
@@ -253,11 +260,11 @@ Unwrap that too.</p>
<div class="pilwrap ">
<a class="pilcrow" href="#section-9">&#182;</a>
</div>
<p>Add assignment to <code>__</code> variable to force the input to be an expression.</p>
<p>Generate the AST of the tokens.</p>
</div>
<div class="content"><div class='highlight'><pre> ast = <span class="hljs-keyword">new</span> Block [<span class="hljs-keyword">new</span> Assign (<span class="hljs-keyword">new</span> Value <span class="hljs-keyword">new</span> Literal <span class="hljs-string">'__'</span>), ast, <span class="hljs-string">'='</span>]</pre></div></div>
<div class="content"><div class='highlight'><pre> ast = CoffeeScript.nodes tokens</pre></div></div>
</li>
@@ -268,12 +275,11 @@ Unwrap that too.</p>
<div class="pilwrap ">
<a class="pilcrow" href="#section-10">&#182;</a>
</div>
<p>Wrap the expression in a closure to support top-level <code>await</code></p>
<p>Add assignment to <code>__</code> variable to force the input to be an expression.</p>
</div>
<div class="content"><div class='highlight'><pre> ast = <span class="hljs-keyword">new</span> Code [], ast
isAsync = ast.isAsync</pre></div></div>
<div class="content"><div class='highlight'><pre> ast = <span class="hljs-keyword">new</span> Block [<span class="hljs-keyword">new</span> Assign (<span class="hljs-keyword">new</span> Value <span class="hljs-keyword">new</span> Literal <span class="hljs-string">'__'</span>), ast, <span class="hljs-string">'='</span>]</pre></div></div>
</li>
@@ -284,13 +290,12 @@ Unwrap that too.</p>
<div class="pilwrap ">
<a class="pilcrow" href="#section-11">&#182;</a>
</div>
<p>Invoke the wrapping closure</p>
<p>Wrap the expression in a closure to support top-level <code>await</code>.</p>
</div>
<div class="content"><div class='highlight'><pre> ast = <span class="hljs-keyword">new</span> Block [<span class="hljs-keyword">new</span> Call ast]
js = ast.compile {bare: <span class="hljs-literal">yes</span>, locals: Object.keys(context), referencedVars, sharedScope: <span class="hljs-literal">yes</span>}
result = runInContext js, context, filename</pre></div></div>
<div class="content"><div class='highlight'><pre> ast = <span class="hljs-keyword">new</span> Code [], ast
isAsync = ast.isAsync</pre></div></div>
</li>
@@ -301,17 +306,14 @@ Unwrap that too.</p>
<div class="pilwrap ">
<a class="pilcrow" href="#section-12">&#182;</a>
</div>
<p>Await an async result, if necessary</p>
<p>Invoke the wrapping closure.</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> isAsync
result = <span class="hljs-keyword">await</span> result
cb <span class="hljs-literal">null</span>, result <span class="hljs-keyword">unless</span> sawSIGINT
sawSIGINT = <span class="hljs-literal">false</span>
<span class="hljs-keyword">else</span>
cb <span class="hljs-literal">null</span>, result
<span class="hljs-keyword">catch</span> err</pre></div></div>
<div class="content"><div class='highlight'><pre> ast = <span class="hljs-keyword">new</span> Block [<span class="hljs-keyword">new</span> Call ast]
js = ast.compile {bare: <span class="hljs-literal">yes</span>, locals: Object.keys(context), referencedVars, sharedScope: <span class="hljs-literal">yes</span>}
<span class="hljs-keyword">if</span> transpile
js = transpile.transpile(js, transpile.options).code</pre></div></div>
</li>
@@ -322,6 +324,44 @@ Unwrap that too.</p>
<div class="pilwrap ">
<a class="pilcrow" href="#section-13">&#182;</a>
</div>
<p>Strip <code>&quot;use strict&quot;</code>, to avoid an exception on assigning to
undeclared variable <code>__</code>.</p>
</div>
<div class="content"><div class='highlight'><pre> js = js.replace <span class="hljs-regexp">/^"use strict"|^'use strict'/</span>, <span class="hljs-string">''</span>
result = runInContext js, context, filename</pre></div></div>
</li>
<li id="section-14">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-14">&#182;</a>
</div>
<p>Await an async result, if necessary.</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> isAsync
result.<span class="hljs-keyword">then</span> (resolvedResult) -&gt;
cb <span class="hljs-literal">null</span>, resolvedResult <span class="hljs-keyword">unless</span> sawSIGINT
sawSIGINT = <span class="hljs-literal">no</span>
<span class="hljs-keyword">else</span>
cb <span class="hljs-literal">null</span>, result
<span class="hljs-keyword">catch</span> err</pre></div></div>
</li>
<li id="section-15">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-15">&#182;</a>
</div>
<p>ASTs <code>compile</code> does not add source code information to syntax errors.</p>
</div>
@@ -341,11 +381,11 @@ Unwrap that too.</p>
</li>
<li id="section-14">
<li id="section-16">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-14">&#182;</a>
<a class="pilcrow" href="#section-16">&#182;</a>
</div>
<p>Node 0.11.12 changed API, prompt is now _prompt.</p>
@@ -362,11 +402,11 @@ Unwrap that too.</p>
</li>
<li id="section-15">
<li id="section-17">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-15">&#182;</a>
<a class="pilcrow" href="#section-17">&#182;</a>
</div>
<p>Proxy nodes line listener</p>
@@ -387,11 +427,11 @@ Unwrap that too.</p>
</li>
<li id="section-16">
<li id="section-18">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-16">&#182;</a>
<a class="pilcrow" href="#section-18">&#182;</a>
</div>
<p>Handle Ctrl-v</p>
@@ -404,11 +444,11 @@ Unwrap that too.</p>
</li>
<li id="section-17">
<li id="section-19">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-17">&#182;</a>
<a class="pilcrow" href="#section-19">&#182;</a>
</div>
<p>allow arbitrarily switching between modes any time before multiple lines are entered</p>
@@ -423,11 +463,11 @@ Unwrap that too.</p>
</li>
<li id="section-18">
<li id="section-20">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-18">&#182;</a>
<a class="pilcrow" href="#section-20">&#182;</a>
</div>
<p>no-op unless the current line is empty</p>
@@ -438,11 +478,11 @@ Unwrap that too.</p>
</li>
<li id="section-19">
<li id="section-21">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-19">&#182;</a>
<a class="pilcrow" href="#section-21">&#182;</a>
</div>
<p>eval, print, loop</p>
@@ -457,11 +497,11 @@ Unwrap that too.</p>
</li>
<li id="section-20">
<li id="section-22">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-20">&#182;</a>
<a class="pilcrow" href="#section-22">&#182;</a>
</div>
<p>XXX: multiline hack</p>
@@ -479,11 +519,11 @@ Unwrap that too.</p>
</li>
<li id="section-21">
<li id="section-23">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-21">&#182;</a>
<a class="pilcrow" href="#section-23">&#182;</a>
</div>
<p>Store and load command history from a file</p>
@@ -496,11 +536,11 @@ Unwrap that too.</p>
</li>
<li id="section-22">
<li id="section-24">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-22">&#182;</a>
<a class="pilcrow" href="#section-24">&#182;</a>
</div>
<p>Get file info and at most maxSize of command history</p>
@@ -512,11 +552,11 @@ Unwrap that too.</p>
</li>
<li id="section-23">
<li id="section-25">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-23">&#182;</a>
<a class="pilcrow" href="#section-25">&#182;</a>
</div>
<p>Read last <code>size</code> bytes from the file</p>
@@ -530,11 +570,11 @@ Unwrap that too.</p>
</li>
<li id="section-24">
<li id="section-26">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-24">&#182;</a>
<a class="pilcrow" href="#section-26">&#182;</a>
</div>
<p>Set the history on the interpreter</p>
@@ -545,11 +585,11 @@ Unwrap that too.</p>
</li>
<li id="section-25">
<li id="section-27">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-25">&#182;</a>
<a class="pilcrow" href="#section-27">&#182;</a>
</div>
<p>If the history file was truncated we should pop off a potential partial line</p>
@@ -560,11 +600,11 @@ Unwrap that too.</p>
</li>
<li id="section-26">
<li id="section-28">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-26">&#182;</a>
<a class="pilcrow" href="#section-28">&#182;</a>
</div>
<p>Shift off the final blank newline</p>
@@ -582,11 +622,11 @@ Unwrap that too.</p>
</li>
<li id="section-27">
<li id="section-29">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-27">&#182;</a>
<a class="pilcrow" href="#section-29">&#182;</a>
</div>
<p>Save the latest command in the file</p>
@@ -598,11 +638,11 @@ Unwrap that too.</p>
</li>
<li id="section-28">
<li id="section-30">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-28">&#182;</a>
<a class="pilcrow" href="#section-30">&#182;</a>
</div>
<p>XXX: The SIGINT event from REPLServer is undocumented, so this is a bit fragile</p>
@@ -614,11 +654,11 @@ Unwrap that too.</p>
</li>
<li id="section-29">
<li id="section-31">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-29">&#182;</a>
<a class="pilcrow" href="#section-31">&#182;</a>
</div>
<p>Add a command to show the history stack</p>
@@ -635,11 +675,11 @@ Unwrap that too.</p>
</li>
<li id="section-30">
<li id="section-32">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-30">&#182;</a>
<a class="pilcrow" href="#section-32">&#182;</a>
</div>
<p>Node 0.11 changed API, a command such as .help is now stored as help</p>
@@ -658,6 +698,44 @@ Unwrap that too.</p>
CoffeeScript.register()
process.argv = [<span class="hljs-string">'coffee'</span>].concat process.argv[<span class="hljs-number">2.</span>.]
<span class="hljs-keyword">if</span> opts.transpile
<span class="hljs-keyword">try</span>
transpile = {}
transpile.transpile = <span class="hljs-built_in">require</span>(<span class="hljs-string">'babel-core'</span>).transform
<span class="hljs-keyword">catch</span>
<span class="hljs-built_in">console</span>.error <span class="hljs-string">'''
To use --transpile with an interactive REPL, babel-core must be installed either in the current folder or globally:
npm install --save-dev babel-core
or
npm install --global babel-core
And you must save options to configure Babel in one of the places it looks to find its options.
See http://coffeescript.org/#transpilation
'''</span>
process.exit <span class="hljs-number">1</span>
transpile.options =
filename: path.resolve process.cwd(), <span class="hljs-string">'&lt;repl&gt;'</span></pre></div></div>
</li>
<li id="section-33">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-33">&#182;</a>
</div>
<p>Since the REPL compilation path is unique (in <code>eval</code> above), we need
another way to get the <code>options</code> object attached to a module so that
it knows later on whether it needs to be transpiled. In the case of
the REPL, the only applicable option is <code>transpile</code>.</p>
</div>
<div class="content"><div class='highlight'><pre> Module = <span class="hljs-built_in">require</span> <span class="hljs-string">'module'</span>
originalModuleLoad = Module::load
Module::load = <span class="hljs-function"><span class="hljs-params">(filename)</span> -&gt;</span>
@options = transpile: transpile.options
originalModuleLoad.call @, filename
opts = merge replDefaults, opts
repl = nodeREPL.start opts
runInContext opts.prelude, repl.context, <span class="hljs-string">'prelude'</span> <span class="hljs-keyword">if</span> opts.prelude
@@ -668,11 +746,11 @@ Unwrap that too.</p>
</li>
<li id="section-31">
<li id="section-34">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-31">&#182;</a>
<a class="pilcrow" href="#section-34">&#182;</a>
</div>
<p>Adapt help inherited from the node REPL</p>

View File

@@ -234,6 +234,7 @@ output the token stream after it has been rewritten by this file.</p>
@normalizeLines()
@tagPostfixConditionals()
@addImplicitBracesAndParens()
@addParensToChainedDoIife()
@rescueStowawayComments()
@addLocationDataToGeneratedTokens()
@enforceValidCSXAttributes()
@@ -694,7 +695,8 @@ Added support for spread dots on the left side: f …a</p>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (tag <span class="hljs-keyword">in</span> IMPLICIT_FUNC <span class="hljs-keyword">and</span> token.spaced <span class="hljs-keyword">or</span>
tag <span class="hljs-keyword">is</span> <span class="hljs-string">'?'</span> <span class="hljs-keyword">and</span> i &gt; <span class="hljs-number">0</span> <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> tokens[i - <span class="hljs-number">1</span>].spaced) <span class="hljs-keyword">and</span>
(nextTag <span class="hljs-keyword">in</span> IMPLICIT_CALL <span class="hljs-keyword">or</span> nextTag <span class="hljs-keyword">is</span> <span class="hljs-string">'...'</span> <span class="hljs-keyword">or</span>
(nextTag <span class="hljs-keyword">in</span> IMPLICIT_CALL <span class="hljs-keyword">or</span>
(nextTag <span class="hljs-keyword">is</span> <span class="hljs-string">'...'</span> <span class="hljs-keyword">and</span> @tag(i + <span class="hljs-number">2</span>) <span class="hljs-keyword">in</span> IMPLICIT_CALL <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> @findTagsBackwards(i, [<span class="hljs-string">'INDEX_START'</span>, <span class="hljs-string">'['</span>])) <span class="hljs-keyword">or</span>
nextTag <span class="hljs-keyword">in</span> IMPLICIT_UNSPACED_CALL <span class="hljs-keyword">and</span>
<span class="hljs-keyword">not</span> nextToken.spaced <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> nextToken.newLine)
tag = token[<span class="hljs-number">0</span>] = <span class="hljs-string">'FUNC_EXIST'</span> <span class="hljs-keyword">if</span> tag <span class="hljs-keyword">is</span> <span class="hljs-string">'?'</span>
@@ -767,7 +769,7 @@ that creates grammatical ambiguities.</p>
<span class="hljs-keyword">when</span> @tag(i - <span class="hljs-number">2</span>) <span class="hljs-keyword">is</span> <span class="hljs-string">'@'</span> <span class="hljs-keyword">then</span> i - <span class="hljs-number">2</span>
<span class="hljs-keyword">else</span> i - <span class="hljs-number">1</span>
startsLine = s <span class="hljs-keyword">is</span> <span class="hljs-number">0</span> <span class="hljs-keyword">or</span> @tag(s - <span class="hljs-number">1</span>) <span class="hljs-keyword">in</span> LINEBREAKS <span class="hljs-keyword">or</span> tokens[s - <span class="hljs-number">1</span>].newLine</pre></div></div>
startsLine = s &lt;= <span class="hljs-number">0</span> <span class="hljs-keyword">or</span> @tag(s - <span class="hljs-number">1</span>) <span class="hljs-keyword">in</span> LINEBREAKS <span class="hljs-keyword">or</span> tokens[s - <span class="hljs-number">1</span>].newLine</pre></div></div>
</li>
@@ -914,7 +916,7 @@ e = <span class="hljs-number">2</span>
</code></pre>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> tag <span class="hljs-keyword">is</span> <span class="hljs-string">','</span> <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> @looksObjectish(i + <span class="hljs-number">1</span>) <span class="hljs-keyword">and</span> inImplicitObject() <span class="hljs-keyword">and</span>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> tag <span class="hljs-keyword">is</span> <span class="hljs-string">','</span> <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> @looksObjectish(i + <span class="hljs-number">1</span>) <span class="hljs-keyword">and</span> inImplicitObject() <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> (@tag(i + <span class="hljs-number">2</span>) <span class="hljs-keyword">in</span> [<span class="hljs-string">'FOROF'</span>, <span class="hljs-string">'FORIN'</span>]) <span class="hljs-keyword">and</span>
(nextTag <span class="hljs-keyword">isnt</span> <span class="hljs-string">'TERMINATOR'</span> <span class="hljs-keyword">or</span> <span class="hljs-keyword">not</span> @looksObjectish(i + <span class="hljs-number">2</span>))</pre></div></div>
</li>
@@ -1197,6 +1199,42 @@ location corresponding to the last “real” token under the node.</p>
<div class="pilwrap ">
<a class="pilcrow" href="#section-48">&#182;</a>
</div>
<p>Add parens around a <code>do</code> IIFE followed by a chained <code>.</code> so that the
chaining applies to the executed function rather than the function
object (see #3736)</p>
</div>
<div class="content"><div class='highlight'><pre> addParensToChainedDoIife: <span class="hljs-function">-&gt;</span>
<span class="hljs-function"> <span class="hljs-title">condition</span> = <span class="hljs-params">(token, i)</span> -&gt;</span>
@tag(i - <span class="hljs-number">1</span>) <span class="hljs-keyword">is</span> <span class="hljs-string">'OUTDENT'</span>
<span class="hljs-function"> <span class="hljs-title">action</span> = <span class="hljs-params">(token, i)</span> -&gt;</span>
<span class="hljs-keyword">return</span> <span class="hljs-keyword">unless</span> token[<span class="hljs-number">0</span>] <span class="hljs-keyword">in</span> CALL_CLOSERS
@tokens.splice doIndex, <span class="hljs-number">0</span>, generate <span class="hljs-string">'('</span>, <span class="hljs-string">'('</span>, @tokens[doIndex]
@tokens.splice i + <span class="hljs-number">1</span>, <span class="hljs-number">0</span>, generate <span class="hljs-string">')'</span>, <span class="hljs-string">')'</span>, @tokens[i]
doIndex = <span class="hljs-literal">null</span>
@scanTokens (token, i, tokens) -&gt;
<span class="hljs-keyword">return</span> <span class="hljs-number">1</span> <span class="hljs-keyword">unless</span> token[<span class="hljs-number">1</span>] <span class="hljs-keyword">is</span> <span class="hljs-string">'do'</span>
doIndex = i
glyphIndex = i + <span class="hljs-number">1</span>
<span class="hljs-keyword">if</span> @tag(i + <span class="hljs-number">1</span>) <span class="hljs-keyword">is</span> <span class="hljs-string">'PARAM_START'</span>
glyphIndex = <span class="hljs-literal">null</span>
@detectEnd i + <span class="hljs-number">1</span>,
<span class="hljs-function"><span class="hljs-params">(token, i)</span> -&gt;</span> @tag(i - <span class="hljs-number">1</span>) <span class="hljs-keyword">is</span> <span class="hljs-string">'PARAM_END'</span>
(token, i) -&gt; glyphIndex = i
<span class="hljs-keyword">return</span> <span class="hljs-number">1</span> <span class="hljs-keyword">unless</span> glyphIndex? <span class="hljs-keyword">and</span> @tag(glyphIndex) <span class="hljs-keyword">in</span> [<span class="hljs-string">'-&gt;'</span>, <span class="hljs-string">'=&gt;'</span>] <span class="hljs-keyword">and</span> @tag(glyphIndex + <span class="hljs-number">1</span>) <span class="hljs-keyword">is</span> <span class="hljs-string">'INDENT'</span>
@detectEnd glyphIndex + <span class="hljs-number">1</span>, condition, action
<span class="hljs-keyword">return</span> <span class="hljs-number">2</span></pre></div></div>
</li>
<li id="section-49">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-49">&#182;</a>
</div>
<p>Because our grammar is LALR(1), it cant handle some single-line
expressions that lack ending delimiters. The <strong>Rewriter</strong> adds the implicit
blocks, so it doesnt need to. To keep the grammar clean and tidy, trailing
@@ -1250,11 +1288,11 @@ blocks are added.</p>
</li>
<li id="section-49">
<li id="section-50">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-49">&#182;</a>
<a class="pilcrow" href="#section-50">&#182;</a>
</div>
<p>Tag postfix conditionals as such, so that we can parse them with a
different precedence.</p>
@@ -1282,11 +1320,11 @@ different precedence.</p>
</li>
<li id="section-50">
<li id="section-51">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-50">&#182;</a>
<a class="pilcrow" href="#section-51">&#182;</a>
</div>
<p>Generate the indentation tokens, based on another token on the same line.</p>
@@ -1307,11 +1345,11 @@ different precedence.</p>
</li>
<li id="section-51">
<li id="section-52">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-51">&#182;</a>
<a class="pilcrow" href="#section-52">&#182;</a>
</div>
<p>Look up a tag by token index.</p>
@@ -1322,26 +1360,14 @@ different precedence.</p>
</li>
<li id="section-52">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-52">&#182;</a>
</div>
<h2 id="constants">Constants</h2>
</div>
</li>
<li id="section-53">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-53">&#182;</a>
</div>
<h2 id="constants">Constants</h2>
</div>
</li>
@@ -1353,6 +1379,18 @@ different precedence.</p>
<div class="pilwrap ">
<a class="pilcrow" href="#section-54">&#182;</a>
</div>
</div>
</li>
<li id="section-55">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-55">&#182;</a>
</div>
<p>List of the token pairs that must be balanced.</p>
</div>
@@ -1372,11 +1410,11 @@ different precedence.</p>
</li>
<li id="section-55">
<li id="section-56">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-55">&#182;</a>
<a class="pilcrow" href="#section-56">&#182;</a>
</div>
<p>The inverse mappings of <code>BALANCED_PAIRS</code> were trying to fix up, so we can
look things up from either end.</p>
@@ -1388,11 +1426,11 @@ look things up from either end.</p>
</li>
<li id="section-56">
<li id="section-57">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-56">&#182;</a>
<a class="pilcrow" href="#section-57">&#182;</a>
</div>
<p>The tokens that signal the start/end of a balanced pair.</p>
@@ -1408,11 +1446,11 @@ EXPRESSION_END = []
</li>
<li id="section-57">
<li id="section-58">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-57">&#182;</a>
<a class="pilcrow" href="#section-58">&#182;</a>
</div>
<p>Tokens that indicate the close of a clause of an expression.</p>
@@ -1423,11 +1461,11 @@ EXPRESSION_END = []
</li>
<li id="section-58">
<li id="section-59">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-58">&#182;</a>
<a class="pilcrow" href="#section-59">&#182;</a>
</div>
<p>Tokens that, if followed by an <code>IMPLICIT_CALL</code>, indicate a function invocation.</p>
@@ -1438,11 +1476,11 @@ EXPRESSION_END = []
</li>
<li id="section-59">
<li id="section-60">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-59">&#182;</a>
<a class="pilcrow" href="#section-60">&#182;</a>
</div>
<p>If preceded by an <code>IMPLICIT_FUNC</code>, indicates a function invocation.</p>
@@ -1462,11 +1500,11 @@ IMPLICIT_UNSPACED_CALL = [<span class="hljs-string">'+'</span>, <span class="hlj
</li>
<li id="section-60">
<li id="section-61">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-60">&#182;</a>
<a class="pilcrow" href="#section-61">&#182;</a>
</div>
<p>Tokens that always mark the end of an implicit call for single-liners.</p>
@@ -1478,11 +1516,11 @@ IMPLICIT_UNSPACED_CALL = [<span class="hljs-string">'+'</span>, <span class="hlj
</li>
<li id="section-61">
<li id="section-62">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-61">&#182;</a>
<a class="pilcrow" href="#section-62">&#182;</a>
</div>
<p>Single-line flavors of block expressions that have unclosed endings.
The grammar cant disambiguate them, so we insert the implicit indentation.</p>
@@ -1495,11 +1533,11 @@ SINGLE_CLOSERS = [<span class="hljs-string">'TERMINATOR'</span>, <span class="
</li>
<li id="section-62">
<li id="section-63">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-62">&#182;</a>
<a class="pilcrow" href="#section-63">&#182;</a>
</div>
<p>Tokens that end a line.</p>
@@ -1510,11 +1548,11 @@ SINGLE_CLOSERS = [<span class="hljs-string">'TERMINATOR'</span>, <span class="
</li>
<li id="section-63">
<li id="section-64">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-63">&#182;</a>
<a class="pilcrow" href="#section-64">&#182;</a>
</div>
<p>Tokens that close open calls when they follow a newline.</p>
@@ -1525,11 +1563,11 @@ SINGLE_CLOSERS = [<span class="hljs-string">'TERMINATOR'</span>, <span class="
</li>
<li id="section-64">
<li id="section-65">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-64">&#182;</a>
<a class="pilcrow" href="#section-65">&#182;</a>
</div>
<p>Tokens that prevent a subsequent indent from ending implicit calls/objects</p>
@@ -1540,11 +1578,11 @@ SINGLE_CLOSERS = [<span class="hljs-string">'TERMINATOR'</span>, <span class="
</li>
<li id="section-65">
<li id="section-66">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-65">&#182;</a>
<a class="pilcrow" href="#section-66">&#182;</a>
</div>
<p>Tokens that are swallowed up by the parser, never leading to code generation.
You can spot these in <code>grammar.coffee</code> because the <code>o</code> function second
@@ -1558,8 +1596,8 @@ the node that becomes <code>StringWithInterpolations</code>, and therefore
<div class="content"><div class='highlight'><pre>DISCARDED = [<span class="hljs-string">'('</span>, <span class="hljs-string">')'</span>, <span class="hljs-string">'['</span>, <span class="hljs-string">']'</span>, <span class="hljs-string">'{'</span>, <span class="hljs-string">'}'</span>, <span class="hljs-string">'.'</span>, <span class="hljs-string">'..'</span>, <span class="hljs-string">'...'</span>, <span class="hljs-string">','</span>, <span class="hljs-string">'='</span>, <span class="hljs-string">'++'</span>, <span class="hljs-string">'--'</span>, <span class="hljs-string">'?'</span>,
<span class="hljs-string">'AS'</span>, <span class="hljs-string">'AWAIT'</span>, <span class="hljs-string">'CALL_START'</span>, <span class="hljs-string">'CALL_END'</span>, <span class="hljs-string">'DEFAULT'</span>, <span class="hljs-string">'ELSE'</span>, <span class="hljs-string">'EXTENDS'</span>, <span class="hljs-string">'EXPORT'</span>,
<span class="hljs-string">'FORIN'</span>, <span class="hljs-string">'FOROF'</span>, <span class="hljs-string">'FORFROM'</span>, <span class="hljs-string">'IMPORT'</span>, <span class="hljs-string">'INDENT'</span>, <span class="hljs-string">'INDEX_SOAK'</span>, <span class="hljs-string">'LEADING_WHEN'</span>,
<span class="hljs-string">'OUTDENT'</span>, <span class="hljs-string">'PARAM_START'</span>, <span class="hljs-string">'PARAM_END'</span>, <span class="hljs-string">'REGEX_START'</span>, <span class="hljs-string">'REGEX_END'</span>, <span class="hljs-string">'RETURN'</span>,
<span class="hljs-string">'STRING_END'</span>, <span class="hljs-string">'THROW'</span>, <span class="hljs-string">'UNARY'</span>, <span class="hljs-string">'YIELD'</span>
<span class="hljs-string">'OUTDENT'</span>, <span class="hljs-string">'PARAM_END'</span>, <span class="hljs-string">'REGEX_START'</span>, <span class="hljs-string">'REGEX_END'</span>, <span class="hljs-string">'RETURN'</span>, <span class="hljs-string">'STRING_END'</span>, <span class="hljs-string">'THROW'</span>,
<span class="hljs-string">'UNARY'</span>, <span class="hljs-string">'YIELD'</span>
].concat IMPLICIT_UNSPACED_CALL.concat IMPLICIT_END.concat CALL_CLOSERS.concat CONTROL_IN_IMPLICIT</pre></div></div>
</li>

View File

@@ -139,12 +139,14 @@ with external scopes.</p>
as well as a reference to the <strong>Block</strong> node it belongs to, which is
where it should declare its variables, a reference to the function that
it belongs to, and a list of variables referenced in the source code
and therefore should be avoided when generating variables.</p>
and therefore should be avoided when generating variables. Also track comments
that should be output as part of variable declarations.</p>
</div>
<div class="content"><div class='highlight'><pre> constructor: <span class="hljs-function"><span class="hljs-params">(@parent, @expressions, @method, @referencedVars)</span> -&gt;</span>
@variables = [{name: <span class="hljs-string">'arguments'</span>, type: <span class="hljs-string">'arguments'</span>}]
@comments = {}
@positions = {}
@utilities = {} <span class="hljs-keyword">unless</span> @parent</pre></div></div>

View File

@@ -370,15 +370,22 @@ column for the current line:</p>
</div>
<div class="content"><div class='highlight'><pre> v3 =
<div class="content"><div class='highlight'><pre> sources = <span class="hljs-keyword">if</span> options.sourceFiles
options.sourceFiles
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> options.filename
[options.filename]
<span class="hljs-keyword">else</span>
[<span class="hljs-string">'&lt;anonymous&gt;'</span>]
v3 =
version: <span class="hljs-number">3</span>
file: options.generatedFile <span class="hljs-keyword">or</span> <span class="hljs-string">''</span>
sourceRoot: options.sourceRoot <span class="hljs-keyword">or</span> <span class="hljs-string">''</span>
sources: options.sourceFiles <span class="hljs-keyword">or</span> [<span class="hljs-string">''</span>]
sources: sources
names: []
mappings: buffer
v3.sourcesContent = [code] <span class="hljs-keyword">if</span> options.inlineMap
v3.sourcesContent = [code] <span class="hljs-keyword">if</span> options.sourceMap <span class="hljs-keyword">or</span> options.inlineMap
v3</pre></div></div>

View File

@@ -0,0 +1,351 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=UTF-8" />
<title>Announcing CoffeeScript 2</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="canonical" href="http://coffeescript.org" />
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png">
<link rel="icon" type="image/png" href="/favicon-32x32.png" sizes="32x32">
<link rel="icon" type="image/png" href="/favicon-16x16.png" sizes="16x16">
<link rel="manifest" href="/manifest.json">
<link rel="mask-icon" href="/safari-pinned-tab.svg" color="#5bbad5">
<meta name="theme-color" content="#ffffff">
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M" crossorigin="anonymous">
<link href="https://fonts.googleapis.com/css?family=Alegreya+Sans:400,800|Galada:400|Lato:300,300i,400,700|Roboto+Mono:400,400i" rel="stylesheet" crossorigin="anonymous">
<style>
body {
/* Push below header bar */
margin-top: 3.5rem;
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1 3"><path opacity=".02" fill="#000" d="M0 0h1v1H0z"/><path opacity=".005" fill="#000" d="M0 1h1v2H0z"/></svg>');
background-size: 1px 3px;
}
svg {
width: auto;
height: 100%;
}
a {
color: #1b5e20;
transition: 0.1s ease-in-out;
}
a:focus, a:hover, a:active {
color: #388e3c;
cursor: pointer;
text-decoration: none;
}
button:focus, .navbar-dark .navbar-toggler:focus {
outline: none;
border: thin solid rgba(248, 243, 240, 0.3);
}
.bg-dark {
background-color: #3e2723 !important;
}
.bg-ribbed-light {
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1 3"><path opacity=".03" fill="#000" d="M0 0h1v1H0z"/><path opacity=".005" fill="#000" d="M0 1h1v2H0z"/></svg>');
background-size: 1px 3px;
}
.bg-ribbed-dark {
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1 3"><path opacity=".2" fill="#000" d="M0 0h1v1H0z"/><path opacity=".15" fill="#000" d="M0 1h1v2H0z"/></svg>');
background-size: 1px 3px;
}
/*
* Header
*/
.site-navbar {
height: 3.5rem;
font-family: 'Lato';
font-weight: 400;
font-size: 1.1em;
}
.navbar-brand {
height: 2.2em;
margin-right: 1em;
}
.navbar-dark path {
fill: #fff;
}
.navbar-nav .nav-item {
margin-left: 0.6em;
margin-right: 0.6em;
border-radius: 0.4em;
}
.navbar-nav .nav-item:hover,
.navbar-nav .nav-item:active,
.navbar-nav .nav-item.show {
background-color: #4e342e;
}
.navbar-toggler {
transition: all 0.1s ease-in-out;
}
/*
* Main content
*/
.main {
padding: 1.3em;
}
@media (min-width: 992px) {
.main {
padding-right: 2em;
padding-left: 2em;
}
}
h1 {
font: 2.5em Galada;
color: #2f2625;
text-align: center;
}
@media (min-width: 768px) {
h1 {
font-size: 3em;
}
}
@media (min-width: 992px) {
h1 {
font-size: 4em;
}
}
.title-logo {
display: inline-block;
height: 1em;
transform: translateY(0.2em);
margin-left: 0.3em;
margin-right: 0.25em;
fill: #2f2625;
}
.main p, .main li {
font-family: Lato;
font-weight: 300;
font-size: 1.1em;
line-height: 1.6;
}
.main blockquote {
font-size: 1.1em;
}
@media (min-width: 768px) {
.main p, .main li {
font-size: 1.3em;
}
.main blockquote {
font-size: 1.3em;
}
}
.main strong {
font-weight: 700;
}
.main a {
border-bottom: 2px solid transparent;
font-weight: 400;
}
.main a:focus, .main a:hover, .main a:active {
border-bottom: 2px solid rgba(56, 142, 60, 0.2);
}
.main blockquote pre {
background-color: #f8f3f0;
color: #2f2625;
border-radius: .3em;
padding: 0.4em 0.6em;
}
p, blockquote, li {
margin-bottom: 1.3rem;
}
.credits li {
margin-bottom: 0.3em;
}
h2, h3, h4 {
margin-top: 1.3em;
margin-bottom: 0.6em;
font-family: 'Alegreya Sans';
}
h2 {
font-weight: 800;
}
h3, h4, h2 time {
font-weight: 400;
}
.main h2 {
padding-top: 4rem;
margin-top: -4rem;
}
code {
font-family: 'Roboto Mono';
font-weight: 400;
}
code, a > code {
background-color: #f8f3f0;
padding: 0.2rem 0.4rem;
}
code {
color: #2f2625;
}
.uneditable-code-block .comment {
font-style: italic;
color: #837B85;
}
.uneditable-code-block .class,
.uneditable-code-block .function,
.uneditable-code-block .keyword,
.uneditable-code-block .reserved,
.uneditable-code-block .title {
color: #534328;
}
.uneditable-code-block .string
.uneditable-code-block .value
.uneditable-code-block .inheritance
.uneditable-code-block .header {
color: #3A4029;
}
.uneditable-code-block .variable,
.uneditable-code-block .literal,
.uneditable-code-block .tag,
.uneditable-code-block .regexp,
.uneditable-code-block .subst,
.uneditable-code-block .property {
color: #474429;
}
.uneditable-code-block .number,
.uneditable-code-block .preprocessor,
.uneditable-code-block .built_in,
.uneditable-code-block .params,
.uneditable-code-block .constant {
color: #474429;
}
</style>
</head>
<body>
<nav class="navbar navbar-expand-lg fixed-top navbar-dark bg-dark bg-ribbed-dark site-navbar">
<a class="navbar-brand" href="/" data-close="try"><svg xmlns="http://www.w3.org/2000/svg" viewBox="-22 347 566 100">
<title>
CoffeeScript Logo
</title>
<path d="M21.7 351.1c.1.6-.2 1.1-1.2 1.6-1.3-.7-4.1-1.1-6.4-.9-2.5.2-4.6 1-4.3 2.7.4 1.7 2.8 2.7 7.1 2.3 10.5-.9 10.4-8 25.8-9.4 12-1.1 18.7 2.6 19.6 7.1.7 3.5-2.2 6.9-10.9 7.6-7.7.7-12.2-1.4-12.6-3.5-.2-1.1.4-2.7 4.1-3.1.4 1.7 2.5 3.5 7.5 3 3.6-.3 6.6-1.6 6.2-3.6-.4-2.1-4.2-3.3-10.2-2.8-12.2 1.1-15.2 7.8-25.6 8.7-7.4.7-13.4-2-14.2-6-.3-1.5-.3-5 7.5-5.7 4-.3 7.2.4 7.6 2zm-39 41.8c-3.4 4.3-4.9 9.3-4.6 14.2.3 4.9 2.7 8.9 6.5 12 4 3.1 8.3 4 13.2 3.1 1.9-.3 4-1.3 5.9-1.9-4 0-7.4-1.3-10.8-4-3.7-2.7-6.2-6.5-6.8-11.1-.9-4.3 0-8.3 2.4-11.8 2.7-3.4 6.2-5.3 10.8-5.9 4.6-.3 8.6.9 12.6 3.7-.9-1.3-2.2-2.2-3.4-3.4-4-2.7-8.3-4-13.6-2.7-4.8 1-8.8 3.5-12.2 7.8zm53.6-23.1c-12.9 0-24.4-1.3-32.7-3.1-8.9-2.2-13.6-4.6-13.6-7.7 0-1.3.6-2.4 2.4-3.7-5.6 2.2-8.6 4-8.6 6.8.3 3.1 5.3 6.2 15.5 8.6 9.6 2.4 21.9 3.7 36.7 3.7 15.1 0 27.1-1.3 36.7-3.7 10.2-2.4 15.1-5.6 15.1-8.6 0-2.2-2.2-4.3-6.2-5.9.9.6 1.6 1.6 1.6 2.7 0 3.1-4.6 5.6-13.9 7.7-8.6 1.9-19.6 3.2-33 3.2zm36.8 8.6c-9.6 2.2-21.9 3.7-36.7 3.7-15.1 0-27.4-1.6-37-3.7-8.6-2.2-13.2-4.6-14.8-7.1 1.6 10.8 5.3 21 10.2 30 3.7 5.6 7.4 10.5 11.1 15.8 1.6 3.1 2.7 6.2 3.4 9.3 2.4 3.4 5.9 5.6 10.2 6.8 5.3 1.9 10.8 2.7 16.4 2.4h.6c5.6.3 11.5-.6 16.9-2.4 4-1.3 7.4-3.4 9.9-6.8h.3c.6-3.1 1.6-6.2 3.1-9.3 3.7-5.3 7.4-10.2 11.1-15.8 4.9-8.9 8.3-19.1 10.2-30-2 2.8-6.6 5.2-14.9 7.1zm106.2 30.1c-4.8 12.1-17.6 16.9-25.9 16.9-13.4 0-19.9-6-19.9-22.3 0-16.5 7.9-47.3 31.7-47.3 8.5 0 15.2 3.3 15.2 12.1 0 4.8-1.8 8.3-6.4 8.3-1.5 0-3.4-.4-5.2-2.4 2.2-1.1 4.2-4.9 4.2-8.3 0-2.9-1.5-5.6-5.6-5.6-10 0-18.9 23.9-18.9 42.4 0 8.3 2.2 14.2 10.9 14.2 7.1 0 13.5-3.4 17.7-9.1l2.2 1.1zm32.9-16.3c.4.2.7.2 1 .2 4.2 0 10.1-2.7 14-5.5l.8 2.4c-3.4 3.7-9.5 6.5-16.1 7.5-1.5 16.8-10.6 27.3-21.7 27.3-8.4 0-14.5-4-14.5-14.4 0-10.5 6.2-32.2 24.9-32.2 7.8.3 11.6 5.3 11.6 14.7zm-7.7 5c-1.9-.5-2.4-2-2.4-3.8 0-2.5 1.2-4.2 2.8-4.9-.2-3.8-1.1-5.3-3.4-5.3-6.5 0-12 16.6-12 25.6 0 6 1.2 7.3 4.6 7.3 4.2.1 8.9-8 10.4-18.9zm-6.6 39.7c0-8.3 7.1-11 15.8-13.6l10.9-51.9c2.7-13 10.6-15.5 16.5-15.5 4.1 0 8 2.2 9.7 5.7 3.6-4.6 8.4-5.7 12.4-5.7 5.6 0 10.8 3.9 10.8 9.8 0 1.5-.1 2.6-.3 3.7h-4.3c.1-.9.2-1.7.2-2.4 0-2.1-1.7-3.1-3.4-3.1-2 0-4.8 1.1-6.2 7.1l-1.7 7.4h9.1l-.8 3.6h-9l-10.3 49.1c-2.7 13-10.6 15.5-16.5 15.5-5.2 0-8.3-2.3-9.8-5.7-3.5 4.6-8.3 5.7-12.3 5.7-5.6.1-10.8-3.8-10.8-9.7zm9.1 1.8c1.9 0 4.2-1.8 5.4-7.1l1.1-5.3c-5.7 2-10.1 4.4-10.1 9.4 0 1.2 1.7 3 3.6 3zm21.7 0c1.9 0 4.2-1.8 5.4-7.1l2.2-10.4-9.4 1.8-1.8 8.3c-.5 2.1-1.1 4-1.8 5.6.9 1.3 3 1.8 5.4 1.8zm-1.4-18l9.4-1.7 7.7-36.8h-9l-8.1 38.5zm16.6-56.7c-2 0-4.8 1.1-6.2 7.1l-1.7 7.4h9l2.1-9.5c.2-.7.2-1.3.2-2 .1-2-1.5-3-3.4-3zm37.9 53c7.1 0 11.6-4 16.1-9.2h3.1c-5.2 8.3-12.9 16.8-25 16.8-8.5 0-14.2-4.2-14.2-14.5 0-10.5 5.9-32.3 24.6-32.3 8.1 0 10 4.2 10 8.7 0 10.5-10 18.5-20.9 19.2-.1 1.3-.2 2.5-.2 3.6 0 6.2 2.2 7.7 6.5 7.7zm5.3-34.4c-4.6 0-9.1 9.7-10.9 18.7 7-.5 13.2-7.4 13.2-15 0-2.2-.5-3.7-2.3-3.7zm28.6 33.4c3.4 0 7.8-2.3 10.8-4.8-2 10.4-8.4 13.4-15.8 13.4-8.4 0-14.1-4.2-14.1-14.5 0-10.5 5.9-32.3 24.6-32.3 8.1 0 10 4.2 10 8.7 0 10.6-10 18.5-20.9 19.2-.1.9-.2 2-.2 2.7 0 5.7 2.5 7.6 5.6 7.6zm6.2-33.4c-4.5 0-9.1 10.1-11 18.7 7.1-.4 13.3-7.3 13.3-15 0-2.2-.6-3.7-2.3-3.7zm51.3-6.7c-1.7 0-3-.6-4.2-1.9 2.4-1.5 4.1-4.8 4.1-7.8 0-3.1-1.8-6.1-6.8-6.1s-8.3 2.8-8.3 8.2c0 13.3 20.5 15.2 20.5 34.8 0 15.3-12.3 22.7-25.6 22.7-10.4 0-19.3-4.5-19.3-15.7 0-9.8 7-14.9 13.3-14.9 3.1 0 7.7 1.3 8 6-4.9 0-10.7 2.3-10.7 8.5 0 4.5 2.9 8.7 8.7 8.7 6.1 0 10.6-4.4 10.6-12 0-15.6-18.6-21.1-18.6-34.5 0-9.5 9.3-16.3 21-16.3 4.3 0 14.6.9 14.6 10.9.1 5.5-2.8 9.4-7.3 9.4zm36.2 10.3c0-2.3-.8-3.7-2.5-3.7-5.7 0-11.7 16.6-11.7 26.7 0 6.2 2.2 7.6 6.6 7.6 7.1 0 11.6-4 16.1-9.2h3.1c-5.2 8.3-12.9 16.8-25 16.8-8.5 0-14.2-4.2-14.2-14.5 0-10.6 6-32.3 24.5-32.3 8.1 0 10.1 4.2 10.1 8.3 0 4.4-2.2 6.7-4.8 6.7-1 0-2.1-.4-3.1-1.1.5-1.9.9-3.6.9-5.3zm27.7-7.6l-1.2 5.7c3.1-2.7 6.7-5.7 11-5.7 4.1 0 6.3 3.3 6.3 6.9 0 3.1-2.1 6.7-6.6 6.7-5.1 0-2.5-6-5.3-6-2.7 0-4.4 1.4-6.7 3.4l-7.2 34.6h-13.1l9.6-45.4 13.2-.2zm34.2 0l-6.6 30.9c-.3 1.2-.4 2.1-.4 2.9 0 2.5 1.2 3.3 3.7 3.3 3.5 0 6.9-3.4 8.1-8h3.8c-5.2 14.8-14.2 16.8-19.1 16.8-5.5 0-9.7-3.2-9.7-10.9 0-1.8.3-3.7.7-5.9l6.2-29.2 13.3.1zm-4.1-19.4c4 0 7.2 3.2 7.2 7.2s-3.2 7.1-7.2 7.1-7.1-3.1-7.1-7.1c-.1-4 3.2-7.2 7.1-7.2zm29.1 16l-1.5 6.9c2.6-2.3 6.1-3.9 10.7-3.9 6.2 0 11.1 3.5 11.1 14.4 0 12.2-4.7 32.1-22.3 32.1-4.5 0-6.8-1.6-7.7-3.2l-4.7 22.1-13.7 3.2 15.2-71.5 12.9-.1zm7.8 17c0-7-2.9-7.5-4.5-7.5-2 0-4.5 1.6-6.3 4.4l-5.4 25.5c.4 1 1.4 2.1 3.4 2.1 9.7 0 12.8-15.9 12.8-24.5zm27.8 17.3c-.3 1.1-.5 2.2-.5 3.1 0 1.9.7 3.2 3.1 3.2.7 0 1.7 0 2.4-.3-2.5 7.8-6.6 8.9-9.6 8.9-6.4 0-9.1-4.4-9.1-10.3 0-1.6.2-3.1.6-4.8l5.8-27.2h-3l.7-3.6h3L528 366l13.4-1.9s-1.4 6.2-3.1 14.4h5.5l-.7 3.6h-5.5l-5.7 27.4z"/>
</svg>
</a>
<button class="navbar-toggler" type="button" data-toggle="offcanvas" data-close="try" aria-label="Toggle sidebar">
<span class="navbar-toggler-icon"></span>
</button>
<nav class="collapse navbar-collapse">
<div class="navbar-nav mr-auto d-none d-lg-flex">
<a href="../#try" id="try-link" class="nav-item nav-link" data-toggle="try">Try CoffeeScript</a>
<a href="../#language" class="nav-item nav-link" data-close="try">Language Reference</a>
<a href="../#resources" class="nav-item nav-link" data-close="try">Resources</a>
<a href="https://github.com/jashkenas/coffeescript" class="nav-item nav-link" data-close="try">GitHub
</a>
</div>
</nav>
</nav>
<div class="container" id="top">
<div class="row">
<main class="main">
<header>
<h1>Announcing <span class="text-nowrap"><svg class="title-logo" xmlns="http://www.w3.org/2000/svg" viewBox="-76 212 458 369">
<title>
CoffeeScript Icon
</title>
<path d="M106 228.6c.5 2.3-.9 4.4-5 6.5-5.5-3.1-16.9-4.4-26.7-3.5-10.4.9-19.4 4.2-17.9 11.3 1.5 7.1 11.7 11 29.5 9.5 43.6-3.8 43.4-33.3 107.4-39 49.8-4.4 77.8 11 81.8 29.7 3.1 14.7-9.1 28.6-45.2 31.8-32 2.8-50.7-5.6-52.6-14.6-1-4.5 1.8-11.3 17.2-13.1 1.5 7 10.6 14.4 31.1 12.6 14.8-1.3 27.6-6.6 25.9-14.9-1.8-8.6-17.7-13.7-42.6-11.5-50.7 4.5-63.2 32.5-106.8 36.3-30.8 2.7-55.9-8.5-59.4-25.1-1.3-6.1-1.4-21 31.2-23.9 17.1-1.5 30.7 1.5 32.1 7.9zM-56.4 402.5c-14.3 18-20.4 38.8-19.2 59.2 1.2 20.4 11.4 37.1 26.9 50.2C-32 525-14 528.6 6.4 525c7.8-1.2 16.7-5.3 24.5-7.8-16.7 0-31-5.3-44.9-16.7-15.5-11.4-25.7-26.9-28.2-46.1-3.7-18 0-34.7 10.2-49 11.4-14.3 25.7-22 44.9-24.5 19.2-1.2 35.9 3.7 52.6 15.5-3.7-5.3-9-9-14.3-14.3-16.7-11.4-34.7-16.7-56.7-11.4-19.9 3.6-36.7 13.8-50.9 31.8zm223.6-96.3c-53.9 0-101.6-5.3-136.3-13.1-37.1-9-56.7-19.2-56.7-32.2 0-5.3 2.4-10.2 10.2-15.5-23.3 9-35.9 16.7-35.9 28.2 1.2 13.1 22 25.7 64.5 35.9 40 10.2 91.4 15.5 153 15.5 62.8 0 113-5.3 153-15.5 42.4-10.2 62.8-23.3 62.8-35.9 0-9-9-18-25.7-24.5 3.7 2.4 6.5 6.5 6.5 11.4 0 13.1-19.2 23.3-57.9 32.2-36 8.2-82.1 13.5-137.5 13.5zm153 35.9c-40 9-91.4 15.5-153 15.5-62.8 0-114.2-6.5-154.2-15.5-35.9-9-55.1-19.2-61.6-29.4 6.5 44.9 22 87.3 42.4 124.8 15.5 23.3 31 43.7 46.1 65.7 6.5 13.1 11.4 25.7 14.3 38.8 10.2 14.3 24.5 23.3 42.4 28.2 22 7.8 44.9 11.4 68.1 10.2h2.4c23.3 1.2 47.7-2.4 70.6-10.2 16.7-5.3 31-14.3 41.2-28.2h1.2c2.4-13.1 6.5-25.7 13.1-38.8 15.5-22 31-42.4 46.1-65.7 20.4-37.1 34.7-79.6 42.4-124.8-7.7 11.4-26.9 21.6-61.5 29.4z"/>
</svg> CoffeeScript 2</span></h1>
</header>
<section>
<p>We are pleased to announce CoffeeScript 2! This new release of the CoffeeScript language and compiler aims to bring CoffeeScript into the modern JavaScript era, closing gaps in compatibility with JavaScript while preserving the clean syntax that is CoffeeScripts hallmark. In a nutshell:</p>
<ul>
<li>The CoffeeScript 2 compiler now translates CoffeeScript code into modern JavaScript syntax. So a CoffeeScript <code>=&gt;</code> is now output as <code>=&gt;</code>, a CoffeeScript <code>class</code> is now output using the <code>class</code> keyword, and so on. This means you may need to <a href="../#transpilation">transpile the CoffeeScript compilers output</a>.</li>
<li>CoffeeScript 2 adds support for <a href="../#async-functions">async functions</a> syntax, for the future <a href="../#destructuring">object destructuring</a> syntax, and for <a href="../#jsx">JSX</a>. Some features, such as <a href="../#modules">modules</a> (<code>import</code> and <code>export</code> statements), <a href="../#generator-iteration"><code>for…of</code></a>, and <a href="../#tagged-template-literals">tagged template literals</a> were backported into CoffeeScript versions 1.11 and 1.12.</li>
<li>All of the above was achieved with very few <a href="../#breaking-changes">breaking changes from 1.x</a>. Most current CoffeeScript projects should be able to upgrade with little or no refactoring necessary.</li>
</ul>
<p>CoffeeScript 2 was developed with two primary goals: remove any incompatibilities with modern JavaScript that might prevent CoffeeScript from being used on a project; and preserve as much backward compatibility as possible. <a href="../#installation">Install now</a>: <code>npm install -g coffeescript@2</code></p>
<h2 id="modern-javascript-output">Modern JavaScript Output</h2>
<p>From the beginning, CoffeeScript has been described as being “just JavaScript.” And today, JavaScript is ES2015 (well, ES2017; also commonly known as ES6). CoffeeScript welcomes the changes in the JavaScript world and were happy to stop outputting circa-1999 syntax for modern features.</p>
<p>Many new JavaScript features, such as <code>=&gt;</code>, were informed by CoffeeScript and are one-to-one compatible, or very nearly so. This has made outputting many of CoffeeScripts innovations into new JS syntax straightforward: not only does <code>=&gt;</code> become <code>=&gt;</code>, but <code>{ a } = obj</code> becomes <code>{ a } = obj</code>, <code>&quot;a#{b}c&quot;</code> becomes <code>`a${b}c`</code> and so on.</p>
<p>The following CoffeeScript features were updated in 2.0 to output using modern JavaScript syntax (or added in CoffeeScript 1.11 through 2.0, output using modern syntax):</p>
<ul>
<li>Modules: <code>import</code>/<code>export</code></li>
<li>Classes: <code>class Animal</code></li>
<li>Async functions: <code>await someFunction()</code></li>
<li>Bound/arrow functions: <code>=&gt;</code></li>
<li>Function default parameters: <code>(options = {}) -&gt;</code></li>
<li>Function splat/rest parameters: <code>(items...) -&gt;</code></li>
<li>Destructuring, for both arrays and objects: <code>[first, second] = items</code>, <code>{length} = items</code></li>
<li>Object rest/spread properties: <code>{options..., force: yes}</code>, <code>{force, otherOptions...} = options</code></li>
<li>Interpolated strings/template literals (JS backticked strings): <code>&quot;Hello, #{user}!&quot;</code></li>
<li>Tagged template literals: <code>html&quot;&lt;strong&gt;coffee&lt;/strong&gt;&quot;</code></li>
<li>JavaScripts <code>for…of</code> is now available as CoffeeScripts <code>for…from</code> (we already had a <code>for…of</code>): <code>for n from generatorFunction()</code></li>
</ul>
<p>Not all CoffeeScript features were adopted into JavaScript in 100% the same way; most notably, <a href="../#breaking-changes-default-values">default values</a> in JavaScript (and also in CoffeeScript 2) are only applied when a variable is <code>undefined</code>, not <code>undefined</code> or <code>null</code> as in CoffeeScript 1; and <a href="../#breaking-changes-classes">classes</a> have their own differences. See the <a href="../#breaking-changes">breaking changes</a> for the fine details.</p>
<p>In our experience, most breaking changes are edge cases that should affect very few people, like JavaScripts <a href="../#breaking-change-fat-arrow">lack of an <code>arguments</code> object inside arrow functions</a>. There seem to be two breaking changes that affect a significant number of projects:</p>
<ul>
<li>In CoffeeScript 2, “bare” <code>super</code> (calling <code>super</code> without arguments) is now no longer allowed, and one must use <code>super()</code> or <code>super arguments...</code> instead.</li>
<li>References to <code>this</code>/<code>@</code> cannot occur before a call to <code>super</code>, per the JS spec.</li>
</ul>
<p>See the <a href="../#breaking-changes-super-extends">full details</a>. Either the CoffeeScript compiler or your transpiler will throw errors for either of these cases, so updating your code is a matter of fixing each occurrence as the compiler errors on it, until your code compiles successfully.</p>
<h2 id="other-features">Other Features</h2>
<p>Besides supporting new JavaScript features and outputting older CoffeeScript features in modern JS syntax, CoffeeScript 2 has added support for the following:</p>
<ul>
<li><a href="../#jsx">JSX</a></li>
<li><a href="../#comments">Line comments</a> are now output (in CoffeeScript 1 they were discarded)</li>
<li>Block comments are now allowed anywhere, enabling <a href="../#type-annotations">static type annotations</a> using Flows comment-based syntax</li>
</ul>
<p>There are many smaller improvements as well, such as to the <code>coffee</code> command-line tool. You can read all the details in the <a href="../#changelog">changelog</a> for the 2.0.0 betas.</p>
<h2 id="what-about-…">“What About …?”</h2>
<p>A few JavaScript features have been intentionally omitted from CoffeeScript. These include <code>let</code> and <code>const</code> (and <code>var</code>), named functions and the <code>get</code> and <code>set</code> keywords. These get asked about so often that we added a section to the docs called <a href="../#unsupported">Unsupported ECMAScript Features</a>. CoffeeScripts lack of equivalents for these features does not affect compatibility or interoperability with JavaScript modules or libraries.</p>
<h2 id="future-compatibility">Future Compatibility</h2>
<p>Back when CoffeeScript 1 was created, ES2015 JavaScript and transpilers like <a href="http://babeljs.io/">Babel</a>, <a href="https://buble.surge.sh/">Bublé</a> or <a href="https://github.com/google/traceur-compiler">Traceur Compiler</a> were several years away. The CoffeeScript compiler itself had to do what todays transpilers do, converting modern features like destructuring and arrow functions into equivalent lowest-common-denominator JavaScript.</p>
<p>But transpilers exist now, and they do their job well. With them around, theres no need for the CoffeeScript compiler to duplicate this functionality. All the CoffeeScript compiler needs to worry about now is converting the CoffeeScript version of new syntax into the JS version of that syntax, e.g. <code>&quot;Hello, #{name}!&quot;</code> into <code>`Hello, ${name}!`</code>. This makes adding support for new JavaScript features much easier than before.</p>
<p>Most features added by ECMA in recent years havent required any updates at all in CoffeeScript. New global objects, or new methods on global objects, dont require any updates on CoffeeScripts part to work. Some proposed future JS features <em>do</em> involve new syntax, like <a href="https://github.com/tc39/proposal-class-fields">class fields</a>. We have adopted a policy of supporting new syntax only when it reaches Stage 4 in ECMAs process, which means that the syntax is final and will be in the next ES release. On occasion we might support a <em>feature</em> before it has reached Stage 4, but output it using equivalent non-experimental syntax instead of the newly-proposed syntax; thats whats happening in 2.0.0 for <a href="../#splats">object destructuring</a>, where our output uses the same polyfill that Babel uses. When the new syntax is finalized, we will update our output to use the final syntax.</p>
<h2 id="credits">Credits</h2>
<p>The major features of 2.0.0 would not have been possible without the following people:</p>
<ul class="credits">
<li><a href="https://github.com/GeoffreyBooth">@GeoffreyBooth</a>: Organizer of the CoffeeScript 2 effort, developer for modules; arrow functions, function default parameters and function rest parameters output using ES2015 syntax; line comments output and block comments output anywhere; block embedded JavaScript via triple backticks; improved parsing of Literate CoffeeScript; and the new docs website.</li>
<li><a href="https://github.com/connec">@connec</a>: Classes; destructuring; splats/rest syntax in arrays and function calls; and computed properties all output using ES2015 syntax.</li>
<li><a href="https://github.com/GabrielRatener">@GabrielRatener</a>: Async functions.</li>
<li><a href="https://github.com/xixixao">@xixixao</a>: JSX.</li>
<li><a href="https://github.com/zdenko">@zdenko</a>: Object rest/spread properties (object destructuring).</li>
<li><a href="https://github.com/greghuc">@greghuc</a>: Tagged template literals, interpolated strings output in ES2015 syntax.</li>
<li><a href="https://github.com/atg">@atg</a>: ES2015 <code>for…of</code>, supported as CoffeeScripts <code>for…from</code>.</li>
<li><a href="https://github.com/lydell">@lydell</a> and <a href="https://github.com/jashkenas">@jashkenas</a>: Guidance, code reviews and feedback.</li>
</ul>
<p>See the full <a href="https://github.com/jashkenas/coffeescript/wiki/CoffeeScript-2-Honor-Roll">honor roll</a>.</p>
<p>Thanks and we hope you enjoy CoffeeScript 2!</p>
</section>
</main>
</div>
</div>
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-106156830-1"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments)};
gtag('js', new Date());
gtag('config', 'UA-106156830-1');
</script>
</body>
</html>

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,8 +1,10 @@
# Eat lunch.
eat = (food) -> "#{food} eaten."
eat food for food in ['toast', 'cheese', 'wine']
# Fine five course dining.
courses = ['greens', 'caviar', 'truffles', 'roast', 'cake']
menu = (i, dish) -> "Menu Item #{i}: #{dish}"
menu i + 1, dish for dish, i in courses
# Health conscious meal.

View File

@@ -0,0 +1,4 @@
class B extends A
constructor: (arg) ->
super arg
@arg = arg

View File

@@ -2,5 +2,5 @@ $ 'body'
.click (e) ->
$ '.box'
.fadeIn 'fast'
.addClass '.active'
.addClass 'show'
.css 'background', 'white'

View File

@@ -4,4 +4,4 @@ Released under the MIT License
###
sayFortune = (fortune) ->
console.log fortune # in bed!
console.log fortune # in bed!

View File

@@ -1,9 +1,9 @@
class Teenager
@say: (speech) ->
words = speech.split ' '
fillers = ['uh', 'um', 'like', 'actually', 'so', 'maybe']
output = []
for word, index in words
output.push word
output.push fillers[Math.floor(Math.random() * fillers.length)] unless index is words.length - 1
output.join ', '
@say: (speech) ->
words = speech.split ' '
fillers = ['uh', 'um', 'like', 'actually', 'so', 'maybe']
output = []
for word, index in words
output.push word
output.push fillers[Math.floor(Math.random() * fillers.length)] unless index is words.length - 1
output.join ', '

View File

@@ -1,4 +1,10 @@
# @flow
fn = (str ###: string ###, num ###: number ###) ###: string ### ->
str + num
###::
type Obj = {
num: number,
};
###
fn = (str ###: string ###, obj ###: Obj ###) ###: string ### ->
str + obj.num

View File

@@ -1,6 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-22 347 566 100">
<title>
CoffeeScript Logo
</title>
<path d="M21.7 351.1c.1.6-.2 1.1-1.2 1.6-1.3-.7-4.1-1.1-6.4-.9-2.5.2-4.6 1-4.3 2.7.4 1.7 2.8 2.7 7.1 2.3 10.5-.9 10.4-8 25.8-9.4 12-1.1 18.7 2.6 19.6 7.1.7 3.5-2.2 6.9-10.9 7.6-7.7.7-12.2-1.4-12.6-3.5-.2-1.1.4-2.7 4.1-3.1.4 1.7 2.5 3.5 7.5 3 3.6-.3 6.6-1.6 6.2-3.6-.4-2.1-4.2-3.3-10.2-2.8-12.2 1.1-15.2 7.8-25.6 8.7-7.4.7-13.4-2-14.2-6-.3-1.5-.3-5 7.5-5.7 4-.3 7.2.4 7.6 2zm-39 41.8c-3.4 4.3-4.9 9.3-4.6 14.2.3 4.9 2.7 8.9 6.5 12 4 3.1 8.3 4 13.2 3.1 1.9-.3 4-1.3 5.9-1.9-4 0-7.4-1.3-10.8-4-3.7-2.7-6.2-6.5-6.8-11.1-.9-4.3 0-8.3 2.4-11.8 2.7-3.4 6.2-5.3 10.8-5.9 4.6-.3 8.6.9 12.6 3.7-.9-1.3-2.2-2.2-3.4-3.4-4-2.7-8.3-4-13.6-2.7-4.8 1-8.8 3.5-12.2 7.8zm53.6-23.1c-12.9 0-24.4-1.3-32.7-3.1-8.9-2.2-13.6-4.6-13.6-7.7 0-1.3.6-2.4 2.4-3.7-5.6 2.2-8.6 4-8.6 6.8.3 3.1 5.3 6.2 15.5 8.6 9.6 2.4 21.9 3.7 36.7 3.7 15.1 0 27.1-1.3 36.7-3.7 10.2-2.4 15.1-5.6 15.1-8.6 0-2.2-2.2-4.3-6.2-5.9.9.6 1.6 1.6 1.6 2.7 0 3.1-4.6 5.6-13.9 7.7-8.6 1.9-19.6 3.2-33 3.2zm36.8 8.6c-9.6 2.2-21.9 3.7-36.7 3.7-15.1 0-27.4-1.6-37-3.7-8.6-2.2-13.2-4.6-14.8-7.1 1.6 10.8 5.3 21 10.2 30 3.7 5.6 7.4 10.5 11.1 15.8 1.6 3.1 2.7 6.2 3.4 9.3 2.4 3.4 5.9 5.6 10.2 6.8 5.3 1.9 10.8 2.7 16.4 2.4h.6c5.6.3 11.5-.6 16.9-2.4 4-1.3 7.4-3.4 9.9-6.8h.3c.6-3.1 1.6-6.2 3.1-9.3 3.7-5.3 7.4-10.2 11.1-15.8 4.9-8.9 8.3-19.1 10.2-30-2 2.8-6.6 5.2-14.9 7.1zm106.2 30.1c-4.8 12.1-17.6 16.9-25.9 16.9-13.4 0-19.9-6-19.9-22.3 0-16.5 7.9-47.3 31.7-47.3 8.5 0 15.2 3.3 15.2 12.1 0 4.8-1.8 8.3-6.4 8.3-1.5 0-3.4-.4-5.2-2.4 2.2-1.1 4.2-4.9 4.2-8.3 0-2.9-1.5-5.6-5.6-5.6-10 0-18.9 23.9-18.9 42.4 0 8.3 2.2 14.2 10.9 14.2 7.1 0 13.5-3.4 17.7-9.1l2.2 1.1zm32.9-16.3c.4.2.7.2 1 .2 4.2 0 10.1-2.7 14-5.5l.8 2.4c-3.4 3.7-9.5 6.5-16.1 7.5-1.5 16.8-10.6 27.3-21.7 27.3-8.4 0-14.5-4-14.5-14.4 0-10.5 6.2-32.2 24.9-32.2 7.8.3 11.6 5.3 11.6 14.7zm-7.7 5c-1.9-.5-2.4-2-2.4-3.8 0-2.5 1.2-4.2 2.8-4.9-.2-3.8-1.1-5.3-3.4-5.3-6.5 0-12 16.6-12 25.6 0 6 1.2 7.3 4.6 7.3 4.2.1 8.9-8 10.4-18.9zm-6.6 39.7c0-8.3 7.1-11 15.8-13.6l10.9-51.9c2.7-13 10.6-15.5 16.5-15.5 4.1 0 8 2.2 9.7 5.7 3.6-4.6 8.4-5.7 12.4-5.7 5.6 0 10.8 3.9 10.8 9.8 0 1.5-.1 2.6-.3 3.7h-4.3c.1-.9.2-1.7.2-2.4 0-2.1-1.7-3.1-3.4-3.1-2 0-4.8 1.1-6.2 7.1l-1.7 7.4h9.1l-.8 3.6h-9l-10.3 49.1c-2.7 13-10.6 15.5-16.5 15.5-5.2 0-8.3-2.3-9.8-5.7-3.5 4.6-8.3 5.7-12.3 5.7-5.6.1-10.8-3.8-10.8-9.7zm9.1 1.8c1.9 0 4.2-1.8 5.4-7.1l1.1-5.3c-5.7 2-10.1 4.4-10.1 9.4 0 1.2 1.7 3 3.6 3zm21.7 0c1.9 0 4.2-1.8 5.4-7.1l2.2-10.4-9.4 1.8-1.8 8.3c-.5 2.1-1.1 4-1.8 5.6.9 1.3 3 1.8 5.4 1.8zm-1.4-18l9.4-1.7 7.7-36.8h-9l-8.1 38.5zm16.6-56.7c-2 0-4.8 1.1-6.2 7.1l-1.7 7.4h9l2.1-9.5c.2-.7.2-1.3.2-2 .1-2-1.5-3-3.4-3zm37.9 53c7.1 0 11.6-4 16.1-9.2h3.1c-5.2 8.3-12.9 16.8-25 16.8-8.5 0-14.2-4.2-14.2-14.5 0-10.5 5.9-32.3 24.6-32.3 8.1 0 10 4.2 10 8.7 0 10.5-10 18.5-20.9 19.2-.1 1.3-.2 2.5-.2 3.6 0 6.2 2.2 7.7 6.5 7.7zm5.3-34.4c-4.6 0-9.1 9.7-10.9 18.7 7-.5 13.2-7.4 13.2-15 0-2.2-.5-3.7-2.3-3.7zm28.6 33.4c3.4 0 7.8-2.3 10.8-4.8-2 10.4-8.4 13.4-15.8 13.4-8.4 0-14.1-4.2-14.1-14.5 0-10.5 5.9-32.3 24.6-32.3 8.1 0 10 4.2 10 8.7 0 10.6-10 18.5-20.9 19.2-.1.9-.2 2-.2 2.7 0 5.7 2.5 7.6 5.6 7.6zm6.2-33.4c-4.5 0-9.1 10.1-11 18.7 7.1-.4 13.3-7.3 13.3-15 0-2.2-.6-3.7-2.3-3.7zm51.3-6.7c-1.7 0-3-.6-4.2-1.9 2.4-1.5 4.1-4.8 4.1-7.8 0-3.1-1.8-6.1-6.8-6.1s-8.3 2.8-8.3 8.2c0 13.3 20.5 15.2 20.5 34.8 0 15.3-12.3 22.7-25.6 22.7-10.4 0-19.3-4.5-19.3-15.7 0-9.8 7-14.9 13.3-14.9 3.1 0 7.7 1.3 8 6-4.9 0-10.7 2.3-10.7 8.5 0 4.5 2.9 8.7 8.7 8.7 6.1 0 10.6-4.4 10.6-12 0-15.6-18.6-21.1-18.6-34.5 0-9.5 9.3-16.3 21-16.3 4.3 0 14.6.9 14.6 10.9.1 5.5-2.8 9.4-7.3 9.4zm36.2 10.3c0-2.3-.8-3.7-2.5-3.7-5.7 0-11.7 16.6-11.7 26.7 0 6.2 2.2 7.6 6.6 7.6 7.1 0 11.6-4 16.1-9.2h3.1c-5.2 8.3-12.9 16.8-25 16.8-8.5 0-14.2-4.2-14.2-14.5 0-10.6 6-32.3 24.5-32.3 8.1 0 10.1 4.2 10.1 8.3 0 4.4-2.2 6.7-4.8 6.7-1 0-2.1-.4-3.1-1.1.5-1.9.9-3.6.9-5.3zm27.7-7.6l-1.2 5.7c3.1-2.7 6.7-5.7 11-5.7 4.1 0 6.3 3.3 6.3 6.9 0 3.1-2.1 6.7-6.6 6.7-5.1 0-2.5-6-5.3-6-2.7 0-4.4 1.4-6.7 3.4l-7.2 34.6h-13.1l9.6-45.4 13.2-.2zm34.2 0l-6.6 30.9c-.3 1.2-.4 2.1-.4 2.9 0 2.5 1.2 3.3 3.7 3.3 3.5 0 6.9-3.4 8.1-8h3.8c-5.2 14.8-14.2 16.8-19.1 16.8-5.5 0-9.7-3.2-9.7-10.9 0-1.8.3-3.7.7-5.9l6.2-29.2 13.3.1zm-4.1-19.4c4 0 7.2 3.2 7.2 7.2s-3.2 7.1-7.2 7.1-7.1-3.1-7.1-7.1c-.1-4 3.2-7.2 7.1-7.2zm29.1 16l-1.5 6.9c2.6-2.3 6.1-3.9 10.7-3.9 6.2 0 11.1 3.5 11.1 14.4 0 12.2-4.7 32.1-22.3 32.1-4.5 0-6.8-1.6-7.7-3.2l-4.7 22.1-13.7 3.2 15.2-71.5 12.9-.1zm7.8 17c0-7-2.9-7.5-4.5-7.5-2 0-4.5 1.6-6.3 4.4l-5.4 25.5c.4 1 1.4 2.1 3.4 2.1 9.7 0 12.8-15.9 12.8-24.5zm27.8 17.3c-.3 1.1-.5 2.2-.5 3.1 0 1.9.7 3.2 3.1 3.2.7 0 1.7 0 2.4-.3-2.5 7.8-6.6 8.9-9.6 8.9-6.4 0-9.1-4.4-9.1-10.3 0-1.6.2-3.1.6-4.8l5.8-27.2h-3l.7-3.6h3L528 366l13.4-1.9s-1.4 6.2-3.1 14.4h5.5l-.7 3.6h-5.5l-5.7 27.4z"/>
</svg>

Before

Width:  |  Height:  |  Size: 4.7 KiB

View File

@@ -1,16 +1,16 @@
## Annotated Source
You can browse the CoffeeScript <%= fullVersion %> source in readable, annotated form [here](http://coffeescript.org/v<%= majorVersion %>/annotated-source/). You can also jump directly to a particular source file:
You can browse the CoffeeScript <%= fullVersion %> source in readable, annotated form [here](annotated-source/). You can also jump directly to a particular source file:
- [Grammar Rules — src/grammar](http://coffeescript.org/v<%= majorVersion %>/annotated-source/grammar.html)
- [Lexing Tokens — src/lexer](http://coffeescript.org/v<%= majorVersion %>/annotated-source/lexer.html)
- [The Rewriter — src/rewriter](http://coffeescript.org/v<%= majorVersion %>/annotated-source/rewriter.html)
- [The Syntax Tree — src/nodes](http://coffeescript.org/v<%= majorVersion %>/annotated-source/nodes.html)
- [Lexical Scope — src/scope](http://coffeescript.org/v<%= majorVersion %>/annotated-source/scope.html)
- [Helpers &amp; Utility Functions — src/helpers](http://coffeescript.org/v<%= majorVersion %>/annotated-source/helpers.html)
- [The CoffeeScript Module — src/coffeescript](http://coffeescript.org/v<%= majorVersion %>/annotated-source/coffeescript.html)
- [Cake &amp; Cakefiles — src/cake](http://coffeescript.org/v<%= majorVersion %>/annotated-source/cake.html)
- [“coffee” Command-Line Utility — src/command](http://coffeescript.org/v<%= majorVersion %>/annotated-source/command.html)
- [Option Parsing — src/optparse](http://coffeescript.org/v<%= majorVersion %>/annotated-source/optparse.html)
- [Interactive REPL — src/repl](http://coffeescript.org/v<%= majorVersion %>/annotated-source/repl.html)
- [Source Maps — src/sourcemap](http://coffeescript.org/v<%= majorVersion %>/annotated-source/sourcemap.html)
- [Grammar Rules — src/grammar](annotated-source/grammar.html)
- [Lexing Tokens — src/lexer](annotated-source/lexer.html)
- [The Rewriter — src/rewriter](annotated-source/rewriter.html)
- [The Syntax Tree — src/nodes](annotated-source/nodes.html)
- [Lexical Scope — src/scope](annotated-source/scope.html)
- [Helpers &amp; Utility Functions — src/helpers](annotated-source/helpers.html)
- [The CoffeeScript Module — src/coffeescript](annotated-source/coffeescript.html)
- [Cake &amp; Cakefiles — src/cake](annotated-source/cake.html)
- [“coffee” Command-Line Utility — src/command](annotated-source/command.html)
- [Option Parsing — src/optparse](annotated-source/optparse.html)
- [Interactive REPL — src/repl](annotated-source/repl.html)
- [Source Maps — src/sourcemap](annotated-source/sourcemap.html)

View File

@@ -0,0 +1,78 @@
# Announcing CoffeeScript 2
We are pleased to announce CoffeeScript 2! This new release of the CoffeeScript language and compiler aims to bring CoffeeScript into the modern JavaScript era, closing gaps in compatibility with JavaScript while preserving the clean syntax that is CoffeeScripts hallmark. In a nutshell:
- The CoffeeScript 2 compiler now translates CoffeeScript code into modern JavaScript syntax. So a CoffeeScript `=>` is now output as `=>`, a CoffeeScript `class` is now output using the `class` keyword, and so on. This means you may need to [transpile the CoffeeScript compilers output](../#es2015plus-output).
- CoffeeScript 2 adds support for [async functions](../#async-functions) syntax, for the future [object destructuring](../#destructuring) syntax, and for [JSX](../#jsx). Some features, such as [modules](../#modules) (`import` and `export` statements), [`for…of`](../#generator-iteration), and [tagged template literals](../#tagged-template-literals) were backported into CoffeeScript versions 1.11 and 1.12.
- All of the above was achieved with very few [breaking changes from 1.x](../#breaking-changes). Most current CoffeeScript projects should be able to upgrade with little or no refactoring necessary.
CoffeeScript 2 was developed with two primary goals: remove any incompatibilities with modern JavaScript that might prevent CoffeeScript from being used on a project; and preserve as much backward compatibility as possible. [Install now](../#installation): `npm install -g coffeescript@2`
## Modern JavaScript Output
From the beginning, CoffeeScript has been described as being “just JavaScript.” And today, JavaScript is ES2015 (well, ES2017; also commonly known as ES6). CoffeeScript welcomes the changes in the JavaScript world and were happy to stop outputting circa-1999 syntax for modern features.
Many new JavaScript features, such as `=>`, were informed by CoffeeScript and are one-to-one compatible, or very nearly so. This has made outputting many of CoffeeScripts innovations into new JS syntax straightforward: not only does `=>` become `=>`, but `{ a } = obj` becomes `{ a } = obj`, `"a#{b}c"` becomes `` `a${b}c` `` and so on.
The following CoffeeScript features were updated in 2.0 to output using modern JavaScript syntax (or added in CoffeeScript 1.11 through 2.0, output using modern syntax):
- Modules: `import`/`export`
- Classes: `class Animal`
- Async functions: `await someFunction()`
- Bound/arrow functions: `=>`
- Function default parameters: `(options = {}) ->`
- Function splat/rest parameters: `(items...) ->`
- Destructuring, for both arrays and objects: `[first, second] = items`, `{length} = items`
- Object rest/spread properties: `{options..., force: yes}`, `{force, otherOptions...} = options`
- Interpolated strings/template literals (JS backticked strings): `"Hello, #{user}!"`
- Tagged template literals: `html"<strong>coffee</strong>"`
- JavaScripts `for…of` is now available as CoffeeScripts `for…from` (we already had a `for…of`): `for n from generatorFunction()`
Not all CoffeeScript features were adopted into JavaScript in 100% the same way; most notably, [default values](../#breaking-changes-default-values) in JavaScript (and also in CoffeeScript 2) are only applied when a variable is `undefined`, not `undefined` or `null` as in CoffeeScript 1; and [classes](../#breaking-changes-classes) have their own differences. See the [breaking changes](../#breaking-changes) for the fine details.
In our experience, most breaking changes are edge cases that should affect very few people, like JavaScripts [lack of an `arguments` object inside arrow functions](../#breaking-change-fat-arrow). There seem to be two breaking changes that affect a significant number of projects:
- In CoffeeScript 2, “bare” `super` (calling `super` without arguments) is now no longer allowed, and one must use `super()` or `super arguments...` instead.
- References to `this`/`@` cannot occur before a call to `super`, per the JS spec.
See the [full details](../#breaking-changes-super-extends). Either the CoffeeScript compiler or your transpiler will throw errors for either of these cases, so updating your code is a matter of fixing each occurrence as the compiler errors on it, until your code compiles successfully.
## Other Features
Besides supporting new JavaScript features and outputting older CoffeeScript features in modern JS syntax, CoffeeScript 2 has added support for the following:
- [JSX](../#jsx)
- [Line comments](../#comments) are now output (in CoffeeScript 1 they were discarded)
- Block comments are now allowed anywhere, enabling [static type annotations](../#type-annotations) using Flows comment-based syntax
There are many smaller improvements as well, such as to the `coffee` command-line tool. You can read all the details in the [changelog](../#changelog) for the 2.0.0 betas.
## “What About …?”
A few JavaScript features have been intentionally omitted from CoffeeScript. These include `let` and `const` (and `var`), named functions and the `get` and `set` keywords. These get asked about so often that we added a section to the docs called [Unsupported ECMAScript Features](../#unsupported). CoffeeScripts lack of equivalents for these features does not affect compatibility or interoperability with JavaScript modules or libraries.
## Future Compatibility
Back when CoffeeScript 1 was created, ES2015 JavaScript and transpilers like [Babel](http://babeljs.io/), [Bublé](https://buble.surge.sh/) or [Traceur Compiler](https://github.com/google/traceur-compiler) were several years away. The CoffeeScript compiler itself had to do what todays transpilers do, converting modern features like destructuring and arrow functions into equivalent lowest-common-denominator JavaScript.
But transpilers exist now, and they do their job well. With them around, theres no need for the CoffeeScript compiler to duplicate this functionality. All the CoffeeScript compiler needs to worry about now is converting the CoffeeScript version of new syntax into the JS version of that syntax, e.g. `"Hello, #{name}!"` into `` `Hello, ${name}!` ``. This makes adding support for new JavaScript features much easier than before.
Most features added by ECMA in recent years havent required any updates at all in CoffeeScript. New global objects, or new methods on global objects, dont require any updates on CoffeeScripts part to work. Some proposed future JS features _do_ involve new syntax, like [class fields](https://github.com/tc39/proposal-class-fields). We have adopted a policy of supporting new syntax only when it reaches Stage 4 in ECMAs process, which means that the syntax is final and will be in the next ES release. On occasion we might support a _feature_ before it has reached Stage 4, but output it using equivalent non-experimental syntax instead of the newly-proposed syntax; thats whats happening in 2.0.0 for [object destructuring](../#splats), where our output uses the same polyfill that Babel uses. When the new syntax is finalized, we will update our output to use the final syntax.
## Credits
The major features of 2.0.0 would not have been possible without the following people:
- [@GeoffreyBooth](https://github.com/GeoffreyBooth): Organizer of the CoffeeScript 2 effort, developer for modules; arrow functions, function default parameters and function rest parameters output using ES2015 syntax; line comments output and block comments output anywhere; block embedded JavaScript via triple backticks; improved parsing of Literate CoffeeScript; and the new docs website.
- [@connec](https://github.com/connec): Classes; destructuring; splats/rest syntax in arrays and function calls; and computed properties all output using ES2015 syntax.
- [@GabrielRatener](https://github.com/GabrielRatener): Async functions.
- [@xixixao](https://github.com/xixixao): JSX.
- [@zdenko](https://github.com/zdenko): Object rest/spread properties (object destructuring).
- [@greghuc](https://github.com/greghuc): Tagged template literals, interpolated strings output in ES2015 syntax.
- [@atg](https://github.com/atg): ES2015 `for…of`, supported as CoffeeScripts `for…from`.
- [@lydell](https://github.com/lydell) and [@jashkenas](https://github.com/jashkenas): Guidance, code reviews and feedback.
See the full [honor roll](https://github.com/jashkenas/coffeescript/wiki/CoffeeScript-2-Honor-Roll).
Thanks and we hope you enjoy CoffeeScript 2!

View File

@@ -9,13 +9,6 @@ Class constructors cant be invoked without `new`:
# Throws a TypeError at runtime
```
Derived (extended) class `constructor`s cannot use `this` before calling `super`:
```coffee
class B extends A
constructor: -> this # Throws a compiler error
```
ES2015 classes dont allow bound (fat arrow) methods. The CoffeeScript compiler goes through some contortions to preserve support for them, but one thing that cant be accommodated is calling a bound method before it is bound:
```coffee

View File

@@ -0,0 +1,20 @@
### `super` and `this`
In the constructor of a derived class (a class that `extends` another class), `this` cannot be used before calling `super`:
```coffee
class B extends A
constructor: -> this # Throws a compiler error
```
This also means you cannot pass a reference to `this` as an argument to `super` in the constructor of a derived class:
```coffee
class B extends A
constructor: (@arg) ->
super @arg # Throws a compiler error
```
This is a limitation of ES2015 classes. As a workaround, assign to `this` after the `super` call:
```
codeFor('breaking_change_super_this')
```

View File

@@ -1,5 +1,63 @@
## Changelog
```
releaseHeader('2017-11-26', '2.0.3', '2.0.2')
```
* Bugfix for `export default` followed by an implicit object that contains an explicit object, for example `exportedMember: { obj... }`.
* Bugfix for `key, val of obj` after an implicit object member, e.g. `foo: bar for key, val of obj`.
* Bugfix for combining array and object destructuring, e.g. `[ ..., {a, b} ] = arr`.
* Bugfix for an edge case where it was possible to create a bound (`=>`) generator function, which should throw an error as such functions arent allowed in ES2015.
* Bugfix for source maps: `.map` files should always have the same base filename as the requested output filename. So `coffee --map --output foo.js test.coffee` should generate `foo.js` and `foo.js.map`.
* Bugfix for incorrect source maps generated when using `--transpile` with `--map` for multiple input files.
* Bugfix for comments at the beginning or end of input into the REPL (`coffee --interactive`).
```
releaseHeader('2017-10-26', '2.0.2', '2.0.1')
```
* `--transpile` now also applies to `require`d or `import`ed CoffeeScript files.
* `--transpile` can be used with the REPL: `coffee --interactive --transpile`.
* Improvements to comments output that should now cover all of the [Flow comment-based syntax](https://flow.org/en/docs/types/comments/). Inline `###` comments near [variable](https://flow.org/en/docs/types/variables/) initial assignments are now output in the variable declaration statement, and `###` comments near a [class and method names](https://flow.org/en/docs/types/generics/) are now output where Flow expects them.
* Importing CoffeeScript keywords is now allowed, so long as theyre aliased: `import { and as andFn } from 'lib'`. (You could also do `import lib from 'lib'` and then reference `lib.and`.)
* Calls to functions named `get` and `set` no longer throw an error when given a bracketless object literal as an argument: `obj.set propertyName: propertyValue`.
* In the constructor of a derived class (a class that `extends` another class), you cannot call `super` with an argument that references `this`: `class Child extends Parent then constructor: (@arg) -> super(@arg)`. This isnt allowed in JavaScript, and now the CoffeeScript compiler will throw an error. Instead, assign to `this` after calling `super`: `(arg) -> super(arg); @arg = arg`.
* Bugfix for incorrect output when backticked statements and hoisted expressions were both in the same class body. This allows a backticked line like `` `field = 3` ``, for people using the experimental [class fields](https://github.com/tc39/proposal-class-fields) syntax, in the same class along with traditional class body expressions like `prop: 3` that CoffeeScript outputs as part of the class prototype.
* Bugfix for comments not output before a complex `?` operation, e.g. `@a ? b`.
* All tests now pass in Windows.
```
releaseHeader('2017-09-26', '2.0.1', '2.0.0')
```
* `babel-core` is no longer listed in `package.json`, even as an `optionalDependency`, to avoid it being automatically installed for most users. If you wish to use `--transpile`, simply install `babel-core` manually. See [Transpilation](#transpilation).
* `--transpile` now relies on Babel to find its options, i.e. the `.babelrc` file in the path of the file(s) being compiled. (Previously the CoffeeScript compiler was duplicating this logic, so nothing has changed from a users perspective.) This provides automatic support for additional ways to pass options to Babel in future versions, such as the `.babelrc.js` file coming in Babel 7.
* Backticked expressions in a class body, outside any class methods, are now output in the JavaScript class body itself. This allows for passing through experimental JavaScript syntax like the [class fields proposal](https://github.com/tc39/proposal-class-fields), assuming your [transpiler supports it](https://babeljs.io/docs/plugins/transform-class-properties/).
```
releaseHeader('2017-09-18', '2.0.0', '2.0.0-beta5')
```
* Added `--transpile` flag or `transpile` Node API option to tell the CoffeeScript compiler to pipe its output through Babel before saving or returning it; see [Transpilation](#transpilation). Also changed the `-t` short flag to refer to `--transpile` instead of `--tokens`.
* Always populate source maps `sourcesContent` property.
* Bugfixes for destructuring and for comments in JSX.
* _Note that these are only the changes between 2.0.0-beta5 and 2.0.0. See below for all changes since 1.x._
```
releaseHeader('2017-09-02', '2.0.0-beta5', '2.0.0-beta4')
```
* Node 6 is now supported, and we will try to maintain that as the minimum required version for CoffeeScript 2 via the `coffee` command or Node API. Older versions of Node, or non-evergreen browsers, can compile via the [browser compiler](./browser-compiler/coffeescript.js).
* The command line `--output` flag now allows you to specify an output filename, not just an output folder.
* The command line `--require` flag now properly handles filenames or module names that are invalid identifiers (like an NPM module with a hyphen in the name).
* `Object.assign`, output when object destructuring is used, is polyfilled using the same polyfill that Babel outputs. This means that polyfills shouldnt be required unless support for Internet Explorer 8 or below is desired (or your own code uses a feature that requires a polyfill). See [ES2015+ Output](#es2015plus-output).
* A string or JSX interpolation that contains only a comment (`"a#{### comment ###}b"` or `<div>{### comment ###}</div>`) is now output (`` `a${/* comment */}b` ``)
* Interpolated strings (ES2015 template literals) that contain quotation marks no longer have the quotation marks escaped: `` `say "${message}"` ``
* It is now possible to chain after a function literal (for example, to define a function and then call `.call` on it).
* The results of the async tests are included in the output when you run `cake test`.
* Bugfixes for object destructuring; expansions in function parameters; generated reference variables in function parameters; chained functions after `do`; splats after existential operator soaks in arrays (`[a?.b...]`); trailing `if` with splat in arrays or function parameters (`[a if b...]`); attempting to `throw` an `if`, `for`, `switch`, `while` or other invalid construct.
* Bugfixes for syntactical edge cases: semicolons after `=` and other “mid-expression” tokens; spaces after `::`; and scripts that begin with `:` or `*`.
* Bugfixes for source maps generated via the Node API; and stack trace line numbers when compiling CoffeeScript via the Node API from within a `.coffee` file.
```
releaseHeader('2017-08-03', '2.0.0-beta4', '2.0.0-beta3')
```
@@ -159,7 +217,6 @@ releaseHeader('2016-09-24', '1.11.0', '1.10.0')
* CoffeeScript now supports ES2015 [`import` and `export` syntax](#modules).
* 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:
```
@@ -170,7 +227,6 @@ releaseHeader('2016-09-24', '1.11.0', '1.10.0')
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.
* `&&=`, `||=`, `and=` and `or=` no longer accidentally allow a space before the equals sign.
* Improved several error messages.
@@ -178,7 +234,6 @@ releaseHeader('2016-09-24', '1.11.0', '1.10.0')
* 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.
@@ -194,7 +249,6 @@ releaseHeader('2015-09-03', '1.10.0', '1.9.3')
* 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.
* An error in io.js where strict mode is set on internal modules.

View File

@@ -1,17 +1 @@
## CoffeeScript 2
### Whats New In CoffeeScript 2?
The biggest change in CoffeeScript 2 is that now the CoffeeScript compiler produces modern, ES2015+ JavaScript. A CoffeeScript `=>` becomes an ES `=>`, a CoffeeScript `class` becomes an ES `class` and so on. With the exception of [modules](#modules) (`import` and `export` statements) and [JSX](#jsx), all the ES2015+ features that CoffeeScript supports can run natively in Node 7.6+, meaning that Node can run CoffeeScripts output without any further processing required. You can [run the tests in your browser](http://coffeescript.org/v<%= majorVersion %>/test.html) to see if your browser can do the same; Chrome has supported all features since version 55.
Support for ES2015+ syntax is important to ensure compatibility with frameworks that assume ES2015. Now that CoffeeScript compiles classes to the ES `class` keyword, its possible to `extend` an ES class; that wasnt possible in CoffeeScript 1. Parity in how language features work is also important on its own; CoffeeScript “is just JavaScript,” and so things like [function parameter default values](#breaking-changes-default-values) should behave the same in CoffeeScript as in JavaScript.
Many ES2015+ features have been backported to CoffeeScript 1.11 and 1.12, including [modules](#modules), [`for…of`](#generator-iteration), and [tagged template literals](#tagged-template-literals). Major new features unique to CoffeeScript 2 are support for ES2017s [async functions](#async-functions) and for [JSX](#jsx). More details are in the [changelog](#changelog).
There are very few [breaking changes from CoffeeScript 1.x to 2](#breaking-changes); we hope the upgrade process is smooth for most projects.
### Why CoffeeScript When Theres ES2015?
CoffeeScript introduced many new features to the JavaScript world, such as [`=>`](#fat-arrow) and [destructuring](#destructuring) and [classes](#classes). We are happy that ECMA has seen their utility and adopted them into ECMAScript.
CoffeeScripts intent, however, was never to be a superset of JavaScript. One of the guiding principles of CoffeeScript has been _simplicity:_ not just removing JavaScripts “bad parts,” but providing an elegant, concise syntax that eschews unnecessary punctuation whenever possible, to make code easier to read and reason about. This benefit of CoffeeScript remains, even in an ES2015 world.

View File

@@ -5,6 +5,7 @@ Once installed, you should have access to the `coffee` command, which can execut
| Option | Description |
| --- | --- |
| `-c, --compile` | Compile a `.coffee` script into a `.js` JavaScript file of the same name. |
| `-t, --transpile` | Pipe the CoffeeScript compilers output through Babel before saving or running the generated JavaScript. Requires `babel-core` to be installed, and options to pass to Babel in a `.babelrc` file or a `package.json` with a `babel` key in the path of the file or folder to be compiled. See [Transpilation](#transpilation).
| `-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` | Launch an interactive CoffeeScript session to try short snippets. Identical to calling `coffee` with no arguments. |
@@ -16,10 +17,10 @@ Once installed, you should have access to the `coffee` command, which can execut
| `-e, --eval` | Compile and print a little snippet of CoffeeScript directly from the command line. For example:<br>`coffee -e "console.log num for num in [10..1]"` |
| `-r, --require [MODULE]`&emsp; | `require()` the given module before starting the REPL or evaluating the code given with the `--eval` flag. |
| `-b, --bare` | Compile the JavaScript without the [top-level function safety wrapper](#lexical-scope). |
| `-t, --tokens` | 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. 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. |
| `--no-header` | Suppress the “Generated by CoffeeScript” header. |
| `--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. |
| `--tokens` | 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. Used for debugging the compiler. |
#### Examples:
@@ -35,3 +36,5 @@ Once installed, you should have access to the `coffee` command, which can execut
`coffee -o lib/ -cw src/`
* Start the CoffeeScript REPL (`Ctrl-D` to exit, `Ctrl-V`for multi-line):<br>
`coffee`
To use `--transpile`, see [Transpilation](#transpilation).

View File

@@ -0,0 +1,5 @@
### Compatibility
With the exception of [modules](#modules) (`import` and `export` statements) and [JSX](#jsx), all the modern JavaScript features that CoffeeScript supports can run natively in Node 7.6+, meaning that Node can run CoffeeScripts output without any further processing required. You can [run the tests in your browser](test.html) to see if your browser can do the same. For older browsers or older versions of Node, however, [transpilation](#transpilation) is required.
Support for modern JavaScript syntax is important to ensure compatibility with frameworks that assume modern features. Now that CoffeeScript compiles classes to the `class` keyword, its possible to `extend` a JavaScript class; that wasnt possible in CoffeeScript 1. Parity in how language features work is also important on its own; CoffeeScript “is just JavaScript,” and so things like [function parameter default values](#breaking-changes-default-values) should behave the same in CoffeeScript as in JavaScript. Some such features behave slightly differently in JavaScript than they did in CoffeeScript 1; in such cases we are conforming with the JavaScript spec, and weve documented the differences as [breaking changes](#breaking-changes).

View File

@@ -1,8 +1,8 @@
## Contributing
Contributions are welcome! Feel free to fork [the repo](http://github.com/jashkenas/coffeescript) and submit a pull request.
Contributions are welcome! Feel free to fork [the repo](https://github.com/jashkenas/coffeescript) and submit a pull request.
[Some features of ECMAScript are intentionally unsupported](#unsupported). Please review both the open and closed [issues on GitHub](http://github.com/jashkenas/coffeescript/issues) to see if the feature youre looking for has already been discussed. As a general rule, we dont support ECMAScript syntax for features that arent yet finalized (at Stage 4 in the proposal approval process).
[Some features of ECMAScript are intentionally unsupported](#unsupported). Please review both the open and closed [issues on GitHub](https://github.com/jashkenas/coffeescript/issues) to see if the feature youre looking for has already been discussed. As a general rule, we dont support ECMAScript syntax for features that arent yet finalized (at Stage 4 in the proposal approval process).
For more resources on adding to CoffeeScript, please see [the Wiki](https://github.com/jashkenas/coffeescript/wiki/%5BHowto%5D-Hacking-on-the-CoffeeScript-Compiler), especially [How The Parser Works](https://github.com/jashkenas/coffeescript/wiki/%5BHowTo%5D-How-parsing-works).

View File

@@ -1,13 +0,0 @@
### ES2015+ Output
CoffeeScript 2 outputs the latest ES2015+ syntax. If youre looking for a single tool that takes CoffeeScript input and generates JavaScript output that runs in any JavaScript runtime, assuming you opt out of certain newer features, stick to [CoffeeScript 1.x](/v1/). CoffeeScript 2 [breaks compatibility](#breaking-changes) with certain CoffeeScript 1.x features in order to conform with the ES2015+ specifications, and generate more idiomatic output (a CoffeeScript `=>` becomes an ES `=>`; a CoffeeScript `class` becomes an ES `class`; and so on).
Since the CoffeeScript 2 compiler outputs ES2015+ syntax, it is your responsibility to either ensure that your target JavaScript runtime(s) support all these features, or that you pass the output through another transpiler like [Babel](http://babeljs.io/), [Rollup](https://github.com/rollup/rollup) or [Traceur Compiler](https://github.com/google/traceur-compiler). In general, [CoffeeScript 2s output is supported as is by Node.js 7.6+](http://node.green/), except for modules and JSX which require transpilation.
There are many great task runners for setting up JavaScript build chains, such as [Gulp](http://gulpjs.com/), [Webpack](https://webpack.github.io/), [Grunt](https://gruntjs.com/) and [Broccoli](http://broccolijs.com/). If youre looking for a very minimal solution to get started, you can use [babel-preset-env](https://babeljs.io/docs/plugins/preset-env/) and the command line:
```bash
npm install --global coffeescript@next
npm install --save-dev coffeescript@next babel-cli babel-preset-env
coffee --print *.coffee | babel --presets env > app.js
```

View File

@@ -1,19 +1,21 @@
## Installation
The command-line version of `coffee` is available as a [Node.js](https://nodejs.org/) utility. The [core compiler](/v<%= majorVersion %>/browser-compiler/coffeescript.js) however, does not depend on Node, and can be run in any JavaScript environment, or in the browser (see [Try CoffeeScript](#try)).
The command-line version of `coffee` is available as a [Node.js](https://nodejs.org/) utility, requiring Node 6 or later. The [core compiler](/v<%= majorVersion %>/browser-compiler/coffeescript.js) however, does not depend on Node, and can be run in any JavaScript environment, or in the browser (see [Try CoffeeScript](#try)).
To install, first make sure you have a working copy of the latest stable version of [Node.js](https://nodejs.org/). You can then install CoffeeScript globally with [npm](https://www.npmjs.com/):
```bash
npm install --global coffeescript@next
npm install --global coffeescript
```
This will make the `coffee` and `cake` commands available globally.
When you need CoffeeScript as a dependency of a project, within that projects folder you can install it locally:
If you are using CoffeeScript in a project, you should install it locally for that project so that the version of CoffeeScript is tracked as one of your projects dependencies. Within that projects folder:
```bash
npm install --save coffeescript@next
npm install --save-dev coffeescript
```
The `coffee` and `cake` commands will first look in the current folder to see if CoffeeScript is installed locally, and use that version if so. This allows different versions of CoffeeScript to be installed globally and locally.
If you plan to use the `--transpile` option (see [Transpilation](#transpilation)) you will need to also install `babel-core` either globally or locally, depending on whether you are running a globally or locally installed version of CoffeeScript.

View File

@@ -5,5 +5,9 @@ The golden rule of CoffeeScript is: _“Its just JavaScript.”_ The code com
**Latest Version:** [<%= fullVersion %>](https://github.com/jashkenas/coffeescript/tarball/<%= fullVersion %>)
```bash
npm install -g coffeescript@next
# Install locally for a project:
npm install --save-dev coffeescript
# Install globally to execute .coffee files anywhere:
npm install --global coffeescript
```

View File

@@ -20,6 +20,7 @@ The `compile` method has the signature `compile(code, options)` where `code` is
* `options.sourceMap`, boolean: if true, a source map will be generated; and instead of returning a string, `compile` will return an object of the form `{js, v3SourceMap, sourceMap}`.
* `options.inlineMap`, boolean: if true, output the source map as a base64-encoded string in a comment at the bottom.
* `options.filename`, string: the filename to use for the source map.
* `options.filename`, string: the filename to use for the source map. It can include a path (relative or absolute).
* `options.bare`, boolean: if true, output without the [top-level function safety wrapper](#lexical-scope).
* `options.header`, boolean: if true, output the `Generated by CoffeeScript` header.
* `options.transpile`, **object**: if set, this must be an object with the [options to pass to Babel](http://babeljs.io/docs/usage/api/#options). See [Transpilation](#transpilation).

View File

@@ -1,6 +1,6 @@
## Overview
_CoffeeScript on the <span class="hidden-md-up">top</span><span class="hidden-sm-down">left</span>, compiled JavaScript output on the <span class="hidden-md-up">bottom</span><span class="hidden-sm-down">right</span>. The CoffeeScript is editable!_
_CoffeeScript on the <span class="d-md-none">top</span><span class="d-none d-md-inline">left</span>, compiled JavaScript output on the <span class="d-md-none">bottom</span><span class="d-none d-md-inline">right</span>. The CoffeeScript is editable!_
```
codeFor('overview', 'cubes', false)

View File

@@ -11,5 +11,5 @@
Perhaps your CoffeeScript-related question has been asked before. Check the FAQ first.
* [JS2Coffee](http://js2.coffee/)<br>
Is a very well done reverse JavaScript-to-CoffeeScript compiler. Its not going to be perfect (infer what your JavaScript classes are, when you need bound functions, and so on…) — but its a great starting point for converting simple scripts.
* [High-Rez Logo](https://github.com/jashkenas/coffeescript/tree/master/documentation/images)<br>
* [High-Rez Logo](https://github.com/jashkenas/coffeescript/tree/master/documentation/site)<br>
The CoffeeScript logo is available in SVG for use in presentations.

View File

@@ -2,6 +2,4 @@
While its 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](/v<%= majorVersion %>/browser-compiler/coffeescript.js)) as `docs/v<%= majorVersion %>/browser-compiler/coffeescript.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](#try), as well as the code examples and other interactive parts of this site, 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 your JavaScript console 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.

View File

@@ -4,4 +4,4 @@ CoffeeScript includes an extensive test suite, which verifies that the compiler
Note that since no JavaScript runtime yet supports ES2015 modules, the tests for module support verify only that the CoffeeScript compilers output is the correct syntax; the tests dont verify that the modules resolve properly.
[Run the tests in your browser.](http://coffeescript.org/v<%= majorVersion %>/test.html)
[Run the tests in your browser.](test.html)

View File

@@ -0,0 +1,49 @@
### Transpilation
CoffeeScript 2 generates JavaScript that uses the latest, modern syntax. The runtime or browsers where you want your code to run [might not support all of that syntax](#compatibility). In that case, we want to convert modern JavaScript into older JavaScript that will run in older versions of Node or older browsers; for example, `{ a } = obj` into `a = obj.a`. This is done via transpilers like [Babel](http://babeljs.io/), [Bublé](https://buble.surge.sh/) or [Traceur Compiler](https://github.com/google/traceur-compiler).
#### Quickstart
From the root of your project:
```bash
npm install --save-dev babel-core babel-preset-env
echo '{ "presets": ["env"] }' > .babelrc
coffee --compile --transpile --inline-map some-file.coffee
```
#### Transpiling with the CoffeeScript compiler
To make things easy, CoffeeScript has built-in support for the popular [Babel](http://babeljs.io/) transpiler. You can use it via the `--transpile` command-line option or the `transpile` Node API option. To use either, `babel-core` must be installed in your project:
```bash
npm install --save-dev babel-core
```
Or if youre running the `coffee` command outside of a project folder, using a globally-installed `coffeescript` module, `babel-core` needs to be installed globally:
```bash
npm install --global babel-core
```
By default, Babel doesnt do anything—it doesnt make assumptions about what you want to transpile to. You need to provide it with a configuration so that it knows what to do. One way to do this is by creating a [`.babelrc` file](https://babeljs.io/docs/usage/babelrc/) in the folder containing the files youre compiling, or in any parent folder up the path above those files. (Babel supports [other ways](https://babeljs.io/docs/usage/babelrc/), too.) A minimal `.babelrc` file would be just `{ "presets": ["env"] }`. This implies that you have installed [`babel-preset-env`](https://babeljs.io/docs/plugins/preset-env/):
```bash
npm install --save-dev babel-preset-env # Or --global for non-project-based usage
```
See [Babels website to learn about presets and plugins](https://babeljs.io/docs/plugins/) and the multitude of options you have. Another preset you might need is [`transform-react-jsx`](https://babeljs.io/docs/plugins/transform-react-jsx/) if youre using JSX with React (JSX can also be used with other frameworks).
Once you have `babel-core` and `babel-preset-env` (or other presets or plugins) installed, and a `.babelrc` file (or other equivalent) in place, you can use `coffee --transpile` to pipe CoffeeScripts output through Babel using the options youve saved.
If youre using CoffeeScript via the [Node API](nodejs_usage), where you call `CoffeeScript.compile` with a string to be compiled and an `options` object, the `transpile` key of the `options` object should be the Babel options:
```js
CoffeeScript.compile(code, {transpile: {presets: ['env']}})
```
You can also transpile CoffeeScripts output without using the `transpile` option, for example as part of a build chain. This lets you use transpilers other than Babel, and it gives you greater control over the process. There are many great task runners for setting up JavaScript build chains, such as [Gulp](http://gulpjs.com/), [Webpack](https://webpack.github.io/), [Grunt](https://gruntjs.com/) and [Broccoli](http://broccolijs.com/).
#### Polyfills
Note that transpiling doesnt automatically supply [polyfills](https://developer.mozilla.org/en-US/docs/Glossary/Polyfill) for your code. CoffeeScript itself will output [`Array.indexOf`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf) if you use the `in` operator, or destructuring or spread/rest syntax; and [`Function.bind`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind) if you use a bound (`=>`) method in a class. Both are supported in Internet Explorer 9+ and all more recent browsers, but you will need to supply polyfills if you need to support Internet Explorer 8 or below and are using features that would cause these methods to be output. Youll also need to supply polyfills if your own code uses these methods or another method added in recent versions of JavaScript. One polyfill option is [`babel-polyfill`](https://babeljs.io/docs/usage/polyfill/), though there are many [other](https://hackernoon.com/polyfills-everything-you-ever-wanted-to-know-or-maybe-a-bit-less-7c8de164e423) [strategies](https://philipwalton.com/articles/loading-polyfills-only-when-needed/).

View File

@@ -2,4 +2,4 @@
Newcomers to CoffeeScript often wonder how to generate the JavaScript `function foo() {}`, as opposed to the `foo = function() {}` that CoffeeScript produces. The first form is a [function declaration](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function), and the second is a [function expression](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/function). As stated above, in CoffeeScript [everything is an expression](#expressions), so naturally we favor the expression form. Supporting only one variant helps avoid confusing bugs that can arise from the [subtle differences between the two forms](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function#Function_declaration_hoisting).
Technically, `foo = function() {}` is creating an anonymous function that gets assigned to a variable named `foo`. Some very early versions of CoffeeScript named this function, e.g. `foo = function foo() {}`, but this was dropped because of compatibility issues with Internet Explorer. For a while this annoyed people, as these functions would be unnamed in stack traces; but modern JavaScript runtimes [infer the names of such anonymous functions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/name) from the names of the variables to which theyre assigned. Given that this is the case, and given that not all functions in function expressions can be named (for example, the functions in `first.fn = ->; second.fn = ->` cant both be named `fn`) its simplest to just preserve the current behavior.
Technically, `foo = function() {}` is creating an anonymous function that gets assigned to a variable named `foo`. Some very early versions of CoffeeScript named this function, e.g. `foo = function foo() {}`, but this was dropped because of compatibility issues with Internet Explorer. For a while this annoyed people, as these functions would be unnamed in stack traces; but modern JavaScript runtimes [infer the names of such anonymous functions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/name) from the names of the variables to which theyre assigned. Given that this is the case, its simplest to just preserve the current behavior.

View File

@@ -0,0 +1,5 @@
### Whats New In CoffeeScript 2?
The biggest change in CoffeeScript 2 is that now the CoffeeScript compiler produces modern JavaScript syntax (ES6, or ES2015 and later). A CoffeeScript `=>` becomes a JS `=>`, a CoffeeScript `class` becomes a JS `class` and so on. Major new features in CoffeeScript 2 include [async functions](#async-functions) and [JSX](#jsx). You can read more in the [announcement](announcing-coffeescript-2/).
There are very few [breaking changes from CoffeeScript 1.x to 2](#breaking-changes); we hope the upgrade process is smooth for most projects.

View File

@@ -3,22 +3,28 @@
<%= include('try.html') %>
<div class="container-fluid" id="top">
<div class="row row-offcanvas row-offcanvas-left">
<nav class="sidebar sidebar-offcanvas col-xs-12 col-lg-3 bg-ribbed-light">
<div class="row flex-nowrap">
<nav class="sidebar col-lg-3 bg-ribbed-light">
<%= include('sidebar.html') %>
</nav>
<main class="main col-xs-12 col-lg-9 offset-lg-3">
<header class="title-logo hidden-md-down">
<%= include('documentation/images/logo.svg') %>
<main class="main col-lg-9 ml-auto">
<header class="d-none d-lg-block">
<p class="title-logo">
<%= include('logo.svg') %>
</p>
</header>
<section id="overview">
<%= htmlFor('introduction') %>
<%= htmlFor('overview') %>
</section>
<section id="coffeescript-2">
<%= htmlFor('coffeescript_2') %>
<section id="whats-new-in-coffeescript-2">
<%= htmlFor('whats_new_in_coffeescript_2') %>
</section>
<section id="compatibility">
<%= htmlFor('compatibility') %>
</section>
</section>
<section id="installation">
<%= htmlFor('installation') %>
@@ -28,12 +34,12 @@
<section id="cli">
<%= htmlFor('command_line_interface') %>
</section>
<section id="es2015plus-output">
<%= htmlFor('es2015plus_output') %>
</section>
<section id="nodejs-usage">
<%= htmlFor('nodejs_usage') %>
</section>
<section id="transpilation">
<%= htmlFor('transpilation') %>
</section>
</section>
<section id="language">
<%= htmlFor('language') %>
@@ -181,6 +187,9 @@
<section id="breaking-changes-classes">
<%= htmlFor('breaking_changes_classes') %>
</section>
<section id="breaking-changes-super-this">
<%= htmlFor('breaking_changes_super_this') %>
</section>
<section id="breaking-changes-super-extends">
<%= htmlFor('breaking_changes_super_extends') %>
</section>
@@ -197,7 +206,6 @@
<section id="changelog">
<%= htmlFor('changelog') %>
</section>
</main>
</div>
</div>

View File

@@ -0,0 +1,47 @@
fs = require 'fs'
_ = require 'underscore'
# Use CodeMirror in Node for syntax highlighting, per
# https://github.com/codemirror/CodeMirror/blob/master/bin/source-highlight
CodeMirror = require 'codemirror/addon/runmode/runmode.node.js'
require 'codemirror/mode/coffeescript/coffeescript.js'
require 'codemirror/mode/javascript/javascript.js'
CoffeeScript = require '../../lib/coffeescript'
module.exports = ->
(file, run = no) ->
cs = fs.readFileSync "documentation/examples/#{file}.coffee", 'utf-8'
js = CoffeeScript.compile cs, bare: yes # This is just the initial JavaScript output; it is replaced by dynamic compilation on changes of the CoffeeScript pane.
render = _.template fs.readFileSync('documentation/site/code.html', 'utf-8')
include = (file) -> fs.readFileSync("documentation/site/#{file}", 'utf-8')
highlight = (language, code) ->
# Adapted from https://github.com/codemirror/CodeMirror/blob/master/bin/source-highlight.
html = ''
curStyle = null
accum = ''
esc = (str) ->
str.replace /[<&]/g, (ch) ->
if ch is '&' then '&amp;' else '&lt;'
flush = ->
if curStyle
html += "<span class=\"#{curStyle.replace /(^|\s+)/g, '$1cm-'}\">#{esc accum}</span>"
else
html += esc accum
CodeMirror.runMode code, {name: language}, (text, style) ->
if style isnt curStyle
flush()
curStyle = style
accum = text
else
accum += text
flush()
html
output = render {file, cs, js, highlight, include, run}

View File

@@ -1,41 +1,72 @@
/* Adapted from https://github.com/FarhadG/code-mirror-themes/blob/master/themes/twilight.css */
.cm-s-twilight {
.CodeMirror,
.placeholder-code {
letter-spacing: 0.3px;
color: #f8f8f8;
/* Prevent mobile Safari from zooming in on our code editors; the code is 16px naturally, but somehow being explicit about it prevents the zooming */
font-size: 16px;
}
.cm-s-twilight .CodeMirror-lines {
@media (min-width: 768px) {
.CodeMirror,
.placeholder-code {
font-size: 90%; /* Matching Bootstraps font size for code, which calculates to 14.4px */
}
}
.CodeMirror-lines {
padding: 0.5em 0;
}
.cm-s-twilight div.CodeMirror-cursor {
.placeholder-code {
padding: 0.5em 4px;
margin-bottom: 1.37em;
white-space: pre-wrap;
}
div.CodeMirror-cursor {
border-left: 3px solid #f8f8f8;
}
.cm-s-twilight .CodeMirror-activeline-background {
.CodeMirror-activeline-background {
background: #ffffff08;
}
.cm-s-twilight .CodeMirror-selected {
.CodeMirror-selected {
background: #ddf0ff33;
}
.cm-s-twilight .cm-comment {
.cm-comment,
.placeholder-code .comment {
font-style: italic;
color: #5f5a60;
}
.cm-s-twilight .cm-keyword {
.cm-keyword,
.placeholder-code .keyword {
color: #cda869;
}
.cm-s-twilight .cm-string {
.cm-string,
.placeholder-code .string {
color: #8f9d6a;
}
.cm-s-twilight .cm-property {
.cm-property,
.placeholder-code .attribute {
color: #dad085;
}
.cm-s-twilight .cm-atom {
.cm-atom {
color: #dad085;
}
.cm-s-twilight .cm-number {
.cm-number,
.placeholder-code .number,
.placeholder-code .built_in,
.placeholder-code .builtin-name,
.placeholder-code .literal,
.placeholder-code .type,
/*.placeholder-code .params,*/
.placeholder-code .meta,
.placeholder-code .link {
color: #dad085;
}
.cm-s-twilight .cm-operator {
.cm-operator,
.placeholder-code .punctuation,
.placeholder-code .symbol,
.placeholder-code .bullet,
.placeholder-code .addition,
.placeholder-code .operator {
color: #cda869;
}

View File

@@ -2,15 +2,17 @@
<div class="row">
<div class="col-md-6 coffeescript-input-column">
<textarea class="coffeescript-input" id="<%= file %>-coffee"><%= cs %></textarea>
<pre class="placeholder-code"><%= highlight('coffeescript', cs) %></pre>
</div>
<div class="col-md-6 javascript-output-column">
<textarea class="javascript-output" id="<%= file %>-js"><%= js %></textarea>
<pre class="placeholder-code"><%= highlight('javascript', js) %></pre>
</div>
</div>
<% if (run) { %>
<div class="row">
<div class="col-xs-12 text-xs-right">
<button type="button" class="btn btn-primary" data-action="run-code-example" data-example="<%= file %>" data-run="<%= escape(run) %>"><% if (run === true) { %>▶<% } else { %><small></small>&ensp;<%= run.replace(/"/g, '&quot;') %><% } %></button>
<div class="col text-right">
<button type="button" class="btn btn-primary" data-action="run-code-example" data-example="<%= file %>" data-run="<%= escape(run) %>"><small><%= include('play.svg') %></small><%= run === true ? '' : run.replace(/"/g, '&quot;') %></button>
</div>
</div>
<% } %>

View File

@@ -0,0 +1,193 @@
unless window.location.origin # Polyfill `location.origin` for IE < 11
window.location.origin = "#{window.location.protocol}//#{window.location.hostname}"
$(document).ready ->
# Mobile navigation
toggleSidebar = ->
$('.navbar-toggler, .sidebar').toggleClass 'show'
$('[data-toggle="offcanvas"]').click toggleSidebar
$('[data-action="sidebar-nav"]').click (event) ->
if $('.navbar-toggler').is(':visible')
event.preventDefault()
toggleSidebar()
setTimeout ->
window.location = event.target.href
, 260 # Wait for the sidebar to slide away before navigating
gtag 'event', 'sidebar_navigate',
event_category: 'navigation'
event_label: event.target.href.replace window.location.origin, ''
# Initialize Scrollspy for sidebar navigation; https://getbootstrap.com/docs/4.0/components/scrollspy/
# See also http://www.codingeverything.com/2014/02/BootstrapDocsSideBar.html and http://jsfiddle.net/KyleMit/v6zhz/
$('body').scrollspy
target: '#contents'
offset: Math.round $('main').css('padding-top').replace('px', '')
initializeScrollspyFromHash = (hash) ->
$("#contents a.active[href!='#{hash}']").removeClass 'show'
$(window).on 'activate.bs.scrollspy', (event, target) -> # Why `window`? https://github.com/twbs/bootstrap/issues/20086
# We only want one active link in the nav
$("#contents a.active[href!='#{target.relatedTarget}']").removeClass 'show'
$target = $("#contents a[href='#{target.relatedTarget}']")
return if $target.prop('href') is "#{window.location.origin}/#try"
# Update the browser address bar on scroll, without adding to the history; clicking the sidebar links will automatically add to the history
replaceState $target.prop('href')
# Track this as a new pageview; we only want '/#hash', not 'http://coffeescript.org/#hash'
gtag 'config', GA_TRACKING_ID,
page_path: $target.prop('href').replace window.location.origin, ''
# Initialize CodeMirror for code examples; https://codemirror.net/doc/manual.html
# Defer this until a code example is clicked or focused, to avoid unnecessary computation/slowness
textareas = []
editors = []
lastCompilationElapsedTime = 200
$('textarea').each (index) ->
textareas[index] = @
$(@).data 'index', index
initializeEditor = ($textarea) ->
index = $textarea.data 'index'
mode = if $textarea.hasClass('javascript-output') then 'javascript' else 'coffeescript'
editors[index] = editor = CodeMirror.fromTextArea $textarea[0],
mode: mode
theme: 'twilight'
indentUnit: 2
tabSize: 2
lineWrapping: on
lineNumbers: off
inputStyle: 'contenteditable'
readOnly: mode isnt 'coffeescript' # Cant use 'nocursor' if we want the JavaScript to be copyable
viewportMargin: Infinity
# Whenever the user edits the CoffeeScript side of a code example, update the JavaScript output
# If the editor is Try CoffeeScript, also update the hash and save this code in localStorage
if mode is 'coffeescript'
pending = null
editor.on 'change', (instance, change) ->
clearTimeout pending
pending = setTimeout ->
lastCompilationStartTime = Date.now()
try
coffee = editor.getValue()
if index is 0 and $('#try').hasClass('show') # If this is the editor in Try CoffeeScript and its still visible
if $('#try').hasClass('show')
# Update the hash with the current code
link = "try:#{encodeURIComponent coffee}"
replaceState "#{window.location.href.split('#')[0]}##{link}"
# Save this to the users localStorage
try
if window.localStorage?
window.localStorage.setItem 'tryCoffeeScriptCode', coffee
catch exception
output = CoffeeScript.compile coffee, bare: yes
lastCompilationElapsedTime = Math.max(200, Date.now() - lastCompilationStartTime)
catch exception
output = "#{exception}"
editors[index + 1].setValue output
gtag 'event', 'edit_code',
event_category: 'engagement'
event_label: $textarea.closest('[data-example]').data('example')
, lastCompilationElapsedTime
# Fix the code editors handling of tab-indented code
editor.addKeyMap
'Tab': (cm) ->
if cm.somethingSelected()
cm.indentSelection 'add'
else if /^\t/m.test cm.getValue()
# If any lines start with a tab, treat this as tab-indented code
cm.execCommand 'insertTab'
else
cm.execCommand 'insertSoftTab'
'Shift-Tab': (cm) ->
cm.indentSelection 'subtract'
'Enter': (cm) ->
cm.options.indentWithTabs = /^\t/m.test cm.getValue()
cm.execCommand 'newlineAndIndent'
$('.placeholder-code').one 'mouseover', (event) ->
$textarea = $(@).prev 'textarea'
$(@).remove()
initializeEditor $textarea
# Initialize the sibling column too
$siblingColumn = $ $textarea.parent().siblings()[0]
$siblingColumn.children('.placeholder-code').remove()
initializeEditor $ $siblingColumn.children('textarea')[0]
initializeTryEditors = ->
initializeEditor $ '#try-coffeescript-coffee'
initializeEditor $ '#try-coffeescript-js'
# Handle the code example buttons
$('[data-action="run-code-example"]').click ->
run = $(@).data 'run'
index = $("##{$(@).data('example')}-js").data 'index'
js = if editors[index]?
editors[index].getValue()
else
$(textareas[index]).val()
js = "#{js}\nalert(#{unescape run});" unless run is yes
eval js
gtag 'event', 'run_code',
event_category: 'engagement'
event_label: $(@).closest('[data-example]').data('example')
# Try CoffeeScript
previousHash = null
toggleTry = (checkLocalStorage) ->
$('#try, #try-link').toggleClass 'show'
if $('#try').hasClass('show')
previousHash = window.location.hash if window.location.hash
initializeTryEditors() if $('#try .CodeMirror').length is 0
if checkLocalStorage and window.localStorage?
try
coffee = window.localStorage.getItem 'tryCoffeeScriptCode'
if coffee?
editors[0].setValue coffee
else
replaceState '#try'
catch exception
replaceState '#try'
else
replaceState '#try'
else
if previousHash then replaceState(previousHash) else clearHash()
closeTry = ->
$('#try, #try-link').removeClass 'show'
if previousHash then replaceState(previousHash) else clearHash()
$('[data-toggle="try"]').click (event) ->
event.preventDefault()
toggleTry yes
$('[data-close="try"]').click closeTry
clearHash = ->
window.history.replaceState {}, document.title, window.location.pathname
replaceState = (newURL) ->
newURL = "#{window.location.pathname}#{newURL}" if newURL?.indexOf('#') is 0
window.history.replaceState {}, document.title, (newURL or '')
$(window).on 'hashchange', ->
# Get rid of dangling # in the address bar
clearHash() if window.location.hash is ''
# Configure the initial state
if window.location.hash?
if window.location.hash is '#try'
toggleTry yes
else if window.location.hash.indexOf('#try') is 0
initializeTryEditors() if $('#try .CodeMirror').length is 0
editors[0].setValue decodeURIComponent window.location.hash[5..]
toggleTry no
else if window.location.hash is ''
clearHash()
else
initializeScrollspyFromHash window.location.hash
if window.location.hash.length > 1
# Initializing the code editors mightve thrown off our vertical scroll position
document.getElementById(window.location.hash.slice(1).replace(/try:.*/, '')).scrollIntoView()

View File

@@ -1,5 +1,3 @@
/* Adapted from https://v4-alpha.getbootstrap.com/examples/dashboard/dashboard.css and http://v4-alpha.getbootstrap.com/examples/offcanvas/offcanvas.css */
html,
body {
/* Prevent scroll on narrow devices */
@@ -27,7 +25,12 @@ a:focus, a:hover, a:active {
text-decoration: none;
}
.bg-inverse {
button:focus, .navbar-dark .navbar-toggler:focus {
outline: none;
border: thin solid rgba(248, 243, 240, 0.3);
}
.bg-dark {
background-color: #3e2723 !important;
}
@@ -44,92 +47,35 @@ a:focus, a:hover, a:active {
/*
* Header
*/
.navbar-fixed-top {
.site-navbar {
height: 3.5rem;
font-family: 'Lato';
font-weight: 400;
font-size: 1.1em;
}
.navbar-brand {
height: 2em;
margin-right: 2em;
height: 2.2em;
margin-right: 1em;
}
.navbar-dark path {
fill: #fff;
}
.navbar-nav {
font-family: Lato;
font-weight: 400;
font-size: 1.1em;
}
.navbar-nav .nav-link {
padding-left: 0.6em;
padding-right: 0.6em;
.navbar-nav .nav-item {
margin-left: 0.6em;
margin-right: 0.6em;
border-radius: 0.4em;
}
.navbar-nav .nav-link:hover,
.navbar-nav .nav-link:active,
.navbar-nav .nav-link.active {
.navbar-nav .nav-item:hover,
.navbar-nav .nav-item:active,
.navbar-nav .nav-item.show {
background-color: #4e342e;
}
/* Adapted from https://codepen.io/GeoffreyBooth/pen/QGzwYK */
.navbar-menu-button,
.navbar-menu-button:focus {
float: right;
width: 2.3em;
padding: 0;
margin-top: 0.25em;
background: transparent;
border: 0;
outline: 0;
}
.menu-button {
width: 2em;
height: 1.5em;
position: relative;
transform: rotate(0deg);
transition: .25s ease-in-out;
cursor: pointer;
}
.menu-button span {
display: block;
position: absolute;
height: 4px;
width: 100%;
background: #efebe9;
border-radius: 4px;
opacity: 1;
left: 0;
transform: rotate(0deg);
transition: .25s ease-in-out;
}
.menu-button span:nth-child(1) {
top: 0;
}
.menu-button span:nth-child(2),
.menu-button span:nth-child(3) {
top: 0.7em;
}
.menu-button span:nth-child(4) {
top: 1.4em;
}
.menu-button.active span:nth-child(1) {
top: 0.7em;
width: 0%;
left: 50%;
}
.menu-button.active span:nth-child(2) {
transform: rotate(45deg);
}
.menu-button.active span:nth-child(3) {
transform: rotate(-45deg);
}
.menu-button.active span:nth-child(4) {
top: 0.7em;
width: 0%;
left: 50%;
.navbar-toggler {
transition: all 0.1s ease-in-out;
}
@@ -138,92 +84,53 @@ a:focus, a:hover, a:active {
*/
.sidebar {
background-color: #efebe9;
border-right: 1px solid #efebe9;
top: 3.5rem;
bottom: 0;
left: 0;
z-index: 1000;
display: block;
padding: 0;
}
.sidebar .contents {
height: 100%;
position: fixed;
top: 3.5em;
height: calc(100% - 3.5rem);
/* Scrollable contents if viewport is shorter than content */
overflow-y: auto;
overflow-x: hidden;
left: 0;
bottom: 0;
z-index: 1000;
padding: 0;
background-color: #efebe9;
border-right: 1px solid #efebe9;
}
.sidebar::-webkit-scrollbar {
display: none;
}
@media screen and (max-width: 991px) {
.sidebar {
left: -100%;
transition: 0.25s left ease-in-out;
}
.sidebar.show {
left: 0;
}
}
.contents {
padding: 0.5em 0 0.5em 0.5em;
font-family: 'Alegreya Sans';
font-weight: 400;
font-size: 1.2em;
line-height: 2;
}
@media screen and (max-width: 991px) {
.sidebar .contents {
position: fixed;
height: calc(100% - 3.5rem);
padding: 1em 1.6em;
}
}
@media screen and (min-width: 992px) {
.sidebar {
position: fixed;
}
.sidebar .contents {
padding: 1.3em;
}
.sidebar .contents::-webkit-scrollbar {
display: none;
}
align-items: normal;
}
.sidebar .nav-link.active,
.sidebar .nav-link.active a:hover,
.sidebar .nav-link.active a:focus {
font-weight: 800;
}
.nav .nav {
.contents .nav .nav {
margin-left: 1em;
font-size: 0.9em;
line-height: 1.7;
}
.contents .nav-link {
padding: 0.2em 0.7em;
}
/*
* Off Canvas
*/
@media screen and (max-width: 991px) {
.row-offcanvas {
position: relative;
transition: all .25s ease-in-out;
}
.row-offcanvas-left {
left: 0;
}
.sidebar-offcanvas {
position: absolute;
top: 0;
}
}
@media screen and (max-width: 767px) {
.row-offcanvas-left .sidebar-offcanvas {
left: -100%;
}
.row-offcanvas-left.active {
left: calc(100% + 30px)
}
}
@media screen and (min-width: 768px) and (max-width: 991px) {
.row-offcanvas-left .sidebar-offcanvas {
left: calc(-66.667% - 15px);
width: 66.667%;
}
.row-offcanvas-left.active {
left: calc(66.667% + 30px);
}
.row-offcanvas-left .sidebar-offcanvas .contents {
width: 66.667%;
}
.contents .nav-link.active,
.contents .nav-link.active a:hover,
.contents .nav-link.active a:focus {
font-weight: 800;
}
@@ -251,8 +158,20 @@ a:focus, a:hover, a:active {
.main p, .main li, .main td, .main th {
font-family: Lato;
font-size: 1.3rem;
font-weight: 300;
font-size: 1.1em;
line-height: 1.7;
}
.main blockquote {
font-size: 1.1em;
}
.main li p, .main li li, .main li blockquote {
font-size: 1em;
}
@media (min-width: 768px) {
.main p, .main li, .main td, .main th, .main blockquote {
font-size: 1.2em;
}
}
.main td {
vertical-align: top;
@@ -268,9 +187,6 @@ a:focus, a:hover, a:active {
.main a:focus, .main a:hover, .main a:active {
border-bottom: 2px solid rgba(56, 142, 60, 0.2);
}
.main blockquote {
font-size: 1.3rem;
}
.main blockquote pre {
background-color: #f8f3f0;
color: #2f2625;
@@ -279,11 +195,18 @@ a:focus, a:hover, a:active {
}
p, blockquote, table, .code-example {
margin-bottom: 1.3rem;
margin-bottom: 1.1em;
}
.main li {
margin-bottom: 0.6em;
}
td code {
code, td code {
white-space: nowrap;
padding: 2px 8px;
}
pre code {
white-space: pre; /* We want newlines to be newlines in code blocks */
}
h2, h3, h4 {
@@ -304,12 +227,20 @@ h3, h4, h2 time {
margin-top: -2.3rem;
}
@media (min-width: 1200px) {
.main > header, .main section > h2, .main section > h3, .main section > h4, .main section > p, .main section > blockquote, .main section > ul, .main section > table {
max-width: 80%;
}
}
code, button {
font-family: 'Roboto Mono';
font-weight: 400;
}
code {
code, a > code {
background-color: #f8f3f0;
}
code {
color: #2f2625;
}
@@ -348,14 +279,35 @@ textarea {
outline: 0;
}
.CodeMirror {
.play-button {
height: 1em;
}
.CodeMirror pre, pre.placeholder-code {
line-height: 1.4em;
}
.CodeMirror,
.placeholder-code {
/* https://codemirror.net/demo/resize.html */
height: auto;
background: transparent;
font-family: 'Roboto Mono';
font-weight: 400;
line-height: 1.25;
font-size: 0.9em;
}
@media (min-width: 768px) {
.CodeMirror,
.placeholder-code {
font-size: 1em;
}
}
.CodeMirror-code:focus {
outline: none;
}
.javascript-output-column .CodeMirror-cursor {
/* https://github.com/codemirror/CodeMirror/issues/2568 */
display: none;
@@ -373,7 +325,7 @@ textarea {
opacity: 0;
transition: opacity 0.15s ease-in-out;
}
.try-coffeescript.active {
.try-coffeescript.show {
opacity: 1;
z-index: 1001;
}

View File

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-22 347 566 100">
<title>
CoffeeScript Logo
</title>
<path d="M21.7 351.1c.1.6-.2 1.1-1.2 1.6-1.3-.7-4.1-1.1-6.4-.9-2.5.2-4.6 1-4.3 2.7.4 1.7 2.8 2.7 7.1 2.3 10.5-.9 10.4-8 25.8-9.4 12-1.1 18.7 2.6 19.6 7.1.7 3.5-2.2 6.9-10.9 7.6-7.7.7-12.2-1.4-12.6-3.5-.2-1.1.4-2.7 4.1-3.1.4 1.7 2.5 3.5 7.5 3 3.6-.3 6.6-1.6 6.2-3.6-.4-2.1-4.2-3.3-10.2-2.8-12.2 1.1-15.2 7.8-25.6 8.7-7.4.7-13.4-2-14.2-6-.3-1.5-.3-5 7.5-5.7 4-.3 7.2.4 7.6 2zm-39 41.8c-3.4 4.3-4.9 9.3-4.6 14.2.3 4.9 2.7 8.9 6.5 12 4 3.1 8.3 4 13.2 3.1 1.9-.3 4-1.3 5.9-1.9-4 0-7.4-1.3-10.8-4-3.7-2.7-6.2-6.5-6.8-11.1-.9-4.3 0-8.3 2.4-11.8 2.7-3.4 6.2-5.3 10.8-5.9 4.6-.3 8.6.9 12.6 3.7-.9-1.3-2.2-2.2-3.4-3.4-4-2.7-8.3-4-13.6-2.7-4.8 1-8.8 3.5-12.2 7.8zm53.6-23.1c-12.9 0-24.4-1.3-32.7-3.1-8.9-2.2-13.6-4.6-13.6-7.7 0-1.3.6-2.4 2.4-3.7-5.6 2.2-8.6 4-8.6 6.8.3 3.1 5.3 6.2 15.5 8.6 9.6 2.4 21.9 3.7 36.7 3.7 15.1 0 27.1-1.3 36.7-3.7 10.2-2.4 15.1-5.6 15.1-8.6 0-2.2-2.2-4.3-6.2-5.9.9.6 1.6 1.6 1.6 2.7 0 3.1-4.6 5.6-13.9 7.7-8.6 1.9-19.6 3.2-33 3.2zm36.8 8.6c-9.6 2.2-21.9 3.7-36.7 3.7-15.1 0-27.4-1.6-37-3.7-8.6-2.2-13.2-4.6-14.8-7.1 1.6 10.8 5.3 21 10.2 30 3.7 5.6 7.4 10.5 11.1 15.8 1.6 3.1 2.7 6.2 3.4 9.3 2.4 3.4 5.9 5.6 10.2 6.8 5.3 1.9 10.8 2.7 16.4 2.4h.6c5.6.3 11.5-.6 16.9-2.4 4-1.3 7.4-3.4 9.9-6.8h.3c.6-3.1 1.6-6.2 3.1-9.3 3.7-5.3 7.4-10.2 11.1-15.8 4.9-8.9 8.3-19.1 10.2-30-2 2.8-6.6 5.2-14.9 7.1zm106.2 30.1c-4.8 12.1-17.6 16.9-25.9 16.9-13.4 0-19.9-6-19.9-22.3 0-16.5 7.9-47.3 31.7-47.3 8.5 0 15.2 3.3 15.2 12.1 0 4.8-1.8 8.3-6.4 8.3-1.5 0-3.4-.4-5.2-2.4 2.2-1.1 4.2-4.9 4.2-8.3 0-2.9-1.5-5.6-5.6-5.6-10 0-18.9 23.9-18.9 42.4 0 8.3 2.2 14.2 10.9 14.2 7.1 0 13.5-3.4 17.7-9.1l2.2 1.1zm32.9-16.3c.4.2.7.2 1 .2 4.2 0 10.1-2.7 14-5.5l.8 2.4c-3.4 3.7-9.5 6.5-16.1 7.5-1.5 16.8-10.6 27.3-21.7 27.3-8.4 0-14.5-4-14.5-14.4 0-10.5 6.2-32.2 24.9-32.2 7.8.3 11.6 5.3 11.6 14.7zm-7.7 5c-1.9-.5-2.4-2-2.4-3.8 0-2.5 1.2-4.2 2.8-4.9-.2-3.8-1.1-5.3-3.4-5.3-6.5 0-12 16.6-12 25.6 0 6 1.2 7.3 4.6 7.3 4.2.1 8.9-8 10.4-18.9zm-6.6 39.7c0-8.3 7.1-11 15.8-13.6l10.9-51.9c2.7-13 10.6-15.5 16.5-15.5 4.1 0 8 2.2 9.7 5.7 3.6-4.6 8.4-5.7 12.4-5.7 5.6 0 10.8 3.9 10.8 9.8 0 1.5-.1 2.6-.3 3.7h-4.3c.1-.9.2-1.7.2-2.4 0-2.1-1.7-3.1-3.4-3.1-2 0-4.8 1.1-6.2 7.1l-1.7 7.4h9.1l-.8 3.6h-9l-10.3 49.1c-2.7 13-10.6 15.5-16.5 15.5-5.2 0-8.3-2.3-9.8-5.7-3.5 4.6-8.3 5.7-12.3 5.7-5.6.1-10.8-3.8-10.8-9.7zm9.1 1.8c1.9 0 4.2-1.8 5.4-7.1l1.1-5.3c-5.7 2-10.1 4.4-10.1 9.4 0 1.2 1.7 3 3.6 3zm21.7 0c1.9 0 4.2-1.8 5.4-7.1l2.2-10.4-9.4 1.8-1.8 8.3c-.5 2.1-1.1 4-1.8 5.6.9 1.3 3 1.8 5.4 1.8zm-1.4-18l9.4-1.7 7.7-36.8h-9l-8.1 38.5zm16.6-56.7c-2 0-4.8 1.1-6.2 7.1l-1.7 7.4h9l2.1-9.5c.2-.7.2-1.3.2-2 .1-2-1.5-3-3.4-3zm37.9 53c7.1 0 11.6-4 16.1-9.2h3.1c-5.2 8.3-12.9 16.8-25 16.8-8.5 0-14.2-4.2-14.2-14.5 0-10.5 5.9-32.3 24.6-32.3 8.1 0 10 4.2 10 8.7 0 10.5-10 18.5-20.9 19.2-.1 1.3-.2 2.5-.2 3.6 0 6.2 2.2 7.7 6.5 7.7zm5.3-34.4c-4.6 0-9.1 9.7-10.9 18.7 7-.5 13.2-7.4 13.2-15 0-2.2-.5-3.7-2.3-3.7zm28.6 33.4c3.4 0 7.8-2.3 10.8-4.8-2 10.4-8.4 13.4-15.8 13.4-8.4 0-14.1-4.2-14.1-14.5 0-10.5 5.9-32.3 24.6-32.3 8.1 0 10 4.2 10 8.7 0 10.6-10 18.5-20.9 19.2-.1.9-.2 2-.2 2.7 0 5.7 2.5 7.6 5.6 7.6zm6.2-33.4c-4.5 0-9.1 10.1-11 18.7 7.1-.4 13.3-7.3 13.3-15 0-2.2-.6-3.7-2.3-3.7zm51.3-6.7c-1.7 0-3-.6-4.2-1.9 2.4-1.5 4.1-4.8 4.1-7.8 0-3.1-1.8-6.1-6.8-6.1s-8.3 2.8-8.3 8.2c0 13.3 20.5 15.2 20.5 34.8 0 15.3-12.3 22.7-25.6 22.7-10.4 0-19.3-4.5-19.3-15.7 0-9.8 7-14.9 13.3-14.9 3.1 0 7.7 1.3 8 6-4.9 0-10.7 2.3-10.7 8.5 0 4.5 2.9 8.7 8.7 8.7 6.1 0 10.6-4.4 10.6-12 0-15.6-18.6-21.1-18.6-34.5 0-9.5 9.3-16.3 21-16.3 4.3 0 14.6.9 14.6 10.9.1 5.5-2.8 9.4-7.3 9.4zm36.2 10.3c0-2.3-.8-3.7-2.5-3.7-5.7 0-11.7 16.6-11.7 26.7 0 6.2 2.2 7.6 6.6 7.6 7.1 0 11.6-4 16.1-9.2h3.1c-5.2 8.3-12.9 16.8-25 16.8-8.5 0-14.2-4.2-14.2-14.5 0-10.6 6-32.3 24.5-32.3 8.1 0 10.1 4.2 10.1 8.3 0 4.4-2.2 6.7-4.8 6.7-1 0-2.1-.4-3.1-1.1.5-1.9.9-3.6.9-5.3zm27.7-7.6l-1.2 5.7c3.1-2.7 6.7-5.7 11-5.7 4.1 0 6.3 3.3 6.3 6.9 0 3.1-2.1 6.7-6.6 6.7-5.1 0-2.5-6-5.3-6-2.7 0-4.4 1.4-6.7 3.4l-7.2 34.6h-13.1l9.6-45.4 13.2-.2zm34.2 0l-6.6 30.9c-.3 1.2-.4 2.1-.4 2.9 0 2.5 1.2 3.3 3.7 3.3 3.5 0 6.9-3.4 8.1-8h3.8c-5.2 14.8-14.2 16.8-19.1 16.8-5.5 0-9.7-3.2-9.7-10.9 0-1.8.3-3.7.7-5.9l6.2-29.2 13.3.1zm-4.1-19.4c4 0 7.2 3.2 7.2 7.2s-3.2 7.1-7.2 7.1-7.1-3.1-7.1-7.1c-.1-4 3.2-7.2 7.1-7.2zm29.1 16l-1.5 6.9c2.6-2.3 6.1-3.9 10.7-3.9 6.2 0 11.1 3.5 11.1 14.4 0 12.2-4.7 32.1-22.3 32.1-4.5 0-6.8-1.6-7.7-3.2l-4.7 22.1-13.7 3.2 15.2-71.5 12.9-.1zm7.8 17c0-7-2.9-7.5-4.5-7.5-2 0-4.5 1.6-6.3 4.4l-5.4 25.5c.4 1 1.4 2.1 3.4 2.1 9.7 0 12.8-15.9 12.8-24.5zm27.8 17.3c-.3 1.1-.5 2.2-.5 3.1 0 1.9.7 3.2 3.1 3.2.7 0 1.7 0 2.4-.3-2.5 7.8-6.6 8.9-9.6 8.9-6.4 0-9.1-4.4-9.1-10.3 0-1.6.2-3.1.6-4.8l5.8-27.2h-3l.7-3.6h3L528 366l13.4-1.9s-1.4 6.2-3.1 14.4h5.5l-.7 3.6h-5.5l-5.7 27.4z"/>
</svg>

After

Width:  |  Height:  |  Size: 4.7 KiB

View File

@@ -0,0 +1,16 @@
<nav class="navbar navbar-expand-lg fixed-top navbar-dark bg-dark bg-ribbed-dark site-navbar">
<a class="navbar-brand" href="#" data-close="try"><%= include('logo.svg') %></a>
<button class="navbar-toggler" type="button" data-toggle="offcanvas" data-close="try" aria-label="Toggle sidebar">
<span class="navbar-toggler-icon"></span>
</button>
<nav class="collapse navbar-collapse">
<div class="navbar-nav mr-auto d-none d-lg-flex">
<a href="#try" id="try-link" class="nav-item nav-link" data-toggle="try">Try CoffeeScript</a>
<a href="#language" class="nav-item nav-link" data-close="try">Language Reference</a>
<a href="#resources" class="nav-item nav-link" data-close="try">Resources</a>
<a href="https://github.com/jashkenas/coffeescript/" class="nav-item nav-link" data-close="try">GitHub
</a>
</div>
</nav>
</nav>

View File

@@ -0,0 +1,3 @@
<svg class="play-button" viewBox="0 0 24 24">
<path d="M2.56-0.01v24.02L21.44 11.98 2.56-0.01z"/>
</svg>

After

Width:  |  Height:  |  Size: 107 B

View File

@@ -0,0 +1,19 @@
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js" integrity="sha384-xBuQ/xzmlsLoJpyjoggmTEz8OWUFM0/RC5BsqQBDX2v5cMvDHcMakNTNrHIW2I5f" crossorigin="anonymous"></script>
<script>
window.Popper = {}; // Remove if we want to use Bootstrap tooltips
</script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/js/bootstrap.min.js" integrity="sha384-h0AbiXch4ZDo7tp9hKZ4TsHbi047NrKGLO3SEJAg45jXxnGIfYzk4Si90RDIqNm1" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/combine/npm/codemirror@5.29.0/lib/codemirror.js,npm/codemirror@5.29.0/mode/coffeescript/coffeescript.js,npm/codemirror@5.29.0/addon/lint/coffeescript-lint.js,npm/codemirror@5.29.0/mode/javascript/javascript.js"></script>
<script src="browser-compiler/coffeescript.js"></script>
<script>
<%= includeScript('docs.coffee') %>
</script>
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-106156830-1"></script>
<script>
window.GA_TRACKING_ID = 'UA-106156830-1';
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments)};
gtag('js', new Date());
gtag('config', GA_TRACKING_ID);
</script>

View File

@@ -0,0 +1,83 @@
<nav id="contents" class="navbar contents">
<nav class="nav flex-column">
<a href="#try" class="nav-link d-md-none" data-action="sidebar-nav" data-toggle="try">Try CoffeeScript</a>
<a href="#top" class="nav-link" data-action="sidebar-nav">Overview</a>
<a href="#coffeescript-2" class="nav-link" data-action="sidebar-nav">CoffeeScript 2</a>
<nav class="nav flex-column">
<a href="#whats-new-in-coffeescript-2" class="nav-link" data-action="sidebar-nav">Whats New in CoffeeScript 2</a>
<a href="#compatibility" class="nav-link" data-action="sidebar-nav">Compatibility</a>
</nav>
<a href="#installation" class="nav-link" data-action="sidebar-nav">Installation</a>
<a href="#usage" class="nav-link" data-action="sidebar-nav">Usage</a>
<nav class="nav flex-column">
<a href="#cli" class="nav-link" data-action="sidebar-nav">Command Line</a>
<a href="#nodejs-usage" class="nav-link" data-action="sidebar-nav">Node.js</a>
<a href="#transpilation" class="nav-link" data-action="sidebar-nav">Transpilation</a>
</nav>
<a href="#language" class="nav-link" data-action="sidebar-nav">Language Reference</a>
<nav class="nav flex-column">
<a href="#functions" class="nav-link" data-action="sidebar-nav">Functions</a>
<a href="#strings" class="nav-link" data-action="sidebar-nav">Strings</a>
<a href="#objects-and-arrays" class="nav-link" data-action="sidebar-nav">Objects and Arrays</a>
<a href="#comments" class="nav-link" data-action="sidebar-nav">Comments</a>
<a href="#lexical-scope" class="nav-link" data-action="sidebar-nav">Lexical Scoping and Variable Safety</a>
<a href="#conditionals" class="nav-link" data-action="sidebar-nav">If, Else, Unless, and Conditional Assignment</a>
<a href="#splats" class="nav-link" data-action="sidebar-nav">Splats, or Rest Parameters/Spread Syntax</a>
<a href="#loops" class="nav-link" data-action="sidebar-nav">Loops and Comprehensions</a>
<a href="#slices" class="nav-link" data-action="sidebar-nav">Array Slicing and Splicing</a>
<a href="#expressions" class="nav-link" data-action="sidebar-nav">Everything is an Expression</a>
<a href="#operators" class="nav-link" data-action="sidebar-nav">Operators and Aliases</a>
<a href="#existential-operator" class="nav-link" data-action="sidebar-nav">Existential Operator</a>
<a href="#destructuring" class="nav-link" data-action="sidebar-nav">Destructuring Assignment</a>
<a href="#chaining" class="nav-link" data-action="sidebar-nav">Chaining Function Calls</a>
<a href="#fat-arrow" class="nav-link" data-action="sidebar-nav">Bound (Fat Arrow) Functions</a>
<a href="#generators" class="nav-link" data-action="sidebar-nav">Generator Functions</a>
<a href="#async-functions" class="nav-link" data-action="sidebar-nav">Async Functions</a>
<a href="#classes" class="nav-link" data-action="sidebar-nav">Classes</a>
<a href="#prototypal-inheritance" class="nav-link" data-action="sidebar-nav">Prototypal Inheritance</a>
<a href="#switch" class="nav-link" data-action="sidebar-nav">Switch and Try/Catch</a>
<a href="#comparisons" class="nav-link" data-action="sidebar-nav">Chained Comparisons</a>
<a href="#regexes" class="nav-link" data-action="sidebar-nav">Block Regular Expressions</a>
<a href="#tagged-template-literals" class="nav-link" data-action="sidebar-nav">Tagged Template Literals</a>
<a href="#modules" class="nav-link" data-action="sidebar-nav">Modules</a>
<a href="#embedded" class="nav-link" data-action="sidebar-nav">Embedded JavaScript</a>
<a href="#jsx" class="nav-link" data-action="sidebar-nav">JSX</a>
</nav>
<a href="#type-annotations" class="nav-link" data-action="sidebar-nav">Type Annotations</a>
<a href="#literate" class="nav-link" data-action="sidebar-nav">Literate CoffeeScript</a>
<a href="#source-maps" class="nav-link" data-action="sidebar-nav">Source Maps</a>
<a href="#cake" class="nav-link" data-action="sidebar-nav">Cake, and Cakefiles</a>
<a href="#scripts" class="nav-link" data-action="sidebar-nav"><code>"text/coffeescript"</code> Script Tags</a>
<a href="test.html" class="nav-link" data-action="sidebar-nav">Browser-Based Tests</a>
<a href="#resources" class="nav-link" data-action="sidebar-nav">Resources</a>
<nav class="nav flex-column">
<a href="#books" class="nav-link" data-action="sidebar-nav">Books</a>
<a href="#screencasts" class="nav-link" data-action="sidebar-nav">Screencasts</a>
<a href="#examples" class="nav-link" data-action="sidebar-nav">Examples</a>
<a href="#chat" class="nav-link" data-action="sidebar-nav">Chat</a>
<a href="#annotated-source" class="nav-link" data-action="sidebar-nav">Annotated Source</a>
<a href="#contributing" class="nav-link" data-action="sidebar-nav">Contributing</a>
</nav>
<a href="https://github.com/jashkenas/coffeescript/" class="nav-item nav-link d-md-none" data-action="sidebar-nav">GitHub</a>
<a href="#unsupported" class="nav-link" data-action="sidebar-nav">Unsupported ECMAScript Features</a>
<nav class="nav flex-column">
<a href="#unsupported-let-const" class="nav-link" data-action="sidebar-nav"><code>let</code> and <code>const</code></a>
<a href="#unsupported-named-functions" class="nav-link" data-action="sidebar-nav">Named Functions and Function Declarations</a>
<a href="#unsupported-get-set" class="nav-link" data-action="sidebar-nav"><code>get</code> and <code>set</code> Shorthand Syntax</a>
</nav>
<a href="#breaking-changes" class="nav-link" data-action="sidebar-nav">Breaking Changes From 1.x</a>
<nav class="nav flex-column">
<a href="#breaking-change-fat-arrow" class="nav-link" data-action="sidebar-nav">Bound (Fat Arrow) Functions</a>
<a href="#breaking-changes-default-values" class="nav-link" data-action="sidebar-nav">Default Values</a>
<a href="#breaking-changes-bound-generator-functions" class="nav-link" data-action="sidebar-nav">Bound Generator Functions</a>
<a href="#breaking-changes-classes" class="nav-link" data-action="sidebar-nav">Classes</a>
<a href="#breaking-changes-super-this" class="nav-link" data-action="sidebar-nav"><code>super</code> and <code>this</code></a>
<a href="#breaking-changes-super-extends" class="nav-link" data-action="sidebar-nav"><code>super</code> and <code>extends</code></a>
<a href="#breaking-changes-jsx-and-the-less-than-and-greater-than-operators" class="nav-link" data-action="sidebar-nav">JSX and the <code>&lt;</code> and <code>&gt;</code> Operators</a>
<a href="#breaking-changes-literate-coffeescript" class="nav-link" data-action="sidebar-nav">Literate CoffeeScript Parsing</a>
<a href="#breaking-changes-argument-parsing-and-shebang-lines" class="nav-link" data-action="sidebar-nav">Argument Parsing and <code>#!</code> Lines</a>
</nav>
<a href="#changelog" class="nav-link" data-action="sidebar-nav">Changelog</a>
<a href="/v1/" class="nav-link" data-action="sidebar-nav">Version 1.x Documentation</a>
</nav>
</nav>

View File

@@ -1,8 +1,8 @@
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.5/css/bootstrap.min.css" integrity="sha384-AysaV+vQoT3kOAXZkl02PThvDr8HYKPZhNT5h/CXfBThSRXQ6jW5DO2ekP5ViFdi" crossorigin="anonymous">
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M" crossorigin="anonymous">
<!-- The CoffeeScript logo font is Googles Galada -->
<link href="https://fonts.googleapis.com/css?family=Alegreya+Sans:400,800|Lato:300,300i,400,700|Roboto+Mono:400,400i" rel="stylesheet" crossorigin="anonymous">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/codemirror/4.5.0/codemirror.css" crossorigin="anonymous">
<style>
<%= include('docs.css') %>
<%= include('twilight.css') %>
<%= include('code.css') %>
</style>

View File

@@ -52,16 +52,27 @@ say = (msg, className) ->
stdout.appendChild div
msg
asyncTests = []
onFail = (description, fn, err) ->
failures.push
error: err
description: description
source: fn.toString() if fn.toString?
@test = (description, fn) ->
++total
try
fn.call(fn)
++passedTests
catch error
failures.push
error: error
description: description
source: fn.toString() if fn.toString?
result = fn.call(fn)
if result instanceof Promise # An async test.
asyncTests.push result
result.then ->
passedTests++
.catch (err) ->
onFail description, fn, err
else
passedTests++
catch err
onFail description, fn, err
@failures =
push: (failure) -> # Match function called by regular tests
@@ -74,11 +85,11 @@ say = (msg, className) ->
@ok = (good, msg = 'Error') ->
throw Error msg unless good
# Polyfill Node assert's fail
# Polyfill Node asserts fail
@fail = ->
ok no
# Polyfill Node assert's deepEqual with Underscore's isEqual
# Polyfill Node asserts deepEqual with Underscores isEqual
@deepEqual = (a, b) ->
ok _.isEqual(a, b), "Expected #{JSON.stringify a} to deep equal #{JSON.stringify b}"
@@ -114,14 +125,36 @@ for test in document.getElementsByClassName 'test'
CoffeeScript.run test.innerHTML, options
# Finish up
yay = passedTests is total and not failedTests
sec = (new Date - start) / 1000
msg = "passed #{passedTests} tests in #{sec.toFixed 2} seconds"
msg = "failed #{total - passedTests} tests and #{msg}" unless yay
say msg, (if yay then 'good' else 'bad')
done = ->
yay = passedTests is total and not failedTests
sec = (new Date - start) / 1000
msg = "passed #{passedTests} tests in #{sec.toFixed 2} seconds"
msg = "failed #{total - passedTests} tests and #{msg}" unless yay
say msg, (if yay then 'good' else 'bad')
gtag 'event', 'tests_complete',
event_category: 'tests'
event_label: if yay then 'passed' else 'failed'
value: if yay then passedTests else total - passedTests
gtag 'event', 'tests_report',
event_category: 'tests'
event_label: msg
gtag 'event', 'timing_complete',
name: 'tests_run'
value: sec * 1000
Promise.all(asyncTests).then(done).catch(done)
</script>
<%= tests %>
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-106156830-1"></script>
<script>
window.GA_TRACKING_ID = 'UA-106156830-1';
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments)};
gtag('js', new Date());
gtag('config', GA_TRACKING_ID);
</script>
</body>
</html>

View File

@@ -8,8 +8,8 @@
</div>
</div>
<div class="row">
<div class="col-xs-12 text-xs-right try-buttons">
<button type="button" class="btn btn-primary" data-action="run-code-example" data-example="try-coffeescript" data-run="true"></button>&emsp;
<div class="col text-right try-buttons">
<button type="button" class="btn btn-primary" data-action="run-code-example" data-example="try-coffeescript" data-run="true"><%= include('play.svg') %></button>&emsp;
</div>
</div>
</aside>

View File

@@ -1,155 +0,0 @@
<div id="fadeout"></div>
<div id="flybar">
<a id="logo" href="#top"><%= include('documentation/images/logo.svg') %></a>
<div class="navigation toc">
<div class="button">
Table of Contents
</div>
<div class="contents menu">
<a href="#overview">Overview</a>
<a href="#installation">Installation</a>
<a href="#usage">Usage</a>
<a href="#literate">Literate CoffeeScript</a>
<a href="#language">Language Reference</a>
<a href="#literals">Literals: Functions, Objects and Arrays</a>
<a href="#lexical-scope">Lexical Scoping and Variable Safety</a>
<a href="#conditionals">If, Else, Unless, and Conditional Assignment</a>
<a href="#splats">Splats…</a>
<a href="#loops">Loops and Comprehensions</a>
<a href="#slices">Array Slicing and Splicing</a>
<a href="#expressions">Everything is an Expression</a>
<a href="#operators">Operators and Aliases</a>
<a href="#existential-operator">Existential Operator</a>
<a href="#classes">Classes, Inheritance, and Super</a>
<a href="#destructuring">Destructuring Assignment</a>
<a href="#fat-arrow">Bound and Generator Functions</a>
<a href="#embedded">Embedded JavaScript</a>
<a href="#switch">Switch and Try/Catch</a>
<a href="#comparisons">Chained Comparisons</a>
<a href="#strings">String Interpolation, Block Strings, and Block Comments</a>
<a href="#tagged-template-literals">Tagged Template Literals</a>
<a href="#regexes">Block Regular Expressions</a>
<a href="#modules">Modules</a>
<a href="#cake">Cake, and Cakefiles</a>
<a href="#source-maps">Source Maps</a>
<a href="#scripts">"text/coffeescript" Script Tags</a>
<a href="#resources">Books, Screencasts, Examples and Resources</a>
<a href="#changelog">Changelog</a>
</div>
</div>
<div class="navigation try">
<div class="button">
Try CoffeeScript
<div class="repl_bridge"></div>
</div>
<div class="contents repl_wrapper">
<div class="code">
<div class="screenshadow tl"></div>
<div class="screenshadow tr"></div>
<div class="screenshadow bl"></div>
<div class="screenshadow br"></div>
<div id="repl_source_wrap">
<textarea id="repl_source" rows="100" spellcheck="false">alert "Hello CoffeeScript!"</textarea>
</div>
<div id="repl_results_wrap"><pre id="repl_results"></pre></div>
<div class="minibutton dark run" title="Ctrl-Enter">Run</div>
<a class="minibutton permalink" id="repl_permalink">Link</a>
<br class="clear" />
</div>
</div>
</div>
<div class="navigation annotated">
<div class="button">
Annotated Source
</div>
<div class="contents menu">
<a href="/v<%= majorVersion %>/annotated-source/grammar.html">Grammar Rules — src/grammar</a>
<a href="/v<%= majorVersion %>/annotated-source/lexer.html">Lexing Tokens — src/lexer</a>
<a href="/v<%= majorVersion %>/annotated-source/rewriter.html">The Rewriter — src/rewriter</a>
<a href="/v<%= majorVersion %>/annotated-source/nodes.html">The Syntax Tree — src/nodes</a>
<a href="/v<%= majorVersion %>/annotated-source/scope.html">Lexical Scope — src/scope</a>
<a href="/v<%= majorVersion %>/annotated-source/helpers.html">Helpers &amp; Utility Functions — src/helpers</a>
<a href="/v<%= majorVersion %>/annotated-source/coffee-script.html">The CoffeeScript Module — src/coffee-script</a>
<a href="/v<%= majorVersion %>/annotated-source/cake.html">Cake &amp; Cakefiles — src/cake</a>
<a href="/v<%= majorVersion %>/annotated-source/command.html">“coffee” Command-Line Utility — src/command</a>
<a href="/v<%= majorVersion %>/annotated-source/optparse.html">Option Parsing — src/optparse</a>
<a href="/v<%= majorVersion %>/annotated-source/repl.html">Interactive REPL — src/repl</a>
<a href="/v<%= majorVersion %>/annotated-source/sourcemap.html">Source Maps — src/sourcemap</a>
</div>
</div>
</div>
<div id="top" class="container">
<span class="bookmark" id="overview"></span>
<%= htmlFor('introduction') %>
<%= htmlFor('overview') %>
<span class="bookmark" id="installation"></span>
<%= htmlFor('installation') %>
<span class="bookmark" id="usage"></span>
<%= htmlFor('usage') %>
<span class="bookmark" id="literate"></span>
<%= htmlFor('literate') %>
<span class="bookmark" id="language"></span>
<%= htmlFor('language') %>
<span class="bookmark" id="literals"></span>
<%= htmlFor('functions') %>
<span class="bookmark" id="objects-and-arrays"></span>
<%= htmlFor('objects_and_arrays') %>
<span class="bookmark" id="lexical-scope"></span>
<%= htmlFor('lexical_scope') %>
<span class="bookmark" id="conditionals"></span>
<%= htmlFor('conditionals') %>
<span class="bookmark" id="splats"></span>
<%= htmlFor('splats') %>
<span class="bookmark" id="loops"></span>
<%= htmlFor('loops') %>
<span class="bookmark" id="slices"></span>
<%= htmlFor('slices') %>
<span class="bookmark" id="expressions"></span>
<%= htmlFor('expressions') %>
<span class="bookmark" id="operators"></span>
<%= htmlFor('operators') %>
<span class="bookmark" id="existential-operator"></span>
<%= htmlFor('existential_operator') %>
<span class="bookmark" id="classes"></span>
<%= htmlFor('classes') %>
<span class="bookmark" id="destructuring"></span>
<%= htmlFor('destructuring') %>
<span class="bookmark" id="fat-arrow"></span>
<%= htmlFor('fat_arrow') %>
<span class="bookmark" id="embedded"></span>
<%= htmlFor('embedded') %>
<span class="bookmark" id="switch"></span>
<%= htmlFor('switch') %>
<span class="bookmark" id="try-catch"></span>
<%= htmlFor('try') %>
<span class="bookmark" id="comparisons"></span>
<%= htmlFor('comparisons') %>
<span class="bookmark" id="strings"></span>
<%= htmlFor('strings') %>
<span class="bookmark" id="tagged-template-literals"></span>
<%= htmlFor('tagged_template_literals') %>
<span class="bookmark" id="regexes"></span>
<%= htmlFor('heregexes') %>
<span class="bookmark" id="modules"></span>
<%= htmlFor('modules') %>
<span class="bookmark" id="cake"></span>
<%= htmlFor('cake') %>
<span class="bookmark" id="source-maps"></span>
<%= htmlFor('source_maps') %>
<span class="bookmark" id="scripts"></span>
<%= htmlFor('scripts') %>
<span class="bookmark" id="resources"></span>
<%= htmlFor('books') %>
<span class="bookmark" id="screencasts"></span>
<%= htmlFor('screencasts') %>
<span class="bookmark" id="examples"></span>
<%= htmlFor('examples') %>
<span class="bookmark" id="additional-resources"></span>
<%= htmlFor('resources') %>
<span class="bookmark" id="chat"></span>
<%= htmlFor('chat') %>
<span class="bookmark" id="changelog"></span>
<%= htmlFor('changelog') %>
</div>

View File

@@ -1,25 +0,0 @@
fs = require 'fs'
CoffeeScript = require '../../lib/coffeescript'
module.exports = ->
counter = 0
hljs = require 'highlight.js'
hljs.configure classPrefix: ''
(file, executable = no, showLoad = yes) ->
counter++
cs = fs.readFileSync "documentation/examples/#{file}.coffee", 'utf-8'
js = CoffeeScript.compile cs, bare: yes
js = js.replace /^\/\/ generated.*?\n/i, ''
cshtml = "<pre><code>#{hljs.highlight('coffeescript', cs).value}</code></pre>"
jshtml = "<pre><code>#{hljs.highlight('javascript', js).value}</code></pre>"
append = if executable is yes then '' else "alert(#{executable});".replace /"/g, '&quot;'
if executable and executable isnt yes
cs.replace /(\S)\s*\Z/m, "$1\n\nalert #{executable}"
run = if executable is yes then 'run' else "run: #{executable}"
name = "example#{counter}"
script = "<script>window.#{name} = #{JSON.stringify cs}</script>"
load = if showLoad then "<div class='minibutton load' onclick='javascript: loadConsole(#{name});'>load</div>" else ''
button = if executable then """<div class="minibutton ok" onclick="javascript: #{js.replace /"/g, '&quot;'};#{append}">#{run}</div>""" else ''
"<div class='code'>#{cshtml}#{jshtml}#{script}#{load}#{button}<br class='clear' /></div>"

View File

@@ -1,95 +0,0 @@
sourceFragment = "try:"
# Set up the compilation function, to run when you stop typing.
compileSource = ->
source = $('#repl_source').val()
results = $('#repl_results')
window.compiledJS = ''
try
window.compiledJS = CoffeeScript.compile source, bare: on
el = results[0]
if el.innerText
el.innerText = window.compiledJS
else
results.text(window.compiledJS)
results.removeClass 'error'
$('.minibutton.run').removeClass 'error'
catch {location, message}
if location?
message = "Error on line #{location.first_line + 1}: #{message}"
results.text(message).addClass 'error'
$('.minibutton.run').addClass 'error'
# Update permalink
$('#repl_permalink').attr 'href', "##{sourceFragment}#{encodeURIComponent source}"
# Listen for keypresses and recompile.
$('#repl_source').keyup -> compileSource()
# Use tab key to insert tabs
$('#repl_source').keydown (e) ->
if e.keyCode is 9
e.preventDefault()
textbox = e.target
# Insert tab character at caret or in selection
textbox.value = textbox.value[0...textbox.selectionStart] + "\t" + textbox.value[textbox.selectionEnd...]
# Put caret in correct position
textbox.selectionEnd = ++textbox.selectionStart
# Eval the compiled js.
evalJS = ->
try
eval window.compiledJS
catch error then alert error
# Load the console with a string of CoffeeScript.
window.loadConsole = (coffee) ->
$('#repl_source').val coffee
compileSource()
$('.navigation.try').addClass('active')
false
# Helper to hide the menus.
closeMenus = ->
$('.navigation.active').removeClass 'active'
$('.minibutton.run').click -> evalJS()
# Bind navigation buttons to open the menus.
$('.navigation').click (e) ->
return if e.target.tagName.toLowerCase() is 'a'
return false if $(e.target).closest('.repl_wrapper').length
if $(this).hasClass('active')
closeMenus()
else
closeMenus()
$(this).addClass 'active'
false
$(document).on 'click', '[href="#try"]', (e) ->
$('.navigation.try').addClass 'active'
# Dismiss console if Escape pressed or click falls outside console
# Trigger Run button on Ctrl-Enter
$(document.body)
.keydown (e) ->
closeMenus() if e.which == 27
evalJS() if e.which == 13 and (e.metaKey or e.ctrlKey) and $('.minibutton.run:visible').length
.click (e) ->
return false if $(e.target).hasClass('minibutton')
closeMenus()
$('#open_webchat').click ->
$(this).replaceWith $('<iframe src="http://webchat.freenode.net/?channels=coffeescript" width="625" height="400"></iframe>')
$("#repl_permalink").click (e) ->
window.location = $(this).attr("href")
false
# If source code is included in location.hash, display it.
hash = decodeURIComponent location.hash.replace(/^#/, '')
if hash.indexOf(sourceFragment) == 0
src = hash.substr sourceFragment.length
loadConsole src
compileSource()

File diff suppressed because one or more lines are too long

View File

@@ -1,6 +0,0 @@
<script type="text/coffeescript">
<%= include('docs.coffee') %>
</script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script src="v<%= majorVersion %>/browser-compiler/coffeescript.js"></script>

View File

@@ -1,4 +0,0 @@
<style>
<%= include('docs.css') %>
<%= include('tomorrow.css') %>
</style>

View File

@@ -1,60 +0,0 @@
/* Highlight.js syntax highlighting */
/* http://jmblog.github.com/color-themes-for-google-code-highlightjs */
/* Forked from http://softwaremaniacs.org/media/soft/highlight/styles/tomorrow.css */
.tomorrow-comment, pre .comment, pre .title {
color: #8e908c;
}
.tomorrow-red, pre .variable, pre .tag, pre .regexp, pre .ruby .constant, pre .xml .tag .title, pre .xml .pi, pre .xml .doctype, pre .html .doctype, pre .css .id, pre .css .class, pre .css .pseudo {
color: #c82829;
}
.tomorrow-orange, pre .number, pre .preprocessor, pre .built_in, pre .params, pre .constant {
color: #000000;
}
.tomorrow-yellow, pre .class, pre .ruby .class .title, pre .css .rules .attribute {
color: #eab700;
}
.tomorrow-green, pre .string, pre .value, pre .inheritance, pre .header, pre .ruby .symbol, pre .xml .cdata {
color: #718c00;
}
.tomorrow-aqua, pre .css .hexcolor {
color: #3e999f;
}
.tomorrow-blue, pre .function, pre .function .title, pre .python .decorator, pre .python .title, pre .ruby .function .title, pre .ruby .title .keyword, pre .perl .sub, pre .javascript .title, pre .coffeescript .title {
color: #21439C;
}
.tomorrow-purple, pre .keyword, pre .reserved, pre .javascript .function {
color: #FF5600;
}
pre .subst {
color: #A535AE;
}
pre .literal {
color: #A535AE;
}
pre .property {
color: #A535AE;
}
pre .class .title {
color: #21439C;
}
pre .coffeescript .javascript,
pre .javascript .xml,
pre .tex .formula,
pre .xml .javascript,
pre .xml .vbscript,
pre .xml .css,
pre .xml .cdata {
opacity: 0.5;
}

View File

@@ -1,11 +0,0 @@
fs = require 'fs'
_ = require 'underscore'
CoffeeScript = require '../../lib/coffeescript'
module.exports = ->
(file, run = no) ->
cs = fs.readFileSync "documentation/examples/#{file}.coffee", 'utf-8'
js = CoffeeScript.compile cs, bare: yes # This is just the initial JavaScript output; it is replaced by dynamic compilation on changes of the CoffeeScript pane
render = _.template fs.readFileSync('documentation/v2/code.html', 'utf-8')
output = render {file, cs, js, run}

View File

@@ -1,128 +0,0 @@
$(document).ready ->
# Mobile navigation
toggleSidebar = ->
$('.menu-button, .row-offcanvas').toggleClass 'active'
$('[data-toggle="offcanvas"]').click toggleSidebar
$('[data-action="sidebar-nav"]').click (event) ->
if $('.menu-button').is(':visible')
event.preventDefault()
toggleSidebar()
setTimeout ->
window.location = event.target.href
, 260 # Wait for the sidebar to slide away before navigating
# Initialize Scrollspy for sidebar navigation; http://v4-alpha.getbootstrap.com/components/scrollspy/
# See also http://www.codingeverything.com/2014/02/BootstrapDocsSideBar.html and http://jsfiddle.net/KyleMit/v6zhz/
$('body').scrollspy
target: '#contents'
offset: Math.round $('main').css('padding-top').replace('px', '')
initializeScrollspyFromHash = (hash) ->
$(".nav-link.active[href!='#{hash}']").removeClass 'active'
$(window).on 'activate.bs.scrollspy', (event, target) -> # Why `window`? https://github.com/twbs/bootstrap/issues/20086
# We only want one active link in the nav
$(".nav-link.active[href!='#{target.relatedTarget}']").removeClass 'active'
$target = $(".nav-link[href='#{target.relatedTarget}']")
# Update the browser address bar on scroll or navigation
window.history.pushState {}, $target.text(), $target.prop('href')
# Initialize CodeMirror for code examples; https://codemirror.net/doc/manual.html
editors = []
lastCompilationElapsedTime = 200
$('textarea').each (index) ->
$(@).data 'index', index
mode = if $(@).hasClass('javascript-output') then 'javascript' else 'coffeescript'
editors[index] = editor = CodeMirror.fromTextArea @,
mode: mode
theme: 'twilight'
indentUnit: 2
tabSize: 2
lineWrapping: on
lineNumbers: off
inputStyle: 'contenteditable'
readOnly: mode isnt 'coffeescript' # Cant use 'nocursor' if we want the JavaScript to be copyable
viewportMargin: Infinity
# Whenever the user edits the CoffeeScript side of a code example, update the JavaScript output
# If the editor is Try CoffeeScript, also update the hash and save this code in localStorage
if mode is 'coffeescript'
pending = null
editor.on 'change', (instance, change) ->
clearTimeout pending
pending = setTimeout ->
lastCompilationStartTime = Date.now()
try
coffee = editor.getValue()
if index is 0 and $('#try').hasClass('active') # If this is the editor in Try CoffeeScript and its still visible
# Update the hash with the current code
link = "try:#{encodeURIComponent coffee}"
window.history.pushState {}, 'CoffeeScript', "#{location.href.split('#')[0]}##{link}"
# Save this to the users localStorage
try
if window.localStorage?
window.localStorage.setItem 'tryCoffeeScriptCode', coffee
catch exception
output = CoffeeScript.compile coffee, bare: yes
lastCompilationElapsedTime = Math.max(200, Date.now() - lastCompilationStartTime)
catch exception
output = "#{exception}"
editors[index + 1].setValue output
, lastCompilationElapsedTime
# Fix the code editors handling of tab-indented code
editor.addKeyMap
'Tab': (cm) ->
if cm.somethingSelected()
cm.indentSelection 'add'
else if /^\t/m.test cm.getValue()
# If any lines start with a tab, treat this as tab-indented code
cm.execCommand 'insertTab'
else
cm.execCommand 'insertSoftTab'
'Shift-Tab': (cm) ->
cm.indentSelection 'subtract'
'Enter': (cm) ->
cm.options.indentWithTabs = /^\t/m.test cm.getValue()
cm.execCommand 'newlineAndIndent'
# Handle the code example buttons
$('[data-action="run-code-example"]').click ->
run = $(@).data 'run'
index = $("##{$(@).data('example')}-js").data 'index'
js = editors[index].getValue()
js = "#{js}\nalert(#{unescape run});" unless run is yes
eval js
# Try CoffeeScript
toggleTry = (checkLocalStorage = no) ->
if checkLocalStorage and window.localStorage?
try
coffee = window.localStorage.getItem 'tryCoffeeScriptCode'
if coffee?
editors[0].setValue coffee
catch exception
$('#try, #try-link').toggleClass 'active'
closeTry = ->
$('#try, #try-link').removeClass 'active'
$('[data-toggle="try"]').click toggleTry
$('[data-close="try"]').click closeTry
# Configure the initial state
if window.location.hash?
if window.location.hash is '#try'
toggleTry yes
else if window.location.hash.indexOf('#try') is 0
editors[0].setValue decodeURIComponent window.location.hash[5..]
toggleTry()
else
initializeScrollspyFromHash window.location.hash
# Initializing the code editors mightve thrown off our vertical scroll position
document.getElementById(window.location.hash.slice(1)).scrollIntoView()

View File

@@ -1,17 +0,0 @@
<nav class="navbar navbar-dark navbar-fixed-top bg-inverse bg-ribbed-dark">
<a class="navbar-brand" href="#" data-close="try"><%= include('documentation/images/logo.svg') %></a>
<nav class="nav navbar-nav float-xs-left hidden-md-down">
<a href="#try" id="try-link" class="nav-item nav-link" data-toggle="try">Try CoffeeScript</a>
<a href="#language" class="nav-item nav-link" data-close="try">Language Reference</a>
<a href="#resources" class="nav-item nav-link" data-close="try">Resources</a>
<a href="http://github.com/jashkenas/coffeescript/" class="nav-item nav-link" data-close="try">GitHub</a>
</nav>
<button type="button" class="navbar-menu-button hidden-lg-up" data-toggle="offcanvas" aria-label="Toggle sidebar">
<div class="menu-button">
<span></span>
<span></span>
<span></span>
<span></span>
</div>
</button>
</nav>

View File

@@ -1,11 +0,0 @@
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js" integrity="sha384-3ceskX3iaEnIogmQchP8opvBy3Mi7Ce34nWjpBIwVTHfGYWQS9jwHDVRnpKKHJg7" crossorigin="anonymous"></script>
<script>
window.Tether = {}; // Remove if we want to use Bootstrap tooltips
</script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.5/js/bootstrap.min.js" integrity="sha384-BLiI7JTZm+JWlgKa0M0kGRpJbF2J8q+qreVrKBC47e3K6BW78kGLrCkeRX6I9RoK" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/g/codemirror@4.5.0(codemirror.min.js+mode/coffeescript/coffeescript.js+addon/lint/coffeescript-lint.js+mode/javascript/javascript.js)" crossorigin="anonymous"></script>
<script src="browser-compiler/coffeescript.js"></script>
<script type="text/coffeescript">
<%= include('docs.coffee') %>
</script>

View File

@@ -1,200 +0,0 @@
<nav class="contents" id="contents">
<ul class="nav">
<li class="nav-item">
<a href="#top" class="nav-link" data-action="sidebar-nav">Overview</a>
</li>
<li class="nav-item">
<a href="#coffeescript-2" class="nav-link" data-action="sidebar-nav">CoffeeScript 2</a>
</li>
<li class="nav-item">
<a href="#installation" class="nav-link" data-action="sidebar-nav">Installation</a>
</li>
<li class="nav-item">
<a href="#usage" class="nav-link" data-action="sidebar-nav">Usage</a>
<ul class="nav">
<li class="nav-item">
<a href="#cli" class="nav-link" data-action="sidebar-nav">Command Line</a>
</li>
<li class="nav-item">
<a href="#es2015plus-output" class="nav-link" data-action="sidebar-nav">ES2015+ Output</a>
</li>
<li class="nav-item">
<a href="#nodejs-usage" class="nav-link" data-action="sidebar-nav">Node.js</a>
</li>
</ul>
</li>
<li class="nav-item">
<a href="#language" class="nav-link" data-action="sidebar-nav">Language Reference</a>
<ul class="nav">
<li class="nav-item">
<a href="#functions" class="nav-link" data-action="sidebar-nav">Functions</a>
</li>
<li class="nav-item">
<a href="#strings" class="nav-link" data-action="sidebar-nav">Strings</a>
</li>
<li class="nav-item">
<a href="#objects-and-arrays" class="nav-link" data-action="sidebar-nav">Objects and Arrays</a>
</li>
<li class="nav-item">
<a href="#comments" class="nav-link" data-action="sidebar-nav">Comments</a>
</li>
<li class="nav-item">
<a href="#lexical-scope" class="nav-link" data-action="sidebar-nav">Lexical Scoping and Variable Safety</a>
</li>
<li class="nav-item">
<a href="#conditionals" class="nav-link" data-action="sidebar-nav">If, Else, Unless, and Conditional Assignment</a>
</li>
<li class="nav-item">
<a href="#splats" class="nav-link" data-action="sidebar-nav">Splats, or Rest Parameters/Spread Syntax</a>
</li>
<li class="nav-item">
<a href="#loops" class="nav-link" data-action="sidebar-nav">Loops and Comprehensions</a>
</li>
<li class="nav-item">
<a href="#slices" class="nav-link" data-action="sidebar-nav">Array Slicing and Splicing</a>
</li>
<li class="nav-item">
<a href="#expressions" class="nav-link" data-action="sidebar-nav">Everything is an Expression</a>
</li>
<li class="nav-item">
<a href="#operators" class="nav-link" data-action="sidebar-nav">Operators and Aliases</a>
</li>
<li class="nav-item">
<a href="#existential-operator" class="nav-link" data-action="sidebar-nav">Existential Operator</a>
</li>
<li class="nav-item">
<a href="#destructuring" class="nav-link" data-action="sidebar-nav">Destructuring Assignment</a>
</li>
<li class="nav-item">
<a href="#chaining" class="nav-link" data-action="sidebar-nav">Chaining Function Calls</a>
</li>
<li class="nav-item">
<a href="#fat-arrow" class="nav-link" data-action="sidebar-nav">Bound (Fat Arrow) Functions</a>
</li>
<li class="nav-item">
<a href="#generators" class="nav-link" data-action="sidebar-nav">Generator Functions</a>
</li>
<li class="nav-item">
<a href="#async-functions" class="nav-link" data-action="sidebar-nav">Async Functions</a>
</li>
<li class="nav-item">
<a href="#classes" class="nav-link" data-action="sidebar-nav">Classes</a>
</li>
<li class="nav-item">
<a href="#prototypal-inheritance" class="nav-link" data-action="sidebar-nav">Prototypal Inheritance</a>
</li>
<li class="nav-item">
<a href="#switch" class="nav-link" data-action="sidebar-nav">Switch and Try/Catch</a>
</li>
<li class="nav-item">
<a href="#comparisons" class="nav-link" data-action="sidebar-nav">Chained Comparisons</a>
</li>
<li class="nav-item">
<a href="#regexes" class="nav-link" data-action="sidebar-nav">Block Regular Expressions</a>
</li>
<li class="nav-item">
<a href="#tagged-template-literals" class="nav-link" data-action="sidebar-nav">Tagged Template Literals</a>
</li>
<li class="nav-item">
<a href="#modules" class="nav-link" data-action="sidebar-nav">Modules</a>
</li>
<li class="nav-item">
<a href="#embedded" class="nav-link" data-action="sidebar-nav">Embedded JavaScript</a>
</li>
<li class="nav-item">
<a href="#jsx" class="nav-link" data-action="sidebar-nav">JSX</a>
</li>
</ul>
</li>
<li class="nav-item">
<a href="#type-annotations" class="nav-link" data-action="sidebar-nav">Type Annotations</a>
</li>
<li class="nav-item">
<a href="#literate" class="nav-link" data-action="sidebar-nav">Literate CoffeeScript</a>
</li>
<li class="nav-item">
<a href="#source-maps" class="nav-link" data-action="sidebar-nav">Source Maps</a>
</li>
<li class="nav-item">
<a href="#cake" class="nav-link" data-action="sidebar-nav">Cake, and Cakefiles</a>
</li>
<li class="nav-item">
<a href="#scripts" class="nav-link" data-action="sidebar-nav"><code>"text/coffeescript"</code> Script Tags</a>
</li>
<li class="nav-item">
<a href="test.html" class="nav-link" data-action="sidebar-nav">Browser-Based Tests</a>
</li>
<li class="nav-item">
<a href="#resources" class="nav-link" data-action="sidebar-nav">Resources</a>
<ul class="nav">
<li class="nav-item">
<a href="#books" class="nav-link" data-action="sidebar-nav">Books</a>
</li>
<li class="nav-item">
<a href="#screencasts" class="nav-link" data-action="sidebar-nav">Screencasts</a>
</li>
<li class="nav-item">
<a href="#examples" class="nav-link" data-action="sidebar-nav">Examples</a>
</li>
<li class="nav-item">
<a href="#chat" class="nav-link" data-action="sidebar-nav">Chat</a>
</li>
<li class="nav-item">
<a href="#annotated-source" class="nav-link" data-action="sidebar-nav">Annotated Source</a>
</li>
<li class="nav-item">
<a href="#contributing" class="nav-link" data-action="sidebar-nav">Contributing</a>
</li>
</ul>
</li>
<li class="nav-item">
<a href="#unsupported" class="nav-link" data-action="sidebar-nav">Unsupported ECMAScript Features</a>
<ul class="nav">
<li class="nav-item">
<a href="#unsupported-let-const" class="nav-link" data-action="sidebar-nav"><code>let</code> and <code>const</code></a>
</li>
<li class="nav-item">
<a href="#unsupported-named-functions" class="nav-link" data-action="sidebar-nav">Named Functions and Function Declarations</a>
</li>
<li class="nav-item">
<a href="#unsupported-get-set" class="nav-link" data-action="sidebar-nav"><code>get</code> and <code>set</code> Shorthand Syntax</a>
</li>
</ul>
</li>
<li class="nav-item">
<a href="#breaking-changes" class="nav-link" data-action="sidebar-nav">Breaking Changes From 1.x</a>
<ul class="nav">
<li class="nav-item">
<a href="#breaking-change-fat-arrow" class="nav-link" data-action="sidebar-nav">Bound (Fat Arrow) Functions</a>
</li>
<li class="nav-item">
<a href="#breaking-changes-default-values" class="nav-link" data-action="sidebar-nav">Default Values</a>
</li>
<li class="nav-item">
<a href="#breaking-changes-bound-generator-functions" class="nav-link" data-action="sidebar-nav">Bound Generator Functions</a>
</li>
<li class="nav-item">
<a href="#breaking-changes-classes" class="nav-link" data-action="sidebar-nav">Classes</a>
</li>
<li class="nav-item">
<a href="#breaking-changes-super-extends" class="nav-link" data-action="sidebar-nav"><code>super</code> and <code>extends</code></a>
</li>
<li class="nav-item">
<a href="#breaking-changes-jsx-and-the-less-than-and-greater-than-operators" class="nav-link" data-action="sidebar-nav">JSX and the <code>&lt;</code> and <code>&gt;</code> Operators</a>
</li>
<li class="nav-item">
<a href="#breaking-changes-literate-coffeescript" class="nav-link" data-action="sidebar-nav">Literate CoffeeScript Parsing</a>
</li>
<li class="nav-item">
<a href="#breaking-changes-argument-parsing-and-shebang-lines" class="nav-link" data-action="sidebar-nav">Argument Parsing and <code>#!</code> Lines</a>
</li>
</ul>
</li>
<li class="nav-item">
<a href="#changelog" class="nav-link" data-action="sidebar-nav">Changelog</a>
</li>
<li class="nav-item">
<a href="/v1/" class="nav-link" data-action="sidebar-nav">Version 1.x Documentation</a>
</li>
</ul>
</nav>

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 2.0.0-beta4
// Generated by CoffeeScript 2.0.3
(function() {
// This **Browser** compatibility layer extends core CoffeeScript functions
// to make things work smoothly when compiling code directly in the browser.

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 2.0.0-beta4
// Generated by CoffeeScript 2.0.3
(function() {
// `cake` is a simplified version of [Make](http://www.gnu.org/software/make/)
// ([Rake](http://rake.rubyforge.org/), [Jake](https://github.com/280north/jake))

View File

@@ -1,10 +1,11 @@
// Generated by CoffeeScript 2.0.0-beta4
// Generated by CoffeeScript 2.0.3
(function() {
// CoffeeScript can be used both on the server, as a command-line compiler based
// on Node.js/V8, or to run CoffeeScript directly in the browser. This module
// contains the main entry functions for tokenizing, parsing, and compiling
// source CoffeeScript into JavaScript.
var Lexer, SourceMap, base64encode, checkShebangLine, compile, formatSourcePosition, getSourceMap, helpers, lexer, packageJson, parser, sourceMaps, sources, withPrettyErrors;
var FILE_EXTENSIONS, Lexer, SourceMap, base64encode, checkShebangLine, compile, formatSourcePosition, getSourceMap, helpers, lexer, packageJson, parser, sourceMaps, sources, withPrettyErrors,
indexOf = [].indexOf;
({Lexer} = require('./lexer'));
@@ -21,7 +22,7 @@
// The current CoffeeScript version number.
exports.VERSION = packageJson.version;
exports.FILE_EXTENSIONS = ['.coffee', '.litcoffee', '.coffee.md'];
exports.FILE_EXTENSIONS = FILE_EXTENSIONS = ['.coffee', '.litcoffee', '.coffee.md'];
// Expose helpers for testing.
exports.helpers = helpers;
@@ -67,10 +68,10 @@
// a stack trace. Assuming that most of the time, code isnt throwing
// exceptions, its probably more efficient to compile twice only when we
// need a stack trace, rather than always generating a source map even when
// its not likely to be used. Save in form of `filename`: `(source)`
// its not likely to be used. Save in form of `filename`: [`(source)`]
sources = {};
// Also save source maps if generated, in form of `filename`: `(source map)`.
// Also save source maps if generated, in form of `(source)`: [`(source map)`].
sourceMaps = {};
// Compile CoffeeScript code to JavaScript, using the Coffee/Jison compiler.
@@ -83,17 +84,20 @@
// in which case this returns a `{js, v3SourceMap, sourceMap}`
// object, where sourceMap is a sourcemap.coffee#SourceMap object, handy for
// doing programmatic lookups.
exports.compile = compile = withPrettyErrors(function(code, options) {
var currentColumn, currentLine, encoded, extend, filename, fragment, fragments, generateSourceMap, header, i, j, js, len, len1, map, merge, newLines, ref, ref1, sourceMapDataURI, sourceURL, token, tokens, v3SourceMap;
({merge, extend} = helpers);
options = extend({}, options);
exports.compile = compile = withPrettyErrors(function(code, options = {}) {
var currentColumn, currentLine, encoded, filename, fragment, fragments, generateSourceMap, header, i, j, js, len, len1, map, newLines, ref, ref1, sourceMapDataURI, sourceURL, token, tokens, transpiler, transpilerOptions, transpilerOutput, v3SourceMap;
// Clone `options`, to avoid mutating the `options` object passed in.
options = Object.assign({}, options);
// Always generate a source map if no filename is passed in, since without a
// a filename we have no way to retrieve this source later in the event that
// we need to recompile it to get a source map for `prepareStackTrace`.
generateSourceMap = options.sourceMap || options.inlineMap || (options.filename == null);
filename = options.filename || '<anonymous>';
checkShebangLine(filename, code);
sources[filename] = code;
if (sources[filename] == null) {
sources[filename] = [];
}
sources[filename].push(code);
if (generateSourceMap) {
map = new SourceMap;
}
@@ -158,7 +162,33 @@
}
if (generateSourceMap) {
v3SourceMap = map.generate(options, code);
sourceMaps[filename] = map;
if (sourceMaps[filename] == null) {
sourceMaps[filename] = [];
}
sourceMaps[filename].push(map);
}
if (options.transpile) {
if (typeof options.transpile !== 'object') {
// This only happens if run via the Node API and `transpile` is set to
// something other than an object.
throw new Error('The transpile option must be given an object with options to pass to Babel');
}
// Get the reference to Babel that we have been passed if this compiler
// is run via the CLI or Node API.
transpiler = options.transpile.transpile;
delete options.transpile.transpile;
transpilerOptions = Object.assign({}, options.transpile);
// See https://github.com/babel/babel/issues/827#issuecomment-77573107:
// Babel can take a v3 source map object as input in `inputSourceMap`
// and it will return an *updated* v3 source map object in its output.
if (v3SourceMap && (transpilerOptions.inputSourceMap == null)) {
transpilerOptions.inputSourceMap = v3SourceMap;
}
transpilerOutput = transpiler(js, transpilerOptions);
js = transpilerOutput.code;
if (v3SourceMap && transpilerOutput.map) {
v3SourceMap = transpilerOutput.map;
}
}
if (options.inlineMap) {
encoded = base64encode(JSON.stringify(v3SourceMap));
@@ -311,17 +341,43 @@
}
};
getSourceMap = function(filename) {
var answer;
if (sourceMaps[filename] != null) {
return sourceMaps[filename];
// CoffeeScript compiled in a browser may get compiled with `options.filename`
// of `<anonymous>`, but the browser may request the stack trace with the
// filename of the script file.
getSourceMap = function(filename, line, column) {
var answer, i, map, ref, ref1, sourceLocation;
if (!(filename === '<anonymous>' || (ref = filename.slice(filename.lastIndexOf('.')), indexOf.call(FILE_EXTENSIONS, ref) >= 0))) {
// Skip files that we didnt compile, like Node system files that appear in
// the stack trace, as they never have source maps.
return null;
}
if (filename !== '<anonymous>' && (sourceMaps[filename] != null)) {
return sourceMaps[filename][sourceMaps[filename].length - 1];
// CoffeeScript compiled in a browser or via `CoffeeScript.compile` or `.run`
// may get compiled with `options.filename` thats missing, which becomes
// `<anonymous>`; but the runtime might request the stack trace with the
// filename of the script file. See if we have a source map cached under
// `<anonymous>` that matches the error.
} else if (sourceMaps['<anonymous>'] != null) {
return sourceMaps['<anonymous>'];
} else if (sources[filename] != null) {
answer = compile(sources[filename], {
ref1 = sourceMaps['<anonymous>'];
// Work backwards from the most recent anonymous source maps, until we find
// one that works. This isnt foolproof; there is a chance that multiple
// source maps will have line/column pairs that match. But we have no other
// way to match them. `frame.getFunction().toString()` doesnt always work,
// and its not foolproof either.
for (i = ref1.length - 1; i >= 0; i += -1) {
map = ref1[i];
sourceLocation = map.sourceLocation([line - 1, column - 1]);
if (((sourceLocation != null ? sourceLocation[0] : void 0) != null) && (sourceLocation[1] != null)) {
return map;
}
}
}
// If all else fails, recompile this source to get a source map. We need the
// previous section (for `<anonymous>`) despite this option, because after it
// gets compiled we will still need to look it up from
// `sourceMaps['<anonymous>']` in order to find and return it. Thats why we
// start searching from the end in the previous block, because most of the
// time the source map we want is the last one.
if (sources[filename] != null) {
answer = compile(sources[filename][sources[filename].length - 1], {
filename: filename,
sourceMap: true,
literate: helpers.isLiterate(filename)
@@ -340,7 +396,7 @@
var frame, frames, getSourceMapping;
getSourceMapping = function(filename, line, column) {
var answer, sourceMap;
sourceMap = getSourceMap(filename);
sourceMap = getSourceMap(filename, line, column);
if (sourceMap != null) {
answer = sourceMap.sourceLocation([line - 1, column - 1]);
}

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 2.0.0-beta4
// Generated by CoffeeScript 2.0.3
(function() {
// The `coffee` utility. Handles command-line compilation of CoffeeScript
// into various forms: saved into `.js` files or printed to stdout
@@ -45,7 +45,7 @@
BANNER = 'Usage: coffee [options] path/to/script.coffee [args]\n\nIf called without options, `coffee` will run your script.';
// The list of all the valid option flags that `coffee` knows how to handle.
SWITCHES = [['-b', '--bare', 'compile without a top-level function wrapper'], ['-c', '--compile', 'compile to JavaScript and save as .js files'], ['-e', '--eval', 'pass a string from the command line as input'], ['-h', '--help', 'display this help message'], ['-i', '--interactive', 'run an interactive CoffeeScript REPL'], ['-j', '--join [FILE]', 'concatenate the source CoffeeScript before compiling'], ['-m', '--map', 'generate source map and save as .js.map files'], ['-M', '--inline-map', 'generate source map and include it directly in output'], ['-n', '--nodes', 'print out the parse tree that the parser produces'], ['--nodejs [ARGS]', 'pass options directly to the "node" binary'], ['--no-header', 'suppress the "Generated by" header'], ['-o', '--output [DIR]', 'set the output directory for compiled JavaScript'], ['-p', '--print', 'print out the compiled JavaScript'], ['-r', '--require [MODULE*]', 'require the given module before eval or REPL'], ['-s', '--stdio', 'listen for and compile scripts over stdio'], ['-l', '--literate', 'treat stdio as literate style coffeescript'], ['-t', '--tokens', 'print out the tokens that the lexer/rewriter produce'], ['-v', '--version', 'display the version number'], ['-w', '--watch', 'watch scripts for changes and rerun commands']];
SWITCHES = [['-b', '--bare', 'compile without a top-level function wrapper'], ['-c', '--compile', 'compile to JavaScript and save as .js files'], ['-e', '--eval', 'pass a string from the command line as input'], ['-h', '--help', 'display this help message'], ['-i', '--interactive', 'run an interactive CoffeeScript REPL'], ['-j', '--join [FILE]', 'concatenate the source CoffeeScript before compiling'], ['-m', '--map', 'generate source map and save as .js.map files'], ['-M', '--inline-map', 'generate source map and include it directly in output'], ['-n', '--nodes', 'print out the parse tree that the parser produces'], ['--nodejs [ARGS]', 'pass options directly to the "node" binary'], ['--no-header', 'suppress the "Generated by" header'], ['-o', '--output [PATH]', 'set the output path or path/filename for compiled JavaScript'], ['-p', '--print', 'print out the compiled JavaScript'], ['-r', '--require [MODULE*]', 'require the given module before eval or REPL'], ['-s', '--stdio', 'listen for and compile scripts over stdio'], ['-l', '--literate', 'treat stdio as literate style coffeescript'], ['-t', '--transpile', 'pipe generated JavaScript through Babel'], ['--tokens', 'print out the tokens that the lexer/rewriter produce'], ['-v', '--version', 'display the version number'], ['-w', '--watch', 'watch scripts for changes and rerun commands']];
// Top-level objects shared by all the functions.
opts = {};
@@ -68,7 +68,7 @@
// Many flags cause us to divert before compiling anything. Flags passed after
// `--` will be passed verbatim to your script as arguments in `process.argv`
exports.run = function() {
var err, i, len, literals, ref, replCliOpts, results, source;
var err, i, len, literals, outputBasename, ref, replCliOpts, results, source;
optionParser = buildCSOptionParser();
try {
parseOptions();
@@ -92,6 +92,7 @@
opts.prelude = makePrelude(opts.require);
}
replCliOpts.prelude = opts.prelude;
replCliOpts.transpile = opts.transpile;
if (opts.nodejs) {
return forkNode();
}
@@ -117,7 +118,16 @@
process.argv = process.argv.slice(0, 2).concat(literals);
process.argv[0] = 'coffee';
if (opts.output) {
opts.output = path.resolve(opts.output);
outputBasename = path.basename(opts.output);
if (indexOf.call(outputBasename, '.') >= 0 && (outputBasename !== '.' && outputBasename !== '..') && !helpers.ends(opts.output, path.sep)) {
// An output filename was specified, e.g. `/dist/scripts.js`.
opts.outputFilename = outputBasename;
opts.outputPath = path.resolve(path.dirname(opts.output));
} else {
// An output path was specified, e.g. `/dist`.
opts.outputFilename = null;
opts.outputPath = path.resolve(opts.output);
}
}
if (opts.join) {
opts.join = path.resolve(opts.join);
@@ -135,12 +145,12 @@
makePrelude = function(requires) {
return requires.map(function(module) {
var _, match, name;
var full, match, name;
if (match = module.match(/^(.*)=(.*)$/)) {
[_, name, module] = match;
[full, name, module] = match;
}
name || (name = helpers.baseFileName(module, true, useWinPathSep));
return `${name} = require('${module}')`;
return `global['${name}'] = require('${module}')`;
}).join(';');
};
@@ -235,43 +245,43 @@
};
// Compile a single source script, containing the given code, according to the
// requested options. If evaluating the script directly sets `__filename`,
// requested options. If evaluating the script directly, set `__filename`,
// `__dirname` and `module.filename` to be correct relative to the script's path.
compileScript = function(file, input, base = null) {
var compiled, err, message, o, options, t, task;
o = opts;
var compiled, err, message, options, saveTo, task;
options = compileOptions(file, base);
try {
t = task = {file, input, options};
task = {file, input, options};
CoffeeScript.emit('compile', task);
if (o.tokens) {
return printTokens(CoffeeScript.tokens(t.input, t.options));
} else if (o.nodes) {
return printLine(CoffeeScript.nodes(t.input, t.options).toString().trim());
} else if (o.run) {
if (opts.tokens) {
return printTokens(CoffeeScript.tokens(task.input, task.options));
} else if (opts.nodes) {
return printLine(CoffeeScript.nodes(task.input, task.options).toString().trim());
} else if (opts.run) {
CoffeeScript.register();
if (opts.prelude) {
CoffeeScript.eval(opts.prelude, t.options);
CoffeeScript.eval(opts.prelude, task.options);
}
return CoffeeScript.run(t.input, t.options);
} else if (o.join && t.file !== o.join) {
return CoffeeScript.run(task.input, task.options);
} else if (opts.join && task.file !== opts.join) {
if (helpers.isLiterate(file)) {
t.input = helpers.invertLiterate(t.input);
task.input = helpers.invertLiterate(task.input);
}
sourceCode[sources.indexOf(t.file)] = t.input;
sourceCode[sources.indexOf(task.file)] = task.input;
return compileJoin();
} else {
compiled = CoffeeScript.compile(t.input, t.options);
t.output = compiled;
if (o.map) {
t.output = compiled.js;
t.sourceMap = compiled.v3SourceMap;
compiled = CoffeeScript.compile(task.input, task.options);
task.output = compiled;
if (opts.map) {
task.output = compiled.js;
task.sourceMap = compiled.v3SourceMap;
}
CoffeeScript.emit('success', task);
if (o.print) {
return printLine(t.output.trim());
} else if (o.compile || o.map) {
return writeJs(base, t.file, t.output, options.jsPath, t.sourceMap);
if (opts.print) {
return printLine(task.output.trim());
} else if (opts.compile || opts.map) {
saveTo = opts.outputFilename && sources.length === 1 ? path.join(opts.outputPath, opts.outputFilename) : options.jsPath;
return writeJs(base, task.file, task.output, saveTo, task.sourceMap);
}
}
} catch (error) {
@@ -281,7 +291,7 @@
return;
}
message = (err != null ? err.stack : void 0) || `${err}`;
if (o.watch) {
if (opts.watch) {
return printLine(message + '\x07');
} else {
printWarn(message);
@@ -294,6 +304,10 @@
// and write them back to **stdout**.
compileStdio = function() {
var buffers, stdin;
if (opts.map) {
console.error('--stdio and --map cannot be used together');
process.exit(1);
}
buffers = [];
stdin = process.openStdin();
stdin.on('data', function(buffer) {
@@ -486,13 +500,7 @@
var basename, dir, srcDir;
basename = helpers.baseFileName(source, true, useWinPathSep);
srcDir = path.dirname(source);
if (!opts.output) {
dir = srcDir;
} else if (source === base) {
dir = opts.output;
} else {
dir = path.join(opts.output, path.relative(base, srcDir));
}
dir = !opts.outputPath ? srcDir : source === base ? opts.outputPath : path.join(opts.outputPath, path.relative(base, srcDir));
return path.join(dir, basename + extension);
};
@@ -526,7 +534,7 @@
// same directory as the `.js` file.
writeJs = function(base, sourcePath, js, jsPath, generatedSourceMap = null) {
var compile, jsDir, sourceMapPath;
sourceMapPath = outputPath(sourcePath, base, ".js.map");
sourceMapPath = `${jsPath}.map`;
jsDir = path.dirname(jsPath);
compile = function() {
if (opts.compile) {
@@ -603,11 +611,49 @@
// The compile-time options to pass to the CoffeeScript compiler.
compileOptions = function(filename, base) {
var answer, cwd, jsDir, jsPath;
if (opts.transpile) {
try {
// The user has requested that the CoffeeScript compiler also transpile
// via Babel. We dont include Babel as a dependency because we want to
// avoid dependencies in general, and most users probably wont be relying
// on us to transpile for them; we assume most users will probably either
// run CoffeeScripts output without transpilation (modern Node or evergreen
// browsers) or use a proper build chain like Gulp or Webpack.
require('babel-core');
} catch (error) {
// Give appropriate instructions depending on whether `coffee` was run
// locally or globally.
if (require.resolve('.').indexOf(process.cwd()) === 0) {
console.error('To use --transpile, you must have babel-core installed:\n npm install --save-dev babel-core\nAnd you must save options to configure Babel in one of the places it looks to find its options.\nSee http://coffeescript.org/#transpilation');
} else {
console.error('To use --transpile with globally-installed CoffeeScript, you must have babel-core installed globally:\n npm install --global babel-core\nAnd you must save options to configure Babel in one of the places it looks to find its options, relative to the file being compiled or to the current folder.\nSee http://coffeescript.org/#transpilation');
}
process.exit(1);
}
if (typeof opts.transpile !== 'object') {
opts.transpile = {};
}
// Pass a reference to Babel into the compiler, so that the transpile option
// is available for the CLI. We need to do this so that tools like Webpack
// can `require('coffeescript')` and build correctly, without trying to
// require Babel.
opts.transpile.transpile = CoffeeScript.transpile;
// Babel searches for its options (a `.babelrc` file, a `.babelrc.js` file,
// a `package.json` file with a `babel` key, etc.) relative to the path
// given to it in its `filename` option. Make sure we have a path to pass
// along.
if (!opts.transpile.filename) {
opts.transpile.filename = filename || path.resolve(base || process.cwd(), '<anonymous>');
}
} else {
opts.transpile = false;
}
answer = {
filename,
filename: filename,
literate: opts.literate || helpers.isLiterate(filename),
bare: opts.bare,
header: opts.compile && !opts['no-header'],
transpile: opts.transpile,
sourceMap: opts.map,
inlineMap: opts['inline-map']
};

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 2.0.0-beta4
// Generated by CoffeeScript 2.0.3
(function() {
// The CoffeeScript parser is generated by [Jison](https://github.com/zaach/jison)
// from this grammar file. Jison is a bottom-up parser generator, similar in
@@ -389,7 +389,8 @@
function() {
return new Code($2,
$5,
$4);
$4,
LOC(1)(new Literal($1)));
}),
o('FuncGlyph Block',
function() {
@@ -487,6 +488,10 @@
function() {
return $1.add($2);
}),
o('Code Accessor',
function() {
return new Value($1).add($2);
}),
o('ThisProperty')
],
// Everything that can be assigned to.
@@ -817,6 +822,10 @@
function() {
return new ExportDefaultDeclaration($3);
}),
o('EXPORT DEFAULT INDENT Object OUTDENT',
function() {
return new ExportDefaultDeclaration(new Value($4));
}),
o('EXPORT EXPORT_ALL FROM String',
function() {
return new ExportAllDeclaration(new Literal($2),

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 2.0.0-beta4
// Generated by CoffeeScript 2.0.3
(function() {
// This file contains the common helper functions that we'd like to share among
// the **Lexer**, **Rewriter**, and the **Nodes**. Merge objects, flatten

View File

@@ -1,7 +1,7 @@
// Generated by CoffeeScript 2.0.0-beta4
// Generated by CoffeeScript 2.0.3
(function() {
// Node.js Implementation
var CoffeeScript, compile, ext, fn, fs, helpers, i, len, path, ref, vm,
var CoffeeScript, ext, fn, fs, helpers, i, len, path, ref, universalCompile, vm,
hasProp = {}.hasOwnProperty;
CoffeeScript = require('./coffeescript');
@@ -14,7 +14,32 @@
helpers = CoffeeScript.helpers;
compile = CoffeeScript.compile;
CoffeeScript.transpile = function(js, options) {
var babel;
try {
babel = require('babel-core');
} catch (error) {
// This error is only for Node, as CLI users will see a different error
// earlier if they dont have Babel installed.
throw new Error('To use the transpile option, you must have the \'babel-core\' module installed');
}
return babel.transform(js, options);
};
// The `compile` method shared by the CLI, Node and browser APIs.
universalCompile = CoffeeScript.compile;
// The `compile` method particular to the Node API.
CoffeeScript.compile = function(code, options) {
// Pass a reference to Babel into the compiler, so that the transpile option
// is available in the Node API. We need to do this so that tools like Webpack
// can `require('coffeescript')` and build correctly, without trying to
// require Babel.
if (options != null ? options.transpile : void 0) {
options.transpile.transpile = CoffeeScript.transpile;
}
return universalCompile.call(CoffeeScript, code, options);
};
// Compile and execute a string of CoffeeScript (on the server), correctly
// setting `__filename`, `__dirname`, and relative `require()`.
@@ -28,9 +53,11 @@
// Assign paths for node_modules loading
dir = options.filename != null ? path.dirname(fs.realpathSync(options.filename)) : fs.realpathSync('.');
mainModule.paths = require('module')._nodeModulePaths(dir);
// Save the options for compiling child imports.
mainModule.options = options;
// Compile.
if (!helpers.isCoffee(mainModule.filename) || require.extensions) {
answer = compile(code, options);
answer = CoffeeScript.compile(code, options);
code = (ref = answer.js) != null ? ref : answer;
}
return mainModule._compile(code, mainModule.filename);
@@ -95,7 +122,7 @@
o[k] = v;
}
o.bare = true; // ensure return value
js = compile(code, o);
js = CoffeeScript.compile(code, o);
if (sandbox === global) {
return vm.runInThisContext(js);
} else {
@@ -122,19 +149,19 @@
}
}
CoffeeScript._compileFile = function(filename, sourceMap = false, inlineMap = false) {
CoffeeScript._compileFile = function(filename, options = {}) {
var answer, err, raw, stripped;
raw = fs.readFileSync(filename, 'utf8');
// Strip the Unicode byte order mark, if this file begins with one.
stripped = raw.charCodeAt(0) === 0xFEFF ? raw.substring(1) : raw;
options = Object.assign({}, options, {
filename: filename,
literate: helpers.isLiterate(filename),
sourceFiles: [filename],
inlineMap: true // Always generate a source map, so that stack traces line up.
});
try {
answer = compile(stripped, {
filename,
sourceMap,
inlineMap,
sourceFiles: [filename],
literate: helpers.isLiterate(filename)
});
answer = CoffeeScript.compile(stripped, options);
} catch (error) {
err = error;
// As the filename and code of a dynamically loaded file will be different

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 2.0.0-beta4
// Generated by CoffeeScript 2.0.3
(function() {
// The CoffeeScript Lexer. Uses a series of token-matching regexes to attempt
// matches against the beginning of the source code. When a match is found,
@@ -111,7 +111,7 @@
// referenced as property names here, so you can still do `jQuery.is()` even
// though `is` means `===` otherwise.
identifierToken() {
var alias, colon, colonOffset, colonToken, id, idLength, inCSXTag, input, match, poppedToken, prev, prevprev, ref, ref1, ref2, ref3, ref4, ref5, ref6, ref7, regExSuper, regex, sup, tag, tagToken;
var alias, colon, colonOffset, colonToken, id, idLength, inCSXTag, input, match, poppedToken, prev, prevprev, ref, ref1, ref2, ref3, ref4, ref5, ref6, ref7, ref8, regExSuper, regex, sup, tag, tagToken;
inCSXTag = this.atCSXTag();
regex = inCSXTag ? CSX_ATTRIBUTE : IDENTIFIER;
if (!(match = regex.exec(this.chunk))) {
@@ -132,19 +132,28 @@
if (id === 'as' && this.seenImport) {
if (this.value() === '*') {
this.tokens[this.tokens.length - 1][0] = 'IMPORT_ALL';
} else if (ref = this.value(), indexOf.call(COFFEE_KEYWORDS, ref) >= 0) {
this.tokens[this.tokens.length - 1][0] = 'IDENTIFIER';
} else if (ref = this.value(true), indexOf.call(COFFEE_KEYWORDS, ref) >= 0) {
prev = this.prev();
[prev[0], prev[1]] = ['IDENTIFIER', this.value(true)];
}
if ((ref1 = this.tag()) === 'DEFAULT' || ref1 === 'IMPORT_ALL' || ref1 === 'IDENTIFIER') {
this.token('AS', id);
return id.length;
}
}
if (id === 'as' && this.seenExport && ((ref2 = this.tag()) === 'IDENTIFIER' || ref2 === 'DEFAULT')) {
this.token('AS', id);
return id.length;
if (id === 'as' && this.seenExport) {
if ((ref2 = this.tag()) === 'IDENTIFIER' || ref2 === 'DEFAULT') {
this.token('AS', id);
return id.length;
}
if (ref3 = this.value(true), indexOf.call(COFFEE_KEYWORDS, ref3) >= 0) {
prev = this.prev();
[prev[0], prev[1]] = ['IDENTIFIER', this.value(true)];
this.token('AS', id);
return id.length;
}
}
if (id === 'default' && this.seenExport && ((ref3 = this.tag()) === 'EXPORT' || ref3 === 'AS')) {
if (id === 'default' && this.seenExport && ((ref4 = this.tag()) === 'EXPORT' || ref4 === 'AS')) {
this.token('DEFAULT', id);
return id.length;
}
@@ -156,10 +165,10 @@
return sup.length + 3;
}
prev = this.prev();
tag = colon || (prev != null) && (((ref4 = prev[0]) === '.' || ref4 === '?.' || ref4 === '::' || ref4 === '?::') || !prev.spaced && prev[0] === '@') ? 'PROPERTY' : 'IDENTIFIER';
tag = colon || (prev != null) && (((ref5 = prev[0]) === '.' || ref5 === '?.' || ref5 === '::' || ref5 === '?::') || !prev.spaced && prev[0] === '@') ? 'PROPERTY' : 'IDENTIFIER';
if (tag === 'IDENTIFIER' && (indexOf.call(JS_KEYWORDS, id) >= 0 || indexOf.call(COFFEE_KEYWORDS, id) >= 0) && !(this.exportSpecifierList && indexOf.call(COFFEE_KEYWORDS, id) >= 0)) {
tag = id.toUpperCase();
if (tag === 'WHEN' && (ref5 = this.tag(), indexOf.call(LINE_BREAK, ref5) >= 0)) {
if (tag === 'WHEN' && (ref6 = this.tag(), indexOf.call(LINE_BREAK, ref6) >= 0)) {
tag = 'LEADING_WHEN';
} else if (tag === 'FOR') {
this.seenFor = true;
@@ -190,11 +199,11 @@
// what CoffeeScript would normally interpret as calls to functions named
// `get` or `set`, i.e. `get({foo: function () {}})`.
} else if (tag === 'PROPERTY' && prev) {
if (prev.spaced && (ref6 = prev[0], indexOf.call(CALLABLE, ref6) >= 0) && /^[gs]et$/.test(prev[1])) {
if (prev.spaced && (ref7 = prev[0], indexOf.call(CALLABLE, ref7) >= 0) && /^[gs]et$/.test(prev[1]) && this.tokens[this.tokens.length - 2][0] !== '.') {
this.error(`'${prev[1]}' cannot be used as a keyword, or as a function call without parentheses`, prev[2]);
} else {
prevprev = this.tokens[this.tokens.length - 2];
if (((ref7 = prev[0]) === '@' || ref7 === 'THIS') && prevprev && prevprev.spaced && /^[gs]et$/.test(prevprev[1]) && this.tokens[this.tokens.length - 3][0] !== '.') {
if (((ref8 = prev[0]) === '@' || ref8 === 'THIS') && prevprev && prevprev.spaced && /^[gs]et$/.test(prevprev[1]) && this.tokens[this.tokens.length - 3][0] !== '.') {
this.error(`'${prevprev[1]}' cannot be used as a keyword, or as a function call without parentheses`, prevprev[2]);
}
}
@@ -204,7 +213,7 @@
length: id.length
});
}
if (tag !== 'PROPERTY') {
if (!(tag === 'PROPERTY' || this.exportSpecifierList)) {
if (indexOf.call(COFFEE_ALIASES, id) >= 0) {
alias = id;
id = COFFEE_ALIAS_MAP[id];
@@ -672,9 +681,7 @@
if (dent) {
this.outdebt -= moveOut;
}
while (this.value() === ';') {
this.tokens.pop();
}
this.suppressSemicolons();
if (!(this.tag() === 'TERMINATOR' || noNewlines)) {
this.token('TERMINATOR', '\n', outdentLength, 0);
}
@@ -703,9 +710,7 @@
// Generate a newline token. Consecutive newlines get merged together.
newlineToken(offset) {
while (this.value() === ';') {
this.tokens.pop();
}
this.suppressSemicolons();
if (this.tag() !== 'TERMINATOR') {
this.token('TERMINATOR', '\n', offset, 0);
}
@@ -844,7 +849,7 @@
// here. `;` and newlines are both treated as a `TERMINATOR`, we distinguish
// parentheses that indicate a method call from regular parentheses, and so on.
literalToken() {
var match, message, origin, prev, ref, ref1, ref2, ref3, skipToken, tag, token, value;
var match, message, origin, prev, ref, ref1, ref2, ref3, ref4, skipToken, tag, token, value;
if (match = OPERATOR.exec(this.chunk)) {
[value] = match;
if (CODE.test(value)) {
@@ -884,9 +889,12 @@
this.exportSpecifierList = false;
}
if (value === ';') {
if (ref2 = prev != null ? prev[0] : void 0, indexOf.call(['=', ...UNFINISHED], ref2) >= 0) {
this.error('unexpected ;');
}
this.seenFor = this.seenImport = this.seenExport = false;
tag = 'TERMINATOR';
} else if (value === '*' && prev[0] === 'EXPORT') {
} else if (value === '*' && (prev != null ? prev[0] : void 0) === 'EXPORT') {
tag = 'EXPORT_ALL';
} else if (indexOf.call(MATH, value) >= 0) {
tag = 'MATH';
@@ -902,13 +910,13 @@
tag = 'SHIFT';
} else if (value === '?' && (prev != null ? prev.spaced : void 0)) {
tag = 'BIN?';
} else if (prev && !prev.spaced) {
if (value === '(' && (ref2 = prev[0], indexOf.call(CALLABLE, ref2) >= 0)) {
} else if (prev) {
if (value === '(' && !prev.spaced && (ref3 = prev[0], indexOf.call(CALLABLE, ref3) >= 0)) {
if (prev[0] === '?') {
prev[0] = 'FUNC_EXIST';
}
tag = 'CALL_START';
} else if (value === '[' && (ref3 = prev[0], indexOf.call(INDEXABLE, ref3) >= 0)) {
} else if (value === '[' && (((ref4 = prev[0], indexOf.call(INDEXABLE, ref4) >= 0) && !prev.spaced) || (prev[0] === '::'))) { // `.prototype` cant be a method you can call.
tag = 'INDEX_START';
switch (prev[0]) {
case '?':
@@ -1089,7 +1097,7 @@
// of `'NEOSTRING'`s are converted using `fn` and turned into strings using
// `options` first.
mergeInterpolationTokens(tokens, options, fn) {
var converted, firstEmptyStringIndex, firstIndex, i, j, lastToken, len, locationToken, lparen, plusToken, rparen, tag, token, tokensToPush, value;
var converted, firstEmptyStringIndex, firstIndex, i, j, k, lastToken, len, len1, locationToken, lparen, placeholderToken, plusToken, rparen, tag, token, tokensToPush, val, value;
if (tokens.length > 1) {
lparen = this.token('STRING_START', '(', 0, 0);
}
@@ -1100,8 +1108,32 @@
switch (tag) {
case 'TOKENS':
if (value.length === 2) {
// Optimize out empty interpolations (an empty pair of parentheses).
continue;
if (!(value[0].comments || value[1].comments)) {
// Optimize out empty interpolations (an empty pair of parentheses).
continue;
}
// There are comments (and nothing else) in this interpolation.
if (this.csxDepth === 0) {
// This is an interpolated string, not a CSX tag; and for whatever
// reason `` `a${/*test*/}b` `` is invalid JS. So compile to
// `` `a${/*test*/''}b` `` instead.
placeholderToken = this.makeToken('STRING', "''");
} else {
placeholderToken = this.makeToken('JS', '');
}
// Use the same location data as the first parenthesis.
placeholderToken[2] = value[0][2];
for (k = 0, len1 = value.length; k < len1; k++) {
val = value[k];
if (!val.comments) {
continue;
}
if (placeholderToken.comments == null) {
placeholderToken.comments = [];
}
placeholderToken.comments.push(...val.comments);
}
value.splice(1, 0, placeholderToken);
}
// Push all the tokens in the fake `'TOKENS'` token. These already have
// sane location data.
@@ -1252,10 +1284,14 @@
}
// Peek at the last value in the token stream.
value() {
var ref, token;
value(useOrigin = false) {
var ref, ref1, token;
ref = this.tokens, token = ref[ref.length - 1];
return token != null ? token[1] : void 0;
if (useOrigin && ((token != null ? token.origin : void 0) != null)) {
return (ref1 = token.origin) != null ? ref1[1] : void 0;
} else {
return token != null ? token[1] : void 0;
}
}
// Get the previous token in the token stream.
@@ -1383,6 +1419,20 @@
return `${options.delimiter}${body}${options.delimiter}`;
}
suppressSemicolons() {
var ref, ref1, results;
results = [];
while (this.value() === ';') {
this.tokens.pop();
if (ref = (ref1 = this.prev()) != null ? ref1[0] : void 0, indexOf.call(['=', ...UNFINISHED], ref) >= 0) {
results.push(this.error('unexpected ;'));
} else {
results.push(void 0);
}
}
return results;
}
// Throws an error at either a given offset from the current chunk or at the
// location of a token (`token[2]`).
error(message, options = {}) {
@@ -1635,6 +1685,6 @@
INDENTABLE_CLOSERS = [')', '}', ']'];
// Tokens that, when appearing at the end of a line, suppress a following TERMINATOR/INDENT token
UNFINISHED = ['\\', '.', '?.', '?::', 'UNARY', 'MATH', 'UNARY_MATH', '+', '-', '**', 'SHIFT', 'RELATION', 'COMPARE', '&', '^', '|', '&&', '||', 'BIN?', 'EXTENDS', 'DEFAULT'];
UNFINISHED = ['\\', '.', '?.', '?::', 'UNARY', 'MATH', 'UNARY_MATH', '+', '-', '**', 'SHIFT', 'RELATION', 'COMPARE', '&', '^', '|', '&&', '||', 'BIN?', 'EXTENDS'];
}).call(this);

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 2.0.0-beta4
// Generated by CoffeeScript 2.0.3
(function() {
// `nodes.coffee` contains all of the node classes for the syntax tree. Most
// nodes are created as the result of actions in the [grammar](grammar.html),
@@ -145,6 +145,10 @@
return fragments;
}
compileToFragmentsWithoutComments(o, lvl) {
return this.compileWithoutComments(o, lvl, 'compileToFragments');
}
// Statements converted into expressions via closure-wrapping share a scope
// object with their parent closure, to preserve the expected lexical scope.
compileClosure(o) {
@@ -233,6 +237,9 @@
// `compileToFragments` method has logic for outputting comments.
unshiftCommentFragment(commentFragment);
} else {
if (fragments.length === 0) {
fragments.push(this.makeCode(''));
}
if (commentFragment.unshift) {
if ((base1 = fragments[0]).precedingComments == null) {
base1.precedingComments = [];
@@ -697,17 +704,18 @@
ref1 = this.expressions;
for (index = j = 0, len1 = ref1.length; j < len1; index = ++j) {
node = ref1[index];
node = node.unwrapAll();
if (node.hoisted) {
// This is a hoisted expression.
// We want to compile this and ignore the result.
node.compileToFragments(o);
continue;
}
node = node.unfoldSoak(o) || node;
if (node instanceof Block) {
// This is a nested block. We dont do anything special here like
// enclose it in a new scope; we just compile the statements in this
// block along with our own.
compiledNodes.push(node.compileNode(o));
} else if (node.hoisted) {
// This is a hoisted expression.
// We want to compile this and ignore the result.
node.compileToFragments(o);
} else if (top) {
node.front = true;
fragments = node.compileToFragments(o);
@@ -770,7 +778,7 @@
// Compile the expressions body for the contents of a function, with
// declarations of all inner variables pushed up to the top.
compileWithDeclarations(o) {
var assigns, declars, exp, fragments, i, j, len1, post, ref1, rest, scope, spaced;
var assigns, declaredVariable, declaredVariables, declaredVariablesIndex, declars, exp, fragments, i, j, k, len1, len2, post, ref1, rest, scope, spaced;
fragments = [];
post = [];
ref1 = this.expressions;
@@ -801,7 +809,17 @@
}
fragments.push(this.makeCode(`${this.tab}var `));
if (declars) {
fragments.push(this.makeCode(scope.declaredVariables().join(', ')));
declaredVariables = scope.declaredVariables();
for (declaredVariablesIndex = k = 0, len2 = declaredVariables.length; k < len2; declaredVariablesIndex = ++k) {
declaredVariable = declaredVariables[declaredVariablesIndex];
fragments.push(this.makeCode(declaredVariable));
if (Object.prototype.hasOwnProperty.call(o.scope.comments, declaredVariable)) {
fragments.push(...o.scope.comments[declaredVariable]);
}
if (declaredVariablesIndex !== declaredVariables.length - 1) {
fragments.push(this.makeCode(', '));
}
}
}
if (assigns) {
if (declars) {
@@ -1043,17 +1061,19 @@
exports.StringLiteral = StringLiteral = class StringLiteral extends Literal {
compileNode(o) {
var res;
return res = this.csx ? [this.makeCode(this.unquote(true))] : super.compileNode();
return res = this.csx ? [this.makeCode(this.unquote(true, true))] : super.compileNode();
}
unquote(literal) {
unquote(doubleQuote = false, newLine = false) {
var unquoted;
unquoted = this.value.slice(1, -1);
if (literal) {
return unquoted.replace(/\\n/g, '\n').replace(/\\"/g, '"');
} else {
return unquoted;
if (doubleQuote) {
unquoted = unquoted.replace(/\\"/g, '"');
}
if (newLine) {
unquoted = unquoted.replace(/\\n/g, '\n');
}
return unquoted;
}
};
@@ -1246,6 +1266,8 @@
this[tag] = true;
}
this.isDefaultValue = isDefaultValue;
// If this is a `@foo =` assignment, if there are comments on `@` move them
// to be on `foo`.
if (((ref1 = this.base) != null ? ref1.comments : void 0) && this.base instanceof ThisLiteral && (((ref2 = this.properties[0]) != null ? ref2.name : void 0) != null)) {
moveComments(this.base, this.properties[0].name);
}
@@ -1402,7 +1424,7 @@
}
for (j = 0, len1 = props.length; j < len1; j++) {
prop = props[j];
fragments.push(...prop.compileToFragments(o));
fragments.push(...(prop.compileToFragments(o)));
}
return fragments;
}
@@ -1462,12 +1484,12 @@
exports.HereComment = HereComment = class HereComment extends Base {
constructor({
content: content1,
newLine: newLine,
newLine: newLine1,
unshift: unshift
}) {
super();
this.content = content1;
this.newLine = newLine;
this.newLine = newLine1;
this.unshift = unshift;
}
@@ -1509,12 +1531,12 @@
exports.LineComment = LineComment = class LineComment extends Base {
constructor({
content: content1,
newLine: newLine,
newLine: newLine1,
unshift: unshift
}) {
super();
this.content = content1;
this.newLine = newLine;
this.newLine = newLine1;
this.unshift = unshift;
}
@@ -1548,6 +1570,10 @@
this.variable.error("literal is not a function");
}
this.csx = this.variable.base instanceof CSXTag;
// `@variable` never gets output as a result of this node getting created as
// part of `RegexWithInterpolations`, so for that case move any comments to
// the `args` property that gets passed into `RegexWithInterpolations` via
// the grammar.
if (((ref1 = this.variable.base) != null ? ref1.value : void 0) === 'RegExp' && this.args.length !== 0) {
moveComments(this.variable, this.args[0]);
}
@@ -1603,7 +1629,7 @@
}
rite = new Call(rite, this.args);
rite.isNew = this.isNew;
left = new Literal(`typeof ${left.compile(o)} === \"function\"`);
left = new Literal(`typeof ${left.compile(o)} === "function"`);
return new If(left, new Value(rite), {
soak: true
});
@@ -1655,7 +1681,7 @@
if (argIndex) {
compiledArgs.push(this.makeCode(", "));
}
compiledArgs.push(...arg.compileToFragments(o, LEVEL_LIST));
compiledArgs.push(...(arg.compileToFragments(o, LEVEL_LIST)));
}
fragments = [];
if (this.isNew) {
@@ -2103,15 +2129,15 @@
// Check if object contains splat.
hasSplat() {
var j, len1, prop, ref1, splat;
var j, len1, prop, ref1;
ref1 = this.properties;
for (j = 0, len1 = ref1.length; j < len1; j++) {
prop = ref1[j];
if (prop instanceof Splat) {
splat = true;
return true;
}
}
return splat != null ? splat : false;
return false;
}
compileNode(o) {
@@ -2234,9 +2260,9 @@
}
// Object spread properties. https://github.com/tc39/proposal-object-rest-spread/blob/master/Spread.md
// `obj2 = {a: 1, obj..., c: 3, d: 4}` → `obj2 = Object.assign({}, {a: 1}, obj, {c: 3, d: 4})`
// `obj2 = {a: 1, obj..., c: 3, d: 4}` → `obj2 = _extends({}, {a: 1}, obj, {c: 3, d: 4})`
compileSpread(o) {
var addSlice, j, len1, prop, propSlices, props, slices, splatSlice;
var _extends, addSlice, j, len1, prop, propSlices, props, slices, splatSlice;
props = this.properties;
// Store object spreads.
splatSlice = [];
@@ -2265,7 +2291,8 @@
if (!(slices[0] instanceof Obj)) {
slices.unshift(new Obj);
}
return (new Call(new Literal('Object.assign'), slices)).compileToFragments(o);
_extends = new Value(new Literal(utility('_extends', o)));
return (new Call(_extends, slices)).compileToFragments(o);
}
compileCSXAttributes(o) {
@@ -2494,7 +2521,7 @@
}
compileClassDeclaration(o) {
var ref1, result;
var ref1, ref2, result;
if (this.externalCtor || this.boundMethods.length) {
if (this.ctor == null) {
this.ctor = this.makeDefaultConstructor();
@@ -2510,7 +2537,13 @@
result = [];
result.push(this.makeCode("class "));
if (this.name) {
result.push(this.makeCode(`${this.name} `));
result.push(this.makeCode(this.name));
}
if (((ref2 = this.variable) != null ? ref2.comments : void 0) != null) {
this.compileCommentFragments(o, this.variable, result);
}
if (this.name) {
result.push(this.makeCode(' '));
}
if (this.parent) {
result.push(this.makeCode('extends '), ...this.parent.compileToFragments(o), this.makeCode(' '));
@@ -2623,10 +2656,23 @@
// Add an expression to the class initializer
// NOTE Currently, only methods and static methods are valid in ES class initializers.
// When additional expressions become valid, this method should be updated to handle them.
// This is the key method for determining whether an expression in a class
// body should appear in the initializer or the executable body. If the given
// `node` is valid in a class body the method will return a (new, modified,
// or identical) node for inclusion in the class initializer, otherwise
// nothing will be returned and the node will appear in the executable body.
// At time of writing, only methods (instance and static) are valid in ES
// class initializers. As new ES class features (such as class fields) reach
// Stage 4, this method will need to be updated to support them. We
// additionally allow `PassthroughLiteral`s (backticked expressions) in the
// initializer as an escape hatch for ES features that are not implemented
// (e.g. getters and setters defined via the `get` and `set` keywords as
// opposed to the `Object.defineProperty` method).
addInitializerExpression(node) {
if (this.validInitializerMethod(node)) {
if (node.unwrapAll() instanceof PassthroughLiteral) {
return node;
} else if (this.validInitializerMethod(node)) {
return this.addInitializerMethod(node);
} else {
return null;
@@ -3138,7 +3184,7 @@
// we've been assigned to, for correct internal references. If the variable
// has not been seen yet within the current scope, declare it.
compileNode(o) {
var answer, compiledName, isValue, j, name, properties, prototype, ref1, ref2, ref3, ref4, ref5, val, varBase;
var answer, compiledName, isValue, j, name, objDestructAnswer, properties, prototype, ref1, ref2, ref3, ref4, ref5, val, varBase;
isValue = this.variable instanceof Value;
if (isValue) {
// When compiling `@variable`, remember if it is part of a function parameter.
@@ -3159,7 +3205,10 @@
return node instanceof Obj && node.hasSplat();
})) {
// Object destructuring. Can be removed once ES proposal hits Stage 4.
return this.compileObjectDestruct(o);
objDestructAnswer = this.compileObjectDestruct(o);
}
if (objDestructAnswer) {
return objDestructAnswer;
}
}
if (this.variable.isSplice()) {
@@ -3178,7 +3227,7 @@
this.variable.error(`'${this.variable.compile(o)}' can't be assigned`);
}
varBase.eachName((name) => {
var message;
var commentFragments, commentsNode, message;
if (typeof name.hasProperties === "function" ? name.hasProperties() : void 0) {
return;
}
@@ -3186,12 +3235,29 @@
if (message) {
name.error(message);
}
// `moduleDeclaration` can be `'import'` or `'export'`
// `moduleDeclaration` can be `'import'` or `'export'`.
this.checkAssignability(o, name);
if (this.moduleDeclaration) {
return o.scope.add(name.value, this.moduleDeclaration);
} else if (this.param) {
return o.scope.add(name.value, this.param === 'alwaysDeclare' ? 'var' : 'param');
} else {
return o.scope.find(name.value);
o.scope.find(name.value);
// If this assignment identifier has one or more herecomments
// attached, output them as part of the declarations line (unless
// other herecomments are already staged there) for compatibility
// with Flow typing. Dont do this if this assignment is for a
// class, e.g. `ClassName = class ClassName {`, as Flow requires
// the comment to be between the class name and the `{`.
if (name.comments && !o.scope.comments[name.value] && !(this.value instanceof Class) && name.comments.every(function(comment) {
return comment.here && !comment.multiline;
})) {
commentsNode = new IdentifierLiteral(name.value);
commentsNode.comments = name.comments;
commentFragments = [];
this.compileCommentFragments(o, commentsNode, commentFragments);
return o.scope.comments[name.value] = commentFragments;
}
}
});
}
@@ -3220,7 +3286,9 @@
answer = compiledName.concat(this.makeCode(` ${this.context || '='} `), val);
// Per https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment#Assignment_without_declaration,
// if were destructuring without declaring, the destructuring assignment must be wrapped in parentheses.
if (o.level > LEVEL_LIST || (o.level === LEVEL_TOP && isValue && this.variable.base instanceof Obj && !this.nestedLhs && !this.param)) {
// The assignment is wrapped in parentheses if 'o.level' has lower precedence than LEVEL_LIST (3)
// (i.e. LEVEL_COND (4), LEVEL_OP (5) or LEVEL_ACCESS (6)), or if we're destructuring object, e.g. {a,b} = obj.
if (o.level > LEVEL_LIST || isValue && this.variable.base instanceof Obj && !this.nestedLhs && !(this.param === true)) {
return this.wrapInParentheses(answer);
} else {
return answer;
@@ -3230,31 +3298,7 @@
// Check object destructuring variable for rest elements;
// can be removed once ES proposal hits Stage 4.
compileObjectDestruct(o) {
var fragments, getPropKey, getPropName, j, len1, restElement, restElements, result, setScopeVar, traverseRest, value, valueRef;
// Per https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment#Assignment_without_declaration,
// if were destructuring without declaring, the destructuring assignment
// must be wrapped in parentheses: `({a, b} = obj)`. Helper function
// `setScopeVar()` declares variables `a` and `b` at the top of the
// current scope.
setScopeVar = function(prop) {
var newVar;
newVar = false;
if (prop instanceof Assign && prop.value.base instanceof Obj) {
return;
}
if (prop instanceof Assign) {
if (prop.value.base instanceof IdentifierLiteral) {
newVar = prop.value.base.compileWithoutComments(o);
} else {
newVar = prop.variable.base.compileWithoutComments(o);
}
} else {
newVar = prop.compileWithoutComments(o);
}
if (newVar) {
return o.scope.add(newVar, 'var', true);
}
};
var fragments, getPropKey, getPropName, j, len1, restElement, restElements, result, traverseRest, value, valueRef, valueRefTemp;
// Returns a safe (cached) reference to the key for a given property
getPropKey = function(prop) {
var key;
@@ -3284,11 +3328,18 @@
var base1, index, j, len1, nestedProperties, nestedSource, nestedSourceDefault, p, prop, restElements, restIndex;
restElements = [];
restIndex = void 0;
if (source.properties == null) {
source = new Value(source);
}
for (index = j = 0, len1 = properties.length; j < len1; index = ++j) {
prop = properties[index];
setScopeVar(prop.unwrap());
nestedSourceDefault = nestedSource = nestedProperties = null;
if (prop instanceof Assign) {
if (typeof (base1 = prop.value).isObject === "function" ? base1.isObject() : void 0) {
if (prop.context !== 'object') {
// prop is `k = {...} `
continue;
}
// prop is `k: {...}`
nestedProperties = prop.value.base.properties;
} else if (prop.value instanceof Assign && prop.value.variable.isObject()) {
@@ -3331,15 +3382,23 @@
}
return restElements;
};
// Cache the value for reuse with rest elements
[this.value, valueRef] = this.value.cache(o);
// Cache the value for reuse with rest elements.
valueRefTemp = this.value.shouldCache() ? new IdentifierLiteral(o.scope.freeVariable('ref', {
reserve: false
})) : this.value.base;
// Find all rest elements.
restElements = traverseRest(this.variable.base.properties, valueRef);
restElements = traverseRest(this.variable.base.properties, valueRefTemp);
if (!(restElements && restElements.length > 0)) {
return false;
}
[this.value, valueRef] = this.value.cache(o);
result = new Block([this]);
for (j = 0, len1 = restElements.length; j < len1; j++) {
restElement = restElements[j];
value = new Call(new Value(new Literal(utility('objectWithoutKeys', o))), [restElement.source, restElement.excludeProps]);
result.push(new Assign(restElement.name, value));
result.push(new Assign(new Value(restElement.name), value, null, {
param: this.param ? 'alwaysDeclare' : null
}));
}
fragments = result.compileToFragments(o);
if (o.level === LEVEL_TOP) {
@@ -3536,7 +3595,7 @@
[left, right] = this.variable.cacheReference(o);
// Disallow conditional assignment of undefined variables.
if (!left.properties.length && left.base instanceof Literal && !(left.base instanceof ThisLiteral) && !o.scope.check(left.base.value)) {
this.variable.error(`the variable \"${left.base.value}\" can't be assigned with ${this.context} because it has not been declared before`);
this.variable.error(`the variable "${left.base.value}" can't be assigned with ${this.context} because it has not been declared before`);
}
if (indexOf.call(this.context, "?") >= 0) {
o.isExistentialEquals = true;
@@ -3633,10 +3692,11 @@
// has no *children* -- they're within the inner scope.
exports.Code = Code = (function() {
class Code extends Base {
constructor(params, body, funcGlyph) {
constructor(params, body, funcGlyph, paramStart) {
var ref1;
super();
this.funcGlyph = funcGlyph;
this.paramStart = paramStart;
this.params = params || [];
this.body = body || new Block;
this.bound = ((ref1 = this.funcGlyph) != null ? ref1.glyph : void 0) === '=>';
@@ -3671,7 +3731,7 @@
// parameters after the splat, they are declared via expressions in the
// function body.
compileNode(o) {
var answer, body, boundMethodCheck, comment, condition, exprs, haveBodyParam, haveSplatParam, i, ifTrue, j, k, l, len1, len2, len3, m, methodScope, modifiers, name, param, paramNames, paramToAddToScope, params, paramsAfterSplat, ref, ref1, ref2, ref3, ref4, ref5, ref6, ref7, ref8, salvagedComments, signature, splatParamName, thisAssignments, wasEmpty;
var answer, body, boundMethodCheck, comment, condition, exprs, generatedVariables, haveBodyParam, haveSplatParam, i, ifTrue, j, k, l, len1, len2, len3, m, methodScope, modifiers, name, param, paramNames, paramToAddToScope, params, paramsAfterSplat, ref, ref1, ref2, ref3, ref4, ref5, ref6, ref7, ref8, scopeVariablesCount, signature, splatParamName, thisAssignments, wasEmpty, yieldNode;
if (this.ctor) {
if (this.isAsync) {
this.name.error('Class constructor may not be async');
@@ -3774,7 +3834,9 @@
ifTrue = new Assign(new Value(param.name), param.value);
exprs.push(new If(condition, ifTrue));
} else {
exprs.push(new Assign(new Value(param.name), param.asReference(o)));
exprs.push(new Assign(new Value(param.name), param.asReference(o), null, {
param: 'alwaysDeclare'
}));
}
}
// If this parameter comes before the splat or expansion, it will go
@@ -3799,22 +3861,25 @@
if (param.name instanceof Arr || param.name instanceof Obj) {
// This parameter is destructured.
param.name.lhs = true;
param.name.eachName(function(prop) {
return o.scope.parameter(prop.value);
});
// Compile `foo({a, b...}) ->` to `foo(arg) -> {a, b...} = arg`.
// Can be removed once ES proposal hits Stage 4.
if (param.name instanceof Obj && param.name.hasSplat()) {
splatParamName = o.scope.freeVariable('arg');
o.scope.parameter(splatParamName);
ref = new Value(new IdentifierLiteral(splatParamName));
exprs.push(new Assign(new Value(param.name), ref));
exprs.push(new Assign(new Value(param.name), ref, null, {
param: 'alwaysDeclare'
}));
// Compile `foo({a, b...} = {}) ->` to `foo(arg = {}) -> {a, b...} = arg`.
if ((param.value != null) && !param.assignedInBody) {
ref = new Assign(ref, param.value, null, {
param: true
});
}
} else if (!param.shouldCache()) {
param.name.eachName(function(prop) {
return o.scope.parameter(prop.value);
});
}
} else {
// This compilation of the parameter is only to get its name to add
@@ -3823,14 +3888,7 @@
// compilation, so that they get output the “real” time this param
// is compiled.
paramToAddToScope = param.value != null ? param : ref;
if ((ref5 = paramToAddToScope.name) != null ? ref5.comments : void 0) {
salvagedComments = paramToAddToScope.name.comments;
delete paramToAddToScope.name.comments;
}
o.scope.parameter(fragmentsToText(paramToAddToScope.compileToFragments(o)));
if (salvagedComments) {
paramToAddToScope.name.comments = salvagedComments;
}
o.scope.parameter(fragmentsToText(paramToAddToScope.compileToFragmentsWithoutComments(o)));
}
params.push(ref);
} else {
@@ -3843,7 +3901,7 @@
ifTrue = new Assign(new Value(param.name), param.value);
exprs.push(new If(condition, ifTrue));
}
if (((ref6 = param.name) != null ? ref6.value : void 0) != null) {
if (((ref5 = param.name) != null ? ref5.value : void 0) != null) {
// Add this parameter to the scope, since it wouldnt have been added
// yet since it was skipped earlier.
o.scope.add(param.name.value, 'var', true);
@@ -3857,15 +3915,17 @@
// Create a destructured assignment, e.g. `[a, b, c] = [args..., b, c]`
exprs.unshift(new Assign(new Value(new Arr([
new Splat(new IdentifierLiteral(splatParamName)),
...(function() {
var k, len2, results;
...((function() {
var k,
len2,
results;
results = [];
for (k = 0, len2 = paramsAfterSplat.length; k < len2; k++) {
param = paramsAfterSplat[k];
results.push(param.asReference(o));
}
return results;
})()
})())
])), new Value(new IdentifierLiteral(splatParamName))));
}
// Add new expressions to the function body
@@ -3881,6 +3941,14 @@
if (!(wasEmpty || this.noReturn)) {
this.body.makeReturn();
}
// JavaScript doesnt allow bound (`=>`) functions to also be generators.
// This is usually caught via `Op::compileContinuation`, but double-check:
if (this.bound && this.isGenerator) {
yieldNode = this.body.contains(function(node) {
return node instanceof Op && node.operator === 'yield';
});
(yieldNode || this).error('yield cannot occur inside bound (fat arrow) functions');
}
// Assemble the output
modifiers = [];
if (this.isMethod && this.isStatic) {
@@ -3895,6 +3963,11 @@
modifiers.push('*');
}
signature = [this.makeCode('(')];
// Block comments between a function name and `(` get output between
// `function` and `(`.
if (((ref6 = this.paramStart) != null ? ref6.comments : void 0) != null) {
this.compileCommentFragments(o, this.paramStart, signature);
}
for (i = k = 0, len2 = params.length; k < len2; i = ++k) {
param = params[i];
if (i !== 0) {
@@ -3903,7 +3976,15 @@
if (haveSplatParam && i === params.length - 1) {
signature.push(this.makeCode('...'));
}
// Compile this parameter, but if any generated variables get created
// (e.g. `ref`), shift those into the parent scope since we cant put a
// `var` line inside a function parameter list.
scopeVariablesCount = o.scope.variables.length;
signature.push(...param.compileToFragments(o));
if (scopeVariablesCount !== o.scope.variables.length) {
generatedVariables = o.scope.variables.splice(scopeVariablesCount);
o.scope.parent.variables.push(...generatedVariables);
}
}
signature.push(this.makeCode(')'));
// Block comments between `)` and `->`/`=>` get output between `)` and `{`.
@@ -4013,13 +4094,23 @@
return seenSuper;
}
// Find all super calls in the given context node
// Returns `true` if `iterator` is called
// Find all super calls in the given context node;
// returns `true` if `iterator` is called.
eachSuperCall(context, iterator) {
var seenSuper;
seenSuper = false;
context.traverseChildren(true, (child) => {
if (child instanceof SuperCall) {
// `super` in a constructor (the only `super` without an accessor)
// cannot be given an argument with a reference to `this`, as that would
// be referencing `this` before calling `super`.
if (!child.variable.accessor) {
Block.wrap(child.args).traverseChildren(true, (node) => {
if (node.this) {
return node.error("Can't call super with @params in derived class constructors");
}
});
}
seenSuper = true;
iterator(child);
} else if (child instanceof ThisLiteral && this.ctor === 'derived' && !seenSuper) {
@@ -4048,12 +4139,12 @@
// as well as be a splat, gathering up a group of parameters into an array.
exports.Param = Param = (function() {
class Param extends Base {
constructor(name1, value1, splat1) {
constructor(name1, value1, splat) {
var message, token;
super();
this.name = name1;
this.value = value1;
this.splat = splat1;
this.splat = splat;
message = isUnassignable(this.name.unwrapAll().value);
if (message) {
this.name.error(message);
@@ -4068,6 +4159,10 @@
return this.name.compileToFragments(o, LEVEL_LIST);
}
compileToFragmentsWithoutComments(o) {
return this.name.compileToFragmentsWithoutComments(o, LEVEL_LIST);
}
asReference(o) {
var name, node;
if (this.reference) {
@@ -4184,21 +4279,21 @@
// or as part of a destructuring assignment.
exports.Splat = Splat = (function() {
class Splat extends Base {
isAssignable() {
return this.name.isAssignable() && (!this.name.isAtomic || this.name.isAtomic());
}
constructor(name) {
super();
this.name = name.compile ? name : new Literal(name);
}
isAssignable() {
return this.name.isAssignable() && (!this.name.isAtomic || this.name.isAtomic());
}
assigns(name) {
return this.name.assigns(name);
}
compileToFragments(o) {
return [this.makeCode('...'), ...this.name.compileToFragments(o)];
compileNode(o) {
return [this.makeCode('...'), ...this.name.compileToFragments(o, LEVEL_OP)];
}
unwrap() {
@@ -4765,7 +4860,7 @@
compileNode(o) {
var fragments;
fragments = this.expression.compileToFragments(o);
fragments = this.expression.compileToFragments(o, LEVEL_LIST);
unshiftAfterComments(fragments, this.makeCode('throw '));
fragments.unshift(this.makeCode(this.tab));
fragments.push(this.makeCode(';'));
@@ -4800,8 +4895,8 @@
this.expression = expression1;
this.comparisonTarget = onlyNotUndefined ? 'undefined' : 'null';
salvagedComments = [];
this.expression.eachChild(function(child) {
var comment, j, k, len1, len2, ref1, ref2, ref3;
this.expression.traverseChildren(true, function(child) {
var comment, j, len1, ref1;
if (child.comments) {
ref1 = child.comments;
for (j = 0, len1 = ref1.length; j < len1; j++) {
@@ -4810,17 +4905,7 @@
salvagedComments.push(comment);
}
}
delete child.comments;
}
if ((ref2 = child.name) != null ? ref2.comments : void 0) {
ref3 = child.name.comments;
for (k = 0, len2 = ref3.length; k < len2; k++) {
comment = ref3[k];
if (indexOf.call(salvagedComments, comment) < 0) {
salvagedComments.push(comment);
}
}
return delete child.name.comments;
return delete child.comments;
}
});
attachCommentsToNode(salvagedComments, this);
@@ -4833,7 +4918,7 @@
code = this.expression.compile(o, LEVEL_OP);
if (this.expression.unwrap() instanceof IdentifierLiteral && !o.scope.check(code)) {
[cmp, cnj] = this.negated ? ['===', '||'] : ['!==', '&&'];
code = `typeof ${code} ${cmp} \"undefined\"` + (this.comparisonTarget !== 'undefined' ? ` ${cnj} ${code} ${cmp} ${this.comparisonTarget}` : '');
code = `typeof ${code} ${cmp} "undefined"` + (this.comparisonTarget !== 'undefined' ? ` ${cnj} ${code} ${cmp} ${this.comparisonTarget}` : '');
} else {
// We explicity want to use loose equality (`==`) when comparing against `null`,
// so that an existence check roughly corresponds to a check for truthiness.
@@ -4880,14 +4965,22 @@
}
compileNode(o) {
var bare, expr, fragments;
var bare, expr, fragments, ref1, shouldWrapComment;
expr = this.body.unwrap();
if (expr instanceof Value && expr.isAtomic() && !this.csxAttribute) {
// If these parentheses are wrapping an `IdentifierLiteral` followed by a
// block comment, output the parentheses (or put another way, dont optimize
// away these redundant parentheses). This is because Flow requires
// parentheses in certain circumstances to distinguish identifiers followed
// by comment-based type annotations from JavaScript labels.
shouldWrapComment = (ref1 = expr.comments) != null ? ref1.some(function(comment) {
return comment.here && !comment.unshift && !comment.newLine;
}) : void 0;
if (expr instanceof Value && expr.isAtomic() && !this.csxAttribute && !shouldWrapComment) {
expr.front = this.front;
return expr.compileToFragments(o);
}
fragments = expr.compileToFragments(o, LEVEL_PAREN);
bare = o.level < LEVEL_OP && (expr instanceof Op || expr.unwrap() instanceof Call || (expr instanceof For && expr.returns)) && (o.level < LEVEL_COND || fragments.length <= 3);
bare = o.level < LEVEL_OP && !shouldWrapComment && (expr instanceof Op || expr.unwrap() instanceof Call || (expr instanceof For && expr.returns)) && (o.level < LEVEL_COND || fragments.length <= 3);
if (this.csxAttribute) {
return this.wrapInBraces(fragments);
}
@@ -4980,7 +5073,7 @@
for (j = 0, len1 = elements.length; j < len1; j++) {
element = elements[j];
if (element instanceof StringLiteral) {
element.value = element.unquote(this.csx);
element.value = element.unquote(true, this.csx);
if (!this.csx) {
// Backticks and `${` inside template literals must be escaped.
element.value = element.value.replace(/(\\*)(`|\$\{)/g, function(match, backslashes, toBeEscaped) {
@@ -4997,7 +5090,9 @@
fragments.push(this.makeCode('$'));
}
code = element.compileToFragments(o, LEVEL_PAREN);
if (!this.isNestedTag(element)) {
if (!this.isNestedTag(element) || code.some(function(fragment) {
return fragment.comments != null;
})) {
code = this.wrapInBraces(code);
// Flag the `{` and `}` fragments as having been generated by this
// `StringWithInterpolations` node, so that `compileComments` knows
@@ -5349,7 +5444,7 @@
fragments.push(cond.makeCode(idt2 + 'break;\n'));
}
if (this.otherwise && this.otherwise.expressions.length) {
fragments.push(this.makeCode(idt1 + "default:\n"), ...this.otherwise.compileToFragments(o, LEVEL_TOP), this.makeCode("\n"));
fragments.push(this.makeCode(idt1 + "default:\n"), ...(this.otherwise.compileToFragments(o, LEVEL_TOP)), this.makeCode("\n"));
}
fragments.push(this.makeCode(this.tab + '}'));
return fragments;
@@ -5514,6 +5609,9 @@
boundMethodCheck: function() {
return "function(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new Error('Bound instance method accessed before binding'); } }";
},
_extends: function() {
return "Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }";
},
// Shortcuts to speed up the lookup time for native functions.
hasProp: function() {
return '{}.hasOwnProperty';

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 2.0.0-beta4
// Generated by CoffeeScript 2.0.3
(function() {
var LONG_FLAG, MULTI_FLAG, OPTIONAL, OptionParser, SHORT_FLAG, buildRule, buildRules, normalizeArguments, repeat,
slice = [].slice;

333
lib/coffeescript/parser.js Executable file → Normal file

File diff suppressed because one or more lines are too long

View File

@@ -1,6 +1,6 @@
// Generated by CoffeeScript 2.0.0-beta4
// Generated by CoffeeScript 2.0.3
(function() {
var CoffeeScript, Module, binary, child_process, ext, findExtension, fork, helpers, i, len, loadFile, path, ref;
var CoffeeScript, Module, binary, child_process, ext, findExtension, fork, getRootModule, helpers, i, len, loadFile, path, ref;
CoffeeScript = require('./');
@@ -12,8 +12,9 @@
// Load and run a CoffeeScript file for Node, stripping any `BOM`s.
loadFile = function(module, filename) {
var answer;
answer = CoffeeScript._compileFile(filename, false, true);
var answer, options;
options = module.options || getRootModule(module).options;
answer = CoffeeScript._compileFile(filename, options);
return module._compile(answer, filename);
};
@@ -72,4 +73,13 @@
};
}
// Utility function to find the `options` object attached to the topmost module.
getRootModule = function(module) {
if (module.parent) {
return getRootModule(module.parent);
} else {
return module;
}
};
}).call(this);

View File

@@ -1,6 +1,6 @@
// Generated by CoffeeScript 2.0.0-beta4
// Generated by CoffeeScript 2.0.3
(function() {
var CoffeeScript, addHistory, addMultilineHandler, fs, getCommandId, merge, nodeREPL, path, replDefaults, runInContext, sawSIGINT, updateSyntaxError, vm;
var CoffeeScript, addHistory, addMultilineHandler, fs, getCommandId, merge, nodeREPL, path, replDefaults, runInContext, sawSIGINT, transpile, updateSyntaxError, vm;
fs = require('fs');
@@ -16,6 +16,8 @@
sawSIGINT = false;
transpile = false;
replDefaults = {
prompt: 'coffee> ',
historyFile: (function() {
@@ -26,8 +28,8 @@
}
})(),
historyMaxInputSize: 10240,
eval: async function(input, context, filename, cb) {
var Assign, Block, Call, Code, Literal, Value, ast, err, isAsync, js, referencedVars, result, token, tokens;
eval: function(input, context, filename, cb) {
var Assign, Block, Call, Code, Literal, Value, ast, err, isAsync, js, ref, ref1, referencedVars, result, token, tokens;
// XXX: multiline hack.
input = input.replace(/\uFF00/g, '\n');
// Node's REPL sends the input ending with a newline and then wrapped in
@@ -41,6 +43,13 @@
try {
// Tokenize the clean input.
tokens = CoffeeScript.tokens(input);
// Filter out tokens generated just to hold comments.
if (tokens.length >= 2 && tokens[0].generated && ((ref = tokens[0].comments) != null ? ref.length : void 0) !== 0 && tokens[0][1] === '' && tokens[1][0] === 'TERMINATOR') {
tokens = tokens.slice(2);
}
if (tokens.length >= 1 && tokens[tokens.length - 1].generated && ((ref1 = tokens[tokens.length - 1].comments) != null ? ref1.length : void 0) !== 0 && tokens[tokens.length - 1][1] === '') {
tokens.pop();
}
// Collect referenced variable names just like in `CoffeeScript.compile`.
referencedVars = (function() {
var i, len, results;
@@ -57,10 +66,10 @@
ast = CoffeeScript.nodes(tokens);
// Add assignment to `__` variable to force the input to be an expression.
ast = new Block([new Assign(new Value(new Literal('__')), ast, '=')]);
// Wrap the expression in a closure to support top-level `await`
// Wrap the expression in a closure to support top-level `await`.
ast = new Code([], ast);
isAsync = ast.isAsync;
// Invoke the wrapping closure
// Invoke the wrapping closure.
ast = new Block([new Call(ast)]);
js = ast.compile({
bare: true,
@@ -68,13 +77,20 @@
referencedVars,
sharedScope: true
});
if (transpile) {
js = transpile.transpile(js, transpile.options).code;
// Strip `"use strict"`, to avoid an exception on assigning to
// undeclared variable `__`.
js = js.replace(/^"use strict"|^'use strict'/, '');
}
result = runInContext(js, context, filename);
// Await an async result, if necessary
// Await an async result, if necessary.
if (isAsync) {
result = (await result);
if (!sawSIGINT) {
cb(null, result);
}
result.then(function(resolvedResult) {
if (!sawSIGINT) {
return cb(null, resolvedResult);
}
});
return sawSIGINT = false;
} else {
return cb(null, result);
@@ -223,7 +239,7 @@
module.exports = {
start: function(opts = {}) {
var build, major, minor, repl;
var Module, build, major, minor, originalModuleLoad, repl;
[major, minor, build] = process.versions.node.split('.').map(function(n) {
return parseInt(n, 10);
});
@@ -233,6 +249,30 @@
}
CoffeeScript.register();
process.argv = ['coffee'].concat(process.argv.slice(2));
if (opts.transpile) {
try {
transpile = {};
transpile.transpile = require('babel-core').transform;
} catch (error) {
console.error('To use --transpile with an interactive REPL, babel-core must be installed either in the current folder or globally:\n npm install --save-dev babel-core\nor\n npm install --global babel-core\nAnd you must save options to configure Babel in one of the places it looks to find its options.\nSee http://coffeescript.org/#transpilation');
process.exit(1);
}
transpile.options = {
filename: path.resolve(process.cwd(), '<repl>')
};
// Since the REPL compilation path is unique (in `eval` above), we need
// another way to get the `options` object attached to a module so that
// it knows later on whether it needs to be transpiled. In the case of
// the REPL, the only applicable option is `transpile`.
Module = require('module');
originalModuleLoad = Module.prototype.load;
Module.prototype.load = function(filename) {
this.options = {
transpile: transpile.options
};
return originalModuleLoad.call(this, filename);
};
}
opts = merge(replDefaults, opts);
repl = nodeREPL.start(opts);
if (opts.prelude) {

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 2.0.0-beta4
// Generated by CoffeeScript 2.0.3
(function() {
// The CoffeeScript language has a good deal of optional syntax, implicit syntax,
// and shorthand syntax. This can greatly complicate a grammar and bloat
@@ -86,6 +86,7 @@
this.normalizeLines();
this.tagPostfixConditionals();
this.addImplicitBracesAndParens();
this.addParensToChainedDoIife();
this.rescueStowawayComments();
this.addLocationDataToGeneratedTokens();
this.enforceValidCSXAttributes();
@@ -280,7 +281,7 @@
stack = [];
start = null;
return this.scanTokens(function(token, i, tokens) {
var endImplicitCall, endImplicitObject, forward, implicitObjectContinues, inImplicit, inImplicitCall, inImplicitControl, inImplicitObject, isImplicit, isImplicitCall, isImplicitObject, k, newLine, nextTag, nextToken, offset, prevTag, prevToken, ref, s, sameLine, stackIdx, stackItem, stackTag, stackTop, startIdx, startImplicitCall, startImplicitObject, startsLine, tag;
var endImplicitCall, endImplicitObject, forward, implicitObjectContinues, inImplicit, inImplicitCall, inImplicitControl, inImplicitObject, isImplicit, isImplicitCall, isImplicitObject, k, newLine, nextTag, nextToken, offset, prevTag, prevToken, ref, ref1, ref2, s, sameLine, stackIdx, stackItem, stackTag, stackTop, startIdx, startImplicitCall, startImplicitObject, startsLine, tag;
[tag] = token;
[prevTag] = prevToken = i > 0 ? tokens[i - 1] : [];
[nextTag] = nextToken = i < tokens.length - 1 ? tokens[i + 1] : [];
@@ -422,7 +423,7 @@
// Recognize standard implicit calls like
// f a, f() b, f? c, h[0] d etc.
// Added support for spread dots on the left side: f ...a
if ((indexOf.call(IMPLICIT_FUNC, tag) >= 0 && token.spaced || tag === '?' && i > 0 && !tokens[i - 1].spaced) && (indexOf.call(IMPLICIT_CALL, nextTag) >= 0 || nextTag === '...' || indexOf.call(IMPLICIT_UNSPACED_CALL, nextTag) >= 0 && !nextToken.spaced && !nextToken.newLine)) {
if ((indexOf.call(IMPLICIT_FUNC, tag) >= 0 && token.spaced || tag === '?' && i > 0 && !tokens[i - 1].spaced) && (indexOf.call(IMPLICIT_CALL, nextTag) >= 0 || (nextTag === '...' && (ref = this.tag(i + 2), indexOf.call(IMPLICIT_CALL, ref) >= 0) && !this.findTagsBackwards(i, ['INDEX_START', '['])) || indexOf.call(IMPLICIT_UNSPACED_CALL, nextTag) >= 0 && !nextToken.spaced && !nextToken.newLine)) {
if (tag === '?') {
tag = token[0] = 'FUNC_EXIST';
}
@@ -456,9 +457,9 @@
if (tag === ':') {
// Go back to the (implicit) start of the object.
s = (function() {
var ref;
var ref1;
switch (false) {
case ref = this.tag(i - 1), indexOf.call(EXPRESSION_END, ref) < 0:
case ref1 = this.tag(i - 1), indexOf.call(EXPRESSION_END, ref1) < 0:
return start[1];
case this.tag(i - 2) !== '@':
return i - 2;
@@ -466,7 +467,7 @@
return i - 1;
}
}).call(this);
startsLine = s === 0 || (ref = this.tag(s - 1), indexOf.call(LINEBREAKS, ref) >= 0) || tokens[s - 1].newLine;
startsLine = s <= 0 || (ref1 = this.tag(s - 1), indexOf.call(LINEBREAKS, ref1) >= 0) || tokens[s - 1].newLine;
// Are we just continuing an already declared object?
if (stackTop()) {
[stackTag, stackIdx] = stackTop();
@@ -538,7 +539,7 @@
// f a, b: c, d: e, f, g: h: i, j
if (tag === ',' && !this.looksObjectish(i + 1) && inImplicitObject() && (nextTag !== 'TERMINATOR' || !this.looksObjectish(i + 2))) {
if (tag === ',' && !this.looksObjectish(i + 1) && inImplicitObject() && !((ref2 = this.tag(i + 2)) === 'FOROF' || ref2 === 'FORIN') && (nextTag !== 'TERMINATOR' || !this.looksObjectish(i + 2))) {
// When nextTag is OUTDENT the comma is insignificant and
// should just be ignored so embed it in the implicit object.
@@ -734,6 +735,46 @@
});
}
// Add parens around a `do` IIFE followed by a chained `.` so that the
// chaining applies to the executed function rather than the function
// object (see #3736)
addParensToChainedDoIife() {
var action, condition, doIndex;
condition = function(token, i) {
return this.tag(i - 1) === 'OUTDENT';
};
action = function(token, i) {
var ref;
if (ref = token[0], indexOf.call(CALL_CLOSERS, ref) < 0) {
return;
}
this.tokens.splice(doIndex, 0, generate('(', '(', this.tokens[doIndex]));
return this.tokens.splice(i + 1, 0, generate(')', ')', this.tokens[i]));
};
doIndex = null;
return this.scanTokens(function(token, i, tokens) {
var glyphIndex, ref;
if (token[1] !== 'do') {
return 1;
}
doIndex = i;
glyphIndex = i + 1;
if (this.tag(i + 1) === 'PARAM_START') {
glyphIndex = null;
this.detectEnd(i + 1, function(token, i) {
return this.tag(i - 1) === 'PARAM_END';
}, function(token, i) {
return glyphIndex = i;
});
}
if (!((glyphIndex != null) && ((ref = this.tag(glyphIndex)) === '->' || ref === '=>') && this.tag(glyphIndex + 1) === 'INDENT')) {
return 1;
}
this.detectEnd(glyphIndex + 1, condition, action);
return 2;
});
}
// Because our grammar is LALR(1), it cant handle some single-line
// expressions that lack ending delimiters. The **Rewriter** adds the implicit
// blocks, so it doesnt need to. To keep the grammar clean and tidy, trailing
@@ -903,6 +944,6 @@
// `STRING_START` isnt on this list because its `locationData` matches that of
// the node that becomes `StringWithInterpolations`, and therefore
// `addDataToNode` attaches `STRING_START`s tokens to that node.
DISCARDED = ['(', ')', '[', ']', '{', '}', '.', '..', '...', ',', '=', '++', '--', '?', 'AS', 'AWAIT', 'CALL_START', 'CALL_END', 'DEFAULT', 'ELSE', 'EXTENDS', 'EXPORT', 'FORIN', 'FOROF', 'FORFROM', 'IMPORT', 'INDENT', 'INDEX_SOAK', 'LEADING_WHEN', 'OUTDENT', 'PARAM_START', 'PARAM_END', 'REGEX_START', 'REGEX_END', 'RETURN', 'STRING_END', 'THROW', 'UNARY', 'YIELD'].concat(IMPLICIT_UNSPACED_CALL.concat(IMPLICIT_END.concat(CALL_CLOSERS.concat(CONTROL_IN_IMPLICIT))));
DISCARDED = ['(', ')', '[', ']', '{', '}', '.', '..', '...', ',', '=', '++', '--', '?', 'AS', 'AWAIT', 'CALL_START', 'CALL_END', 'DEFAULT', 'ELSE', 'EXTENDS', 'EXPORT', 'FORIN', 'FOROF', 'FORFROM', 'IMPORT', 'INDENT', 'INDEX_SOAK', 'LEADING_WHEN', 'OUTDENT', 'PARAM_END', 'REGEX_START', 'REGEX_END', 'RETURN', 'STRING_END', 'THROW', 'UNARY', 'YIELD'].concat(IMPLICIT_UNSPACED_CALL.concat(IMPLICIT_END.concat(CALL_CLOSERS.concat(CONTROL_IN_IMPLICIT))));
}).call(this);

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 2.0.0-beta4
// Generated by CoffeeScript 2.0.3
(function() {
// The **Scope** class regulates lexical scoping within CoffeeScript. As you
// generate code, you create a tree of scopes in the same shape as the nested
@@ -14,7 +14,8 @@
// as well as a reference to the **Block** node it belongs to, which is
// where it should declare its variables, a reference to the function that
// it belongs to, and a list of variables referenced in the source code
// and therefore should be avoided when generating variables.
// and therefore should be avoided when generating variables. Also track comments
// that should be output as part of variable declarations.
constructor(parent, expressions, method, referencedVars) {
var ref, ref1;
this.parent = parent;
@@ -27,6 +28,7 @@
type: 'arguments'
}
];
this.comments = {};
this.positions = {};
if (!this.parent) {
this.utilities = {};

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 2.0.0-beta4
// Generated by CoffeeScript 2.0.3
(function() {
// Source maps allow JavaScript runtimes to match running JavaScript back to
// the original source code that corresponds to it. This can be minified
@@ -47,18 +47,18 @@
};
// SourceMap
// ---------
// Maps locations in a single generated JavaScript file back to locations in
// the original CoffeeScript source file.
// This is intentionally agnostic towards how a source map might be represented on
// disk. Once the compiler is ready to produce a "v3"-style source map, we can walk
// through the arrays of line and column buffer to produce it.
SourceMap = (function() {
var BASE64_CHARS, VLQ_CONTINUATION_BIT, VLQ_SHIFT, VLQ_VALUE_MASK;
// SourceMap
// ---------
// Maps locations in a single generated JavaScript file back to locations in
// the original CoffeeScript source file.
// This is intentionally agnostic towards how a source map might be represented on
// disk. Once the compiler is ready to produce a "v3"-style source map, we can walk
// through the arrays of line and column buffer to produce it.
class SourceMap {
constructor() {
this.lines = [];
@@ -93,7 +93,7 @@
// map. Also, `options.sourceFiles` and `options.generatedFile` may be passed to
// set "sources" and "file", respectively.
generate(options = {}, code = null) {
var buffer, i, j, lastColumn, lastSourceColumn, lastSourceLine, len, len1, lineMap, lineNumber, mapping, needComma, ref, ref1, v3, writingline;
var buffer, i, j, lastColumn, lastSourceColumn, lastSourceLine, len, len1, lineMap, lineNumber, mapping, needComma, ref, ref1, sources, v3, writingline;
writingline = 0;
lastColumn = 0;
lastSourceLine = 0;
@@ -141,15 +141,16 @@
}
}
// Produce the canonical JSON object format for a "v3" source map.
sources = options.sourceFiles ? options.sourceFiles : options.filename ? [options.filename] : ['<anonymous>'];
v3 = {
version: 3,
file: options.generatedFile || '',
sourceRoot: options.sourceRoot || '',
sources: options.sourceFiles || [''],
sources: sources,
names: [],
mappings: buffer
};
if (options.inlineMap) {
if (options.sourceMap || options.inlineMap) {
v3.sourcesContent = [code];
}
return v3;

1566
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -8,10 +8,10 @@
"compiler"
],
"author": "Jeremy Ashkenas",
"version": "2.0.0-beta4",
"version": "2.0.3",
"license": "MIT",
"engines": {
"node": ">=7.6.0"
"node": ">=6"
},
"directories": {
"lib": "./lib/coffeescript"
@@ -39,16 +39,17 @@
"url": "git://github.com/jashkenas/coffeescript.git"
},
"devDependencies": {
"babel-core": "~6.25.0",
"babel-core": "~6.26.0",
"babel-preset-babili": "~0.1.4",
"babel-preset-env": "~1.6.0",
"babili": "^0.1.4",
"babel-preset-minify": "^0.2.0",
"codemirror": "^5.29.0",
"docco": "~0.7.0",
"highlight.js": "~9.12.0",
"jison": ">=0.4.17",
"markdown-it": "~8.3.1",
"jison": ">=0.4.18",
"markdown-it": "~8.4.0",
"underscore": "~1.8.3",
"webpack": "~3.2.0"
"webpack": "~3.6.0"
},
"dependencies": {}
}

View File

@@ -14,7 +14,7 @@ packageJson = require '../../package.json'
# The current CoffeeScript version number.
exports.VERSION = packageJson.version
exports.FILE_EXTENSIONS = ['.coffee', '.litcoffee', '.coffee.md']
exports.FILE_EXTENSIONS = FILE_EXTENSIONS = ['.coffee', '.litcoffee', '.coffee.md']
# Expose helpers for testing.
exports.helpers = helpers
@@ -49,9 +49,9 @@ withPrettyErrors = (fn) ->
# a stack trace. Assuming that most of the time, code isnt throwing
# exceptions, its probably more efficient to compile twice only when we
# need a stack trace, rather than always generating a source map even when
# its not likely to be used. Save in form of `filename`: `(source)`
# its not likely to be used. Save in form of `filename`: [`(source)`]
sources = {}
# Also save source maps if generated, in form of `filename`: `(source map)`.
# Also save source maps if generated, in form of `(source)`: [`(source map)`].
sourceMaps = {}
# Compile CoffeeScript code to JavaScript, using the Coffee/Jison compiler.
@@ -64,9 +64,9 @@ sourceMaps = {}
# in which case this returns a `{js, v3SourceMap, sourceMap}`
# object, where sourceMap is a sourcemap.coffee#SourceMap object, handy for
# doing programmatic lookups.
exports.compile = compile = withPrettyErrors (code, options) ->
{merge, extend} = helpers
options = extend {}, options
exports.compile = compile = withPrettyErrors (code, options = {}) ->
# Clone `options`, to avoid mutating the `options` object passed in.
options = Object.assign {}, options
# Always generate a source map if no filename is passed in, since without a
# a filename we have no way to retrieve this source later in the event that
# we need to recompile it to get a source map for `prepareStackTrace`.
@@ -75,7 +75,8 @@ exports.compile = compile = withPrettyErrors (code, options) ->
checkShebangLine filename, code
sources[filename] = code
sources[filename] ?= []
sources[filename].push code
map = new SourceMap if generateSourceMap
tokens = lexer.tokenize code, options
@@ -124,8 +125,32 @@ exports.compile = compile = withPrettyErrors (code, options) ->
js = "// #{header}\n#{js}"
if generateSourceMap
v3SourceMap = map.generate(options, code)
sourceMaps[filename] = map
v3SourceMap = map.generate options, code
sourceMaps[filename] ?= []
sourceMaps[filename].push map
if options.transpile
if typeof options.transpile isnt 'object'
# This only happens if run via the Node API and `transpile` is set to
# something other than an object.
throw new Error 'The transpile option must be given an object with options to pass to Babel'
# Get the reference to Babel that we have been passed if this compiler
# is run via the CLI or Node API.
transpiler = options.transpile.transpile
delete options.transpile.transpile
transpilerOptions = Object.assign {}, options.transpile
# See https://github.com/babel/babel/issues/827#issuecomment-77573107:
# Babel can take a v3 source map object as input in `inputSourceMap`
# and it will return an *updated* v3 source map object in its output.
if v3SourceMap and not transpilerOptions.inputSourceMap?
transpilerOptions.inputSourceMap = v3SourceMap
transpilerOutput = transpiler js, transpilerOptions
js = transpilerOutput.code
if v3SourceMap and transpilerOutput.map
v3SourceMap = transpilerOutput.map
if options.inlineMap
encoded = base64encode JSON.stringify v3SourceMap
@@ -264,16 +289,36 @@ formatSourcePosition = (frame, getSourceMapping) ->
else
fileLocation
getSourceMap = (filename) ->
if sourceMaps[filename]?
sourceMaps[filename]
# CoffeeScript compiled in a browser may get compiled with `options.filename`
# of `<anonymous>`, but the browser may request the stack trace with the
# filename of the script file.
getSourceMap = (filename, line, column) ->
# Skip files that we didnt compile, like Node system files that appear in
# the stack trace, as they never have source maps.
return null unless filename is '<anonymous>' or filename.slice(filename.lastIndexOf('.')) in FILE_EXTENSIONS
if filename isnt '<anonymous>' and sourceMaps[filename]?
return sourceMaps[filename][sourceMaps[filename].length - 1]
# CoffeeScript compiled in a browser or via `CoffeeScript.compile` or `.run`
# may get compiled with `options.filename` thats missing, which becomes
# `<anonymous>`; but the runtime might request the stack trace with the
# filename of the script file. See if we have a source map cached under
# `<anonymous>` that matches the error.
else if sourceMaps['<anonymous>']?
sourceMaps['<anonymous>']
else if sources[filename]?
answer = compile sources[filename],
# Work backwards from the most recent anonymous source maps, until we find
# one that works. This isnt foolproof; there is a chance that multiple
# source maps will have line/column pairs that match. But we have no other
# way to match them. `frame.getFunction().toString()` doesnt always work,
# and its not foolproof either.
for map in sourceMaps['<anonymous>'] by -1
sourceLocation = map.sourceLocation [line - 1, column - 1]
return map if sourceLocation?[0]? and sourceLocation[1]?
# If all else fails, recompile this source to get a source map. We need the
# previous section (for `<anonymous>`) despite this option, because after it
# gets compiled we will still need to look it up from
# `sourceMaps['<anonymous>']` in order to find and return it. Thats why we
# start searching from the end in the previous block, because most of the
# time the source map we want is the last one.
if sources[filename]?
answer = compile sources[filename][sources[filename].length - 1],
filename: filename
sourceMap: yes
literate: helpers.isLiterate filename
@@ -287,7 +332,7 @@ getSourceMap = (filename) ->
# positions.
Error.prepareStackTrace = (err, stack) ->
getSourceMapping = (filename, line, column) ->
sourceMap = getSourceMap filename
sourceMap = getSourceMap filename, line, column
answer = sourceMap.sourceLocation [line - 1, column - 1] if sourceMap?
if answer? then [answer[0] + 1, answer[1] + 1] else null

Some files were not shown because too many files have changed in this diff Show More