mirror of
https://github.com/jashkenas/coffeescript.git
synced 2026-01-13 08:47:55 -05:00
Compare commits
121 Commits
2.0.0-beta
...
2.2.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a73f66bc11 | ||
|
|
ba094126e2 | ||
|
|
794f65fbd7 | ||
|
|
0490eb9a3a | ||
|
|
9e80f6fa67 | ||
|
|
fc5ab1afa3 | ||
|
|
0aa77f157a | ||
|
|
1849f0db76 | ||
|
|
d86597dbad | ||
|
|
bf91781888 | ||
|
|
dcd6de9a77 | ||
|
|
70b510bcb7 | ||
|
|
84d596d534 | ||
|
|
c804087ec9 | ||
|
|
74bd537d6c | ||
|
|
0217ed5505 | ||
|
|
e53307b46b | ||
|
|
c8c8c167d1 | ||
|
|
c1283ead45 | ||
|
|
3ade25a32c | ||
|
|
7ea3ea92f3 | ||
|
|
a70f1a082e | ||
|
|
2ccbb6b91a | ||
|
|
e348026073 | ||
|
|
7c6f3788ca | ||
|
|
12fcbfc654 | ||
|
|
38f5963b85 | ||
|
|
ffbe51e374 | ||
|
|
926cb8463c | ||
|
|
b1286752b9 | ||
|
|
5eb9dded52 | ||
|
|
7f5ab7eb0d | ||
|
|
5bc85b8f6d | ||
|
|
81d1b511f0 | ||
|
|
2dc3f6c87a | ||
|
|
04959162c6 | ||
|
|
f14c7ffa3f | ||
|
|
64b8dd486a | ||
|
|
7864acabc3 | ||
|
|
9812d28748 | ||
|
|
555c22af58 | ||
|
|
3f4b03bcff | ||
|
|
a706a64a6d | ||
|
|
637fe305a6 | ||
|
|
bd824c73dd | ||
|
|
cbc695b831 | ||
|
|
f3375e798c | ||
|
|
e2308093e4 | ||
|
|
0dc4755920 | ||
|
|
6faa7f2b35 | ||
|
|
063c2d1f56 | ||
|
|
4d4e47bfb2 | ||
|
|
22fb31e317 | ||
|
|
a2037e799f | ||
|
|
694e69d872 | ||
|
|
bb2871fdde | ||
|
|
08e00331dd | ||
|
|
0b0a9ef2c4 | ||
|
|
9df1457c55 | ||
|
|
22f92f23ae | ||
|
|
cd516b954f | ||
|
|
27eff5ca77 | ||
|
|
5cbd25f5d4 | ||
|
|
eb127923a7 | ||
|
|
42da56deb1 | ||
|
|
81260bff7d | ||
|
|
35f784bcdf | ||
|
|
c17b6b8863 | ||
|
|
1965996933 | ||
|
|
a67dfae985 | ||
|
|
1cb733989c | ||
|
|
a2a2e769c3 | ||
|
|
19231dbcad | ||
|
|
aecc115c79 | ||
|
|
4c41831474 | ||
|
|
659f1b3c4c | ||
|
|
f51c1a150b | ||
|
|
970f31c292 | ||
|
|
d172405244 | ||
|
|
44ebfdb764 | ||
|
|
1b8f1af287 | ||
|
|
e7073bc5d9 | ||
|
|
63d3b699d7 | ||
|
|
458440e57b | ||
|
|
df9d4a2343 | ||
|
|
9e043bbae7 | ||
|
|
671486989f | ||
|
|
4a4f752204 | ||
|
|
b20e52da99 | ||
|
|
5525b2ba01 | ||
|
|
fe5ff39ca2 | ||
|
|
906bedf93a | ||
|
|
6f961a20dd | ||
|
|
e54b8a1009 | ||
|
|
d7d69a4a18 | ||
|
|
eb38dba5d6 | ||
|
|
6cea181ff1 | ||
|
|
9ff82fe17b | ||
|
|
5713b7eb6c | ||
|
|
7c627f9dfd | ||
|
|
c81e2d4767 | ||
|
|
3dd458267b | ||
|
|
892c4699dd | ||
|
|
40c351135a | ||
|
|
a3b08e1bef | ||
|
|
44a27c6204 | ||
|
|
c212e6e9ab | ||
|
|
5a709ed4a8 | ||
|
|
2491d3286d | ||
|
|
1a6477adec | ||
|
|
2149c3561b | ||
|
|
232041db2a | ||
|
|
4623bf5bba | ||
|
|
2664c2c108 | ||
|
|
f9367bacf1 | ||
|
|
aef54aeaf7 | ||
|
|
eff160eeb7 | ||
|
|
911c21f7be | ||
|
|
52795587ec | ||
|
|
3a6ffa6a85 | ||
|
|
e3c2c0397a |
18
.travis.yml
Normal file
18
.travis.yml
Normal 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
|
||||
164
Cakefile
164
Cakefile
@@ -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, '@'
|
||||
@@ -326,7 +332,7 @@ task 'doc:test:watch', 'watch and continually rebuild the browser-based tests',
|
||||
|
||||
buildAnnotatedSource = (watch = no) ->
|
||||
do generateAnnotatedSource = ->
|
||||
exec "node_modules/docco/bin/docco src/*.*coffee --output docs/v#{majorVersion}/annotated-source", (err) -> throw err if err
|
||||
exec "cd src && ../node_modules/docco/bin/docco *.*coffee --output ../docs/v#{majorVersion}/annotated-source", (err) -> throw err if err
|
||||
log 'generated', green, "annotated source in docs/v#{majorVersion}/annotated-source/"
|
||||
|
||||
if watch
|
||||
@@ -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 they’re 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 isn’t 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
|
||||
|
||||
43
README.md
43
README.md
@@ -1,22 +1,27 @@
|
||||
{
|
||||
} } {
|
||||
{ { } }
|
||||
} }{ {
|
||||
{ }{ } } _____ __ __
|
||||
{ }{ }{ { } / ____| / _|/ _|
|
||||
.- { { } { }} -. | | ___ | |_| |_ ___ ___
|
||||
( { } { } { } } ) | | / _ \| _| _/ _ \/ _ \
|
||||
|`-..________ ..-'| | |___| (_) | | | || __/ __/
|
||||
| | \_____\___/|_| |_| \___|\___|
|
||||
| ;--.
|
||||
| (__ \ _____ _ _
|
||||
| | ) ) / ____| (_) | |
|
||||
| |/ / | (___ ___ _ __ _ _ __ | |_
|
||||
| ( / \___ \ / __| '__| | '_ \| __|
|
||||
| |/ ____) | (__| | | | |_) | |_
|
||||
| | |_____/ \___|_| |_| .__/ \__|
|
||||
`-.._________..-' | |
|
||||
|_|
|
||||
@@@@@@@ @@@@ @@@@@
|
||||
{ @@@@@@@@@@ @@@ @@@
|
||||
} } { @@@@ @@ @@@ @@@
|
||||
{ { } } @@@@ @@@@@@@ @@@ @@@ @@@@@@ @@@@@@
|
||||
} }{ { @@@@ @@@ @@ @@@@@ @@@@@@ @@@ @@ @@@@ @@
|
||||
{ }{ } } @@@@ @@@@ @@ @@@ @@@ @@@ @@@ @@@ @@@
|
||||
{ }{ }{ { } @@@@ @@@@ @@ @@@ @@@ @@@@@@@@ @@@@@@@@
|
||||
{ { } { } { } } @@@@@ @@@@ @@ @@@ @@@ @@@ @@@
|
||||
{ } { } { } @@@@@@@@@@ @@@@@@@@ @@@ @@@ @@@@@@@@ @@@@@@@@
|
||||
@@@@@@ { } { } @@@@@@@ @@@@@ @@@ @@@ @@@@@ @@@@@
|
||||
@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@ @@@
|
||||
@@ @@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@ @@@ @@@
|
||||
@@ @@@@@@@@@@@@@@@@@@@@@@@@ @@@@ @@ @@@ @@@@
|
||||
@@@ @@@@@@@@@@@@@@@@@@@@@ @@@@ @@@ @@ @@@@
|
||||
@@@ @@@@@@@@@@@@@@@@@@ @@@@@ @@@@@ @@ @@ @@@ @@@@@@@ @@@@@
|
||||
@@@ @@@@@@@@@@@@@@@@ @@@@@ @@@ @@@ @@@@@@@@ @@@@ @@@@ @@@@@@@
|
||||
@@@@@@@@@@@@@@ @@@@@ @@@ @@@@ @@@@ @@@ @@@ @@@
|
||||
@@@@@ @@@@ @@@@ @@@@ @@@@ @@@@ @@@@ @@@@
|
||||
@@@ @@@@ @@@ @@@@ @@@@ @@@ @@@@ @@@@
|
||||
@@@ @@@@ @@@@ @@@@ @@@@ @@@@ @@@@ @@@@
|
||||
@@@@@@@@@ @@@@@@ @@@@ @@@@ @@@@@@@@@ @@@@
|
||||
@@@ @@@@
|
||||
@@@
|
||||
@@@
|
||||
|
||||
CoffeeScript is a little language that compiles into JavaScript.
|
||||
|
||||
|
||||
27
appveyor.yml
Normal file
27
appveyor.yml
Normal file
@@ -0,0 +1,27 @@
|
||||
environment:
|
||||
matrix:
|
||||
- nodejs_version: '6'
|
||||
- nodejs_version: '8'
|
||||
- nodejs_version: '' # Installs latest.
|
||||
|
||||
install:
|
||||
- ps: Install-Product node $env:nodejs_version
|
||||
- node --version
|
||||
- npm --version
|
||||
- npm install
|
||||
|
||||
cache:
|
||||
- node_modules
|
||||
|
||||
test_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
|
||||
|
||||
build: off
|
||||
|
||||
version: "{build}"
|
||||
7
bin/cake
7
bin/cake
@@ -1,5 +1,12 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
try {
|
||||
new Function('var {a} = {a: 1}')();
|
||||
} catch (error) {
|
||||
console.error('Your JavaScript runtime does not support some features used by the cake command. Please use Node 6 or later.');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
var path = require('path');
|
||||
var fs = require('fs');
|
||||
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
try {
|
||||
new Function('var {a} = {a: 1}')();
|
||||
} catch (error) {
|
||||
console.error('Your JavaScript runtime does not support some features used by the coffee command. Please use Node 6 or later.');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
var path = require('path');
|
||||
var fs = require('fs');
|
||||
|
||||
|
||||
1
docs/annotated-source
Symbolic link
1
docs/annotated-source
Symbolic link
@@ -0,0 +1 @@
|
||||
v2/annotated-source
|
||||
1
docs/announcing-coffeescript-2
Symbolic link
1
docs/announcing-coffeescript-2
Symbolic link
@@ -0,0 +1 @@
|
||||
v2/announcing-coffeescript-2
|
||||
1
docs/browser-compiler
Symbolic link
1
docs/browser-compiler
Symbolic link
@@ -0,0 +1 @@
|
||||
v2/browser-compiler
|
||||
@@ -1 +1 @@
|
||||
v1/index.html
|
||||
v2/index.html
|
||||
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"name": "",
|
||||
"name": "CoffeeScript",
|
||||
"description": "Unfancy JavaScript",
|
||||
"icons": [
|
||||
{
|
||||
"src": "\/android-chrome-192x192.png",
|
||||
|
||||
1
docs/test.html
Symbolic link
1
docs/test.html
Symbolic link
@@ -0,0 +1 @@
|
||||
v2/test.html
|
||||
@@ -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 & 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 & 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 & 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 & 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>“It’s 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">don’t expect any fanciness built-in</a>. If you need dependencies, or async callbacks, it’s 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">don’t expect any fanciness built-in</a>. If you need dependencies, or async callbacks, it’s 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 it’s not recommended for serious use, CoffeeScripts may be included directly within the browser using <code><script type="text/coffeescript"></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 it’s not recommended for serious use, CoffeeScripts may be included directly within the browser using <code><script type="text/coffeescript"></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 && bin/cake build:full</code> is a good command to run when you’re working on the core language. It’ll 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, there’s a good chance you’ve 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 CoffeeScript’s 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 couldn’t 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"> — <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>. It’ll 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>. It’ll 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>
|
||||
|
||||
@@ -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 @@ didn’t create a source map (faster) but something went wrong and we need
|
||||
a stack trace. Assuming that most of the time, code isn’t throwing
|
||||
exceptions, it’s probably more efficient to compile twice only when we
|
||||
need a stack trace, rather than always generating a source map even when
|
||||
it’s not likely to be used. Save in form of <code>filename</code>: <code>(source)</code></p>
|
||||
it’s not likely to be used. Save in form of <code>filename</code>: [<code>(source)</code>]</p>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -267,7 +267,7 @@ it’s not likely to be used. Save in form of <code>filename</code>: <code>(sour
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-9">¶</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) ->
|
||||
{merge, extend} = helpers
|
||||
options = extend {}, options</pre></div></div>
|
||||
<div class="content"><div class='highlight'><pre>exports.compile = compile = withPrettyErrors (code, options = {}) -></pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -306,6 +304,21 @@ doing programmatic lookups.</p>
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-11">¶</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">¶</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">¶</a>
|
||||
<a class="pilcrow" href="#section-13">¶</a>
|
||||
</div>
|
||||
<p>Pass a list of referenced variables, so that generated variables won’t 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">¶</a>
|
||||
<a class="pilcrow" href="#section-14">¶</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">¶</a>
|
||||
<a class="pilcrow" href="#section-15">¶</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">¶</a>
|
||||
<a class="pilcrow" href="#section-16">¶</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">¶</a>
|
||||
<a class="pilcrow" href="#section-17">¶</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">¶</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">¶</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">¶</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">¶</a>
|
||||
<a class="pilcrow" href="#section-21">¶</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">¶</a>
|
||||
<a class="pilcrow" href="#section-22">¶</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">¶</a>
|
||||
<a class="pilcrow" href="#section-23">¶</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">¶</a>
|
||||
<a class="pilcrow" href="#section-24">¶</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">¶</a>
|
||||
<a class="pilcrow" href="#section-25">¶</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">¶</a>
|
||||
<a class="pilcrow" href="#section-26">¶</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">¶</a>
|
||||
<a class="pilcrow" href="#section-27">¶</a>
|
||||
</div>
|
||||
<p>Override Jison’s 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">¶</a>
|
||||
<a class="pilcrow" href="#section-28">¶</a>
|
||||
</div>
|
||||
<p>Disregard Jison’s 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">¶</a>
|
||||
<a class="pilcrow" href="#section-29">¶</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">¶</a>
|
||||
<a class="pilcrow" href="#section-30">¶</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">¶</a>
|
||||
<a class="pilcrow" href="#section-31">¶</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> -></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> -></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">¶</a>
|
||||
<a class="pilcrow" href="#section-32">¶</a>
|
||||
</div>
|
||||
<p>CoffeeScript compiled in a browser may get compiled with <code>options.filename</code>
|
||||
of <code><anonymous></code>, but the browser may request the stack trace with the
|
||||
filename of the script file.</p>
|
||||
<p>Skip files that we didn’t 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">'<anonymous>'</span>]?
|
||||
sourceMaps[<span class="hljs-string">'<anonymous>'</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">'<anonymous>'</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">'<anonymous>'</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">¶</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> that’s missing, which becomes
|
||||
<code><anonymous></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><anonymous></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">'<anonymous>'</span>]?</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-34">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-34">¶</a>
|
||||
</div>
|
||||
<p>Work backwards from the most recent anonymous source maps, until we find
|
||||
one that works. This isn’t 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> doesn’t always work,
|
||||
and it’s 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">'<anonymous>'</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">¶</a>
|
||||
</div>
|
||||
<p>If all else fails, recompile this source to get a source map. We need the
|
||||
previous section (for <code><anonymous></code>) despite this option, because after it
|
||||
gets compiled we will still need to look it up from
|
||||
<code>sourceMaps['<anonymous>']</code> in order to find and return it. That’s 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">¶</a>
|
||||
<a class="pilcrow" href="#section-36">¶</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> -></span>
|
||||
<span class="hljs-function"> <span class="hljs-title">getSourceMapping</span> = <span class="hljs-params">(filename, line, column)</span> -></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>
|
||||
|
||||
|
||||
@@ -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">¶</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">¶</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> -></span>
|
||||
requires.map (<span class="hljs-built_in">module</span>) ->
|
||||
[_, 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">¶</a>
|
||||
<a class="pilcrow" href="#section-11">¶</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">¶</a>
|
||||
<a class="pilcrow" href="#section-12">¶</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 script’s 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> -></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">¶</a>
|
||||
<a class="pilcrow" href="#section-13">¶</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> = -></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> -></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">¶</a>
|
||||
<a class="pilcrow" href="#section-14">¶</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">¶</a>
|
||||
<a class="pilcrow" href="#section-15">¶</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">¶</a>
|
||||
<a class="pilcrow" href="#section-16">¶</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">¶</a>
|
||||
<a class="pilcrow" href="#section-17">¶</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">¶</a>
|
||||
<a class="pilcrow" href="#section-18">¶</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> -></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">¶</a>
|
||||
<a class="pilcrow" href="#section-19">¶</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">¶</a>
|
||||
<a class="pilcrow" href="#section-20">¶</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> -></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> = -></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">¶</a>
|
||||
<a class="pilcrow" href="#section-21">¶</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">¶</a>
|
||||
<a class="pilcrow" href="#section-22">¶</a>
|
||||
</div>
|
||||
<p>When watching scripts, it’s 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">¶</a>
|
||||
<a class="pilcrow" href="#section-23">¶</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">¶</a>
|
||||
<a class="pilcrow" href="#section-24">¶</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">¶</a>
|
||||
<a class="pilcrow" href="#section-25">¶</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> -></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">¶</a>
|
||||
</div>
|
||||
<p>The user has requested that the CoffeeScript compiler also transpile
|
||||
via Babel. We don’t include Babel as a dependency because we want to
|
||||
avoid dependencies in general, and most users probably won’t be relying
|
||||
on us to transpile for them; we assume most users will probably either
|
||||
run CoffeeScript’s 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">¶</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">¶</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('coffeescript')</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">¶</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">'<anonymous>'</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">¶</a>
|
||||
<a class="pilcrow" href="#section-30">¶</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">¶</a>
|
||||
<a class="pilcrow" href="#section-31">¶</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">¶</a>
|
||||
<a class="pilcrow" href="#section-32">¶</a>
|
||||
</div>
|
||||
<p>Print the <code>--version</code> message and exit.</p>
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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> -></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">¶</a>
|
||||
</div>
|
||||
<p>This error is only for Node, as CLI users will see a different error
|
||||
earlier if they don’t 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">¶</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">¶</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> -></span></pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-5">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-5">¶</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('coffeescript')</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">¶</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">¶</a>
|
||||
<a class="pilcrow" href="#section-7">¶</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">¶</a>
|
||||
<a class="pilcrow" href="#section-8">¶</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">¶</a>
|
||||
<a class="pilcrow" href="#section-9">¶</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">¶</a>
|
||||
<a class="pilcrow" href="#section-10">¶</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">¶</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">¶</a>
|
||||
<a class="pilcrow" href="#section-12">¶</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">¶</a>
|
||||
<a class="pilcrow" href="#section-13">¶</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">¶</a>
|
||||
<a class="pilcrow" href="#section-14">¶</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">-></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">¶</a>
|
||||
<a class="pilcrow" href="#section-15">¶</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">-></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> -></span>
|
||||
CoffeeScript._compileFile = <span class="hljs-function"><span class="hljs-params">(filename, options = {})</span> -></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">¶</a>
|
||||
<a class="pilcrow" href="#section-16">¶</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">¶</a>
|
||||
<a class="pilcrow" href="#section-17">¶</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
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -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> -></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">¶</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> -></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>
|
||||
|
||||
@@ -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> '</span>,
|
||||
@@ -223,11 +224,17 @@ Unwrap that too.</p>
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-7">¶</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 >= <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 >= <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">¶</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">¶</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">¶</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">¶</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">¶</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">¶</a>
|
||||
</div>
|
||||
<p>Strip <code>"use strict"</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">¶</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) ->
|
||||
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">¶</a>
|
||||
</div>
|
||||
<p>AST’s <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">¶</a>
|
||||
<a class="pilcrow" href="#section-16">¶</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">¶</a>
|
||||
<a class="pilcrow" href="#section-17">¶</a>
|
||||
</div>
|
||||
<p>Proxy node’s 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">¶</a>
|
||||
<a class="pilcrow" href="#section-18">¶</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">¶</a>
|
||||
<a class="pilcrow" href="#section-19">¶</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">¶</a>
|
||||
<a class="pilcrow" href="#section-20">¶</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">¶</a>
|
||||
<a class="pilcrow" href="#section-21">¶</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">¶</a>
|
||||
<a class="pilcrow" href="#section-22">¶</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">¶</a>
|
||||
<a class="pilcrow" href="#section-23">¶</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">¶</a>
|
||||
<a class="pilcrow" href="#section-24">¶</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">¶</a>
|
||||
<a class="pilcrow" href="#section-25">¶</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">¶</a>
|
||||
<a class="pilcrow" href="#section-26">¶</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">¶</a>
|
||||
<a class="pilcrow" href="#section-27">¶</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">¶</a>
|
||||
<a class="pilcrow" href="#section-28">¶</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">¶</a>
|
||||
<a class="pilcrow" href="#section-29">¶</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">¶</a>
|
||||
<a class="pilcrow" href="#section-30">¶</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">¶</a>
|
||||
<a class="pilcrow" href="#section-31">¶</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">¶</a>
|
||||
<a class="pilcrow" href="#section-32">¶</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">'<repl>'</span></pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-33">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-33">¶</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> -></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">¶</a>
|
||||
<a class="pilcrow" href="#section-34">¶</a>
|
||||
</div>
|
||||
<p>Adapt help inherited from the node REPL</p>
|
||||
|
||||
|
||||
@@ -234,6 +234,7 @@ output the token stream after it has been rewritten by this file.</p>
|
||||
@normalizeLines()
|
||||
@tagPostfixConditionals()
|
||||
@addImplicitBracesAndParens()
|
||||
@addParensToChainedDoIife()
|
||||
@rescueStowawayComments()
|
||||
@addLocationDataToGeneratedTokens()
|
||||
@enforceValidCSXAttributes()
|
||||
@@ -675,7 +676,21 @@ class declaration or if-conditionals).</p>
|
||||
endImplicitObject()
|
||||
<span class="hljs-keyword">else</span>
|
||||
stack.pop()
|
||||
start = stack.pop()</pre></div></div>
|
||||
start = stack.pop()
|
||||
<span class="hljs-function">
|
||||
<span class="hljs-title">inControlFlow</span> = =></span>
|
||||
seenFor = @findTagsBackwards(i, [<span class="hljs-string">'FOR'</span>]) <span class="hljs-keyword">and</span> @findTagsBackwards(i, [<span class="hljs-string">'FORIN'</span>, <span class="hljs-string">'FOROF'</span>, <span class="hljs-string">'FORFROM'</span>])
|
||||
controlFlow = seenFor <span class="hljs-keyword">or</span> @findTagsBackwards i, [<span class="hljs-string">'WHILE'</span>, <span class="hljs-string">'UNTIL'</span>, <span class="hljs-string">'LOOP'</span>, <span class="hljs-string">'LEADING_WHEN'</span>]
|
||||
<span class="hljs-keyword">return</span> <span class="hljs-literal">no</span> <span class="hljs-keyword">unless</span> controlFlow
|
||||
isFunc = <span class="hljs-literal">no</span>
|
||||
tagCurrentLine = token[<span class="hljs-number">2</span>].first_line
|
||||
@detectEnd i,
|
||||
<span class="hljs-function"><span class="hljs-params">(token, i)</span> -></span> token[<span class="hljs-number">0</span>] <span class="hljs-keyword">in</span> LINEBREAKS
|
||||
(token, i) ->
|
||||
[prevTag, ,{first_line}] = tokens[i - <span class="hljs-number">1</span>] || []
|
||||
isFunc = tagCurrentLine <span class="hljs-keyword">is</span> first_line <span class="hljs-keyword">and</span> prevTag <span class="hljs-keyword">in</span> [<span class="hljs-string">'->'</span>, <span class="hljs-string">'=>'</span>]
|
||||
returnOnNegativeLevel: <span class="hljs-literal">yes</span>
|
||||
isFunc</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -694,9 +709,11 @@ 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 > <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)
|
||||
<span class="hljs-keyword">not</span> nextToken.spaced <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> nextToken.newLine) <span class="hljs-keyword">and</span>
|
||||
<span class="hljs-keyword">not</span> inControlFlow()
|
||||
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>
|
||||
startImplicitCall i + <span class="hljs-number">1</span>
|
||||
<span class="hljs-keyword">return</span> forward(<span class="hljs-number">2</span>)</pre></div></div>
|
||||
@@ -767,7 +784,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 <= <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>
|
||||
|
||||
@@ -833,7 +850,9 @@ like e.g.:</p>
|
||||
stackItem[<span class="hljs-number">2</span>].sameLine = <span class="hljs-literal">no</span> <span class="hljs-keyword">if</span> isImplicitObject stackItem
|
||||
|
||||
newLine = prevTag <span class="hljs-keyword">is</span> <span class="hljs-string">'OUTDENT'</span> <span class="hljs-keyword">or</span> prevToken.newLine
|
||||
<span class="hljs-keyword">if</span> tag <span class="hljs-keyword">in</span> IMPLICIT_END <span class="hljs-keyword">or</span> tag <span class="hljs-keyword">in</span> CALL_CLOSERS <span class="hljs-keyword">and</span> newLine
|
||||
<span class="hljs-keyword">if</span> tag <span class="hljs-keyword">in</span> IMPLICIT_END <span class="hljs-keyword">or</span>
|
||||
(tag <span class="hljs-keyword">in</span> CALL_CLOSERS <span class="hljs-keyword">and</span> newLine) <span class="hljs-keyword">or</span>
|
||||
(tag <span class="hljs-keyword">in</span> [<span class="hljs-string">'..'</span>, <span class="hljs-string">'...'</span>] <span class="hljs-keyword">and</span> @findTagsBackwards(i, [<span class="hljs-string">"INDEX_START"</span>]))
|
||||
<span class="hljs-keyword">while</span> inImplicit()
|
||||
[stackTag, stackIdx, {sameLine, startsLine}] = stackTop()</pre></div></div>
|
||||
|
||||
@@ -850,7 +869,8 @@ like e.g.:</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> inImplicitCall() <span class="hljs-keyword">and</span> prevTag <span class="hljs-keyword">isnt</span> <span class="hljs-string">','</span>
|
||||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> inImplicitCall() <span class="hljs-keyword">and</span> prevTag <span class="hljs-keyword">isnt</span> <span class="hljs-string">','</span> <span class="hljs-keyword">or</span>
|
||||
(prevTag <span class="hljs-keyword">is</span> <span class="hljs-string">','</span> <span class="hljs-keyword">and</span> tag <span class="hljs-keyword">is</span> <span class="hljs-string">'TERMINATOR'</span> <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> nextTag?)
|
||||
endImplicitCall()</pre></div></div>
|
||||
|
||||
</li>
|
||||
@@ -914,7 +934,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 +1217,42 @@ location corresponding to the last “real” token under the node.</p>
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-48">¶</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">-></span>
|
||||
<span class="hljs-function"> <span class="hljs-title">condition</span> = <span class="hljs-params">(token, i)</span> -></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> -></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) ->
|
||||
<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> -></span> @tag(i - <span class="hljs-number">1</span>) <span class="hljs-keyword">is</span> <span class="hljs-string">'PARAM_END'</span>
|
||||
(token, i) -> 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">'->'</span>, <span class="hljs-string">'=>'</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">¶</a>
|
||||
</div>
|
||||
<p>Because our grammar is LALR(1), it can’t handle some single-line
|
||||
expressions that lack ending delimiters. The <strong>Rewriter</strong> adds the implicit
|
||||
blocks, so it doesn’t need to. To keep the grammar clean and tidy, trailing
|
||||
@@ -1207,20 +1263,101 @@ blocks are added.</p>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> normalizeLines: <span class="hljs-function">-></span>
|
||||
starter = indent = outdent = <span class="hljs-literal">null</span>
|
||||
leading_switch_when = <span class="hljs-literal">null</span>
|
||||
leading_if_then = <span class="hljs-literal">null</span></pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-50">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-50">¶</a>
|
||||
</div>
|
||||
<p>Count <code>THEN</code> tags</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> ifThens = []
|
||||
<span class="hljs-function">
|
||||
<span class="hljs-title">condition</span> = <span class="hljs-params">(token, i)</span> -></span>
|
||||
token[<span class="hljs-number">1</span>] <span class="hljs-keyword">isnt</span> <span class="hljs-string">';'</span> <span class="hljs-keyword">and</span> token[<span class="hljs-number">0</span>] <span class="hljs-keyword">in</span> SINGLE_CLOSERS <span class="hljs-keyword">and</span>
|
||||
<span class="hljs-keyword">not</span> (token[<span class="hljs-number">0</span>] <span class="hljs-keyword">is</span> <span class="hljs-string">'TERMINATOR'</span> <span class="hljs-keyword">and</span> @tag(i + <span class="hljs-number">1</span>) <span class="hljs-keyword">in</span> EXPRESSION_CLOSE) <span class="hljs-keyword">and</span>
|
||||
<span class="hljs-keyword">not</span> (token[<span class="hljs-number">0</span>] <span class="hljs-keyword">is</span> <span class="hljs-string">'ELSE'</span> <span class="hljs-keyword">and</span> starter <span class="hljs-keyword">isnt</span> <span class="hljs-string">'THEN'</span>) <span class="hljs-keyword">and</span>
|
||||
<span class="hljs-keyword">not</span> (token[<span class="hljs-number">0</span>] <span class="hljs-keyword">is</span> <span class="hljs-string">'ELSE'</span> <span class="hljs-keyword">and</span>
|
||||
(starter <span class="hljs-keyword">isnt</span> <span class="hljs-string">'THEN'</span> <span class="hljs-keyword">or</span> (leading_if_then <span class="hljs-keyword">or</span> leading_switch_when))) <span class="hljs-keyword">and</span>
|
||||
<span class="hljs-keyword">not</span> (token[<span class="hljs-number">0</span>] <span class="hljs-keyword">in</span> [<span class="hljs-string">'CATCH'</span>, <span class="hljs-string">'FINALLY'</span>] <span class="hljs-keyword">and</span> starter <span class="hljs-keyword">in</span> [<span class="hljs-string">'->'</span>, <span class="hljs-string">'=>'</span>]) <span class="hljs-keyword">or</span>
|
||||
token[<span class="hljs-number">0</span>] <span class="hljs-keyword">in</span> CALL_CLOSERS <span class="hljs-keyword">and</span>
|
||||
(@tokens[i - <span class="hljs-number">1</span>].newLine <span class="hljs-keyword">or</span> @tokens[i - <span class="hljs-number">1</span>][<span class="hljs-number">0</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> -></span>
|
||||
ifThens.pop() <span class="hljs-keyword">if</span> token[<span class="hljs-number">0</span>] <span class="hljs-keyword">is</span> <span class="hljs-string">'ELSE'</span> <span class="hljs-keyword">and</span> starter <span class="hljs-keyword">is</span> <span class="hljs-string">'THEN'</span>
|
||||
@tokens.splice (<span class="hljs-keyword">if</span> @tag(i - <span class="hljs-number">1</span>) <span class="hljs-keyword">is</span> <span class="hljs-string">','</span> <span class="hljs-keyword">then</span> i - <span class="hljs-number">1</span> <span class="hljs-keyword">else</span> i), <span class="hljs-number">0</span>, outdent
|
||||
<span class="hljs-function">
|
||||
<span class="hljs-title">closeElseTag</span> = <span class="hljs-params">(tokens, i)</span> =></span>
|
||||
tlen = ifThens.length
|
||||
<span class="hljs-keyword">return</span> i <span class="hljs-keyword">unless</span> tlen > <span class="hljs-number">0</span>
|
||||
lastThen = ifThens.pop()
|
||||
[, outdentElse] = @indentation tokens[lastThen]</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-51">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-51">¶</a>
|
||||
</div>
|
||||
<p>Insert <code>OUTDENT</code> to close inner <code>IF</code>.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> outdentElse[<span class="hljs-number">1</span>] = tlen*<span class="hljs-number">2</span>
|
||||
tokens.splice(i, <span class="hljs-number">0</span>, outdentElse)</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-52">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-52">¶</a>
|
||||
</div>
|
||||
<p>Insert <code>OUTDENT</code> to close outer <code>IF</code>.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> outdentElse[<span class="hljs-number">1</span>] = <span class="hljs-number">2</span>
|
||||
tokens.splice(i + <span class="hljs-number">1</span>, <span class="hljs-number">0</span>, outdentElse)</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-53">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-53">¶</a>
|
||||
</div>
|
||||
<p>Remove outdents from the end.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> @detectEnd i + <span class="hljs-number">2</span>,
|
||||
<span class="hljs-function"><span class="hljs-params">(token, i)</span> -></span> token[<span class="hljs-number">0</span>] <span class="hljs-keyword">in</span> [<span class="hljs-string">'OUTDENT'</span>, <span class="hljs-string">'TERMINATOR'</span>]
|
||||
(token, i) ->
|
||||
<span class="hljs-keyword">if</span> @tag(i) <span class="hljs-keyword">is</span> <span class="hljs-string">'OUTDENT'</span> <span class="hljs-keyword">and</span> @tag(i + <span class="hljs-number">1</span>) <span class="hljs-keyword">is</span> <span class="hljs-string">'OUTDENT'</span>
|
||||
tokens.splice i, <span class="hljs-number">2</span>
|
||||
i + <span class="hljs-number">2</span>
|
||||
|
||||
@scanTokens (token, i, tokens) ->
|
||||
[tag] = token
|
||||
conditionTag = tag <span class="hljs-keyword">in</span> [<span class="hljs-string">'->'</span>, <span class="hljs-string">'=>'</span>] <span class="hljs-keyword">and</span>
|
||||
@findTagsBackwards(i, [<span class="hljs-string">'IF'</span>, <span class="hljs-string">'WHILE'</span>, <span class="hljs-string">'FOR'</span>, <span class="hljs-string">'UNTIL'</span>, <span class="hljs-string">'SWITCH'</span>, <span class="hljs-string">'WHEN'</span>, <span class="hljs-string">'LEADING_WHEN'</span>, <span class="hljs-string">'['</span>, <span class="hljs-string">'INDEX_START'</span>]) <span class="hljs-keyword">and</span>
|
||||
<span class="hljs-keyword">not</span> (@findTagsBackwards i, [<span class="hljs-string">'THEN'</span>, <span class="hljs-string">'..'</span>, <span class="hljs-string">'...'</span>])
|
||||
|
||||
<span class="hljs-keyword">if</span> tag <span class="hljs-keyword">is</span> <span class="hljs-string">'TERMINATOR'</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">'ELSE'</span> <span class="hljs-keyword">and</span> @tag(i - <span class="hljs-number">1</span>) <span class="hljs-keyword">isnt</span> <span class="hljs-string">'OUTDENT'</span>
|
||||
tokens.splice i, <span class="hljs-number">1</span>, @indentation()...
|
||||
@@ -1237,10 +1374,31 @@ blocks are added.</p>
|
||||
tokens.splice i + <span class="hljs-number">1</span>, <span class="hljs-number">0</span>, indent, outdent
|
||||
<span class="hljs-keyword">return</span> <span class="hljs-number">1</span>
|
||||
<span class="hljs-keyword">if</span> tag <span class="hljs-keyword">in</span> SINGLE_LINERS <span class="hljs-keyword">and</span> @tag(i + <span class="hljs-number">1</span>) <span class="hljs-keyword">isnt</span> <span class="hljs-string">'INDENT'</span> <span class="hljs-keyword">and</span>
|
||||
<span class="hljs-keyword">not</span> (tag <span class="hljs-keyword">is</span> <span class="hljs-string">'ELSE'</span> <span class="hljs-keyword">and</span> @tag(i + <span class="hljs-number">1</span>) <span class="hljs-keyword">is</span> <span class="hljs-string">'IF'</span>)
|
||||
<span class="hljs-keyword">not</span> (tag <span class="hljs-keyword">is</span> <span class="hljs-string">'ELSE'</span> <span class="hljs-keyword">and</span> @tag(i + <span class="hljs-number">1</span>) <span class="hljs-keyword">is</span> <span class="hljs-string">'IF'</span>) <span class="hljs-keyword">and</span>
|
||||
<span class="hljs-keyword">not</span> conditionTag
|
||||
starter = tag
|
||||
[indent, outdent] = @indentation tokens[i]
|
||||
indent.fromThen = <span class="hljs-literal">true</span> <span class="hljs-keyword">if</span> starter <span class="hljs-keyword">is</span> <span class="hljs-string">'THEN'</span>
|
||||
<span class="hljs-keyword">if</span> tag <span class="hljs-keyword">is</span> <span class="hljs-string">'THEN'</span>
|
||||
leading_switch_when = @findTagsBackwards(i, [<span class="hljs-string">'LEADING_WHEN'</span>]) <span class="hljs-keyword">and</span> @tag(i + <span class="hljs-number">1</span>) <span class="hljs-keyword">is</span> <span class="hljs-string">'IF'</span>
|
||||
leading_if_then = @findTagsBackwards(i, [<span class="hljs-string">'IF'</span>]) <span class="hljs-keyword">and</span> @tag(i + <span class="hljs-number">1</span>) <span class="hljs-keyword">is</span> <span class="hljs-string">'IF'</span>
|
||||
ifThens.push i <span class="hljs-keyword">if</span> tag <span class="hljs-keyword">is</span> <span class="hljs-string">'THEN'</span> <span class="hljs-keyword">and</span> @findTagsBackwards(i, [<span class="hljs-string">'IF'</span>])</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-54">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-54">¶</a>
|
||||
</div>
|
||||
<p><code>ELSE</code> tag is not closed.</p>
|
||||
|
||||
</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">'ELSE'</span> <span class="hljs-keyword">and</span> @tag(i - <span class="hljs-number">1</span>) <span class="hljs-keyword">isnt</span> <span class="hljs-string">'OUTDENT'</span>
|
||||
i = closeElseTag tokens, i
|
||||
tokens.splice i + <span class="hljs-number">1</span>, <span class="hljs-number">0</span>, indent
|
||||
@detectEnd i + <span class="hljs-number">2</span>, condition, action
|
||||
tokens.splice i, <span class="hljs-number">1</span> <span class="hljs-keyword">if</span> tag <span class="hljs-keyword">is</span> <span class="hljs-string">'THEN'</span>
|
||||
@@ -1250,11 +1408,11 @@ blocks are added.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-49">
|
||||
<li id="section-55">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-49">¶</a>
|
||||
<a class="pilcrow" href="#section-55">¶</a>
|
||||
</div>
|
||||
<p>Tag postfix conditionals as such, so that we can parse them with a
|
||||
different precedence.</p>
|
||||
@@ -1282,11 +1440,11 @@ different precedence.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-50">
|
||||
<li id="section-56">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-50">¶</a>
|
||||
<a class="pilcrow" href="#section-56">¶</a>
|
||||
</div>
|
||||
<p>Generate the indentation tokens, based on another token on the same line.</p>
|
||||
|
||||
@@ -1307,11 +1465,11 @@ different precedence.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-51">
|
||||
<li id="section-57">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-51">¶</a>
|
||||
<a class="pilcrow" href="#section-57">¶</a>
|
||||
</div>
|
||||
<p>Look up a tag by token index.</p>
|
||||
|
||||
@@ -1322,11 +1480,11 @@ different precedence.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-52">
|
||||
<li id="section-58">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-52">¶</a>
|
||||
<a class="pilcrow" href="#section-58">¶</a>
|
||||
</div>
|
||||
<h2 id="constants">Constants</h2>
|
||||
|
||||
@@ -1335,11 +1493,11 @@ different precedence.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-53">
|
||||
<li id="section-59">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-53">¶</a>
|
||||
<a class="pilcrow" href="#section-59">¶</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -1347,11 +1505,11 @@ different precedence.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-54">
|
||||
<li id="section-60">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-54">¶</a>
|
||||
<a class="pilcrow" href="#section-60">¶</a>
|
||||
</div>
|
||||
<p>List of the token pairs that must be balanced.</p>
|
||||
|
||||
@@ -1372,11 +1530,11 @@ different precedence.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-55">
|
||||
<li id="section-61">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-55">¶</a>
|
||||
<a class="pilcrow" href="#section-61">¶</a>
|
||||
</div>
|
||||
<p>The inverse mappings of <code>BALANCED_PAIRS</code> we’re trying to fix up, so we can
|
||||
look things up from either end.</p>
|
||||
@@ -1388,11 +1546,11 @@ look things up from either end.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-56">
|
||||
<li id="section-62">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-56">¶</a>
|
||||
<a class="pilcrow" href="#section-62">¶</a>
|
||||
</div>
|
||||
<p>The tokens that signal the start/end of a balanced pair.</p>
|
||||
|
||||
@@ -1408,11 +1566,11 @@ EXPRESSION_END = []
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-57">
|
||||
<li id="section-63">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-57">¶</a>
|
||||
<a class="pilcrow" href="#section-63">¶</a>
|
||||
</div>
|
||||
<p>Tokens that indicate the close of a clause of an expression.</p>
|
||||
|
||||
@@ -1423,11 +1581,11 @@ EXPRESSION_END = []
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-58">
|
||||
<li id="section-64">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-58">¶</a>
|
||||
<a class="pilcrow" href="#section-64">¶</a>
|
||||
</div>
|
||||
<p>Tokens that, if followed by an <code>IMPLICIT_CALL</code>, indicate a function invocation.</p>
|
||||
|
||||
@@ -1438,11 +1596,11 @@ EXPRESSION_END = []
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-59">
|
||||
<li id="section-65">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-59">¶</a>
|
||||
<a class="pilcrow" href="#section-65">¶</a>
|
||||
</div>
|
||||
<p>If preceded by an <code>IMPLICIT_FUNC</code>, indicates a function invocation.</p>
|
||||
|
||||
@@ -1462,11 +1620,11 @@ IMPLICIT_UNSPACED_CALL = [<span class="hljs-string">'+'</span>, <span class="hlj
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-60">
|
||||
<li id="section-66">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-60">¶</a>
|
||||
<a class="pilcrow" href="#section-66">¶</a>
|
||||
</div>
|
||||
<p>Tokens that always mark the end of an implicit call for single-liners.</p>
|
||||
|
||||
@@ -1478,11 +1636,11 @@ IMPLICIT_UNSPACED_CALL = [<span class="hljs-string">'+'</span>, <span class="hlj
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-61">
|
||||
<li id="section-67">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-61">¶</a>
|
||||
<a class="pilcrow" href="#section-67">¶</a>
|
||||
</div>
|
||||
<p>Single-line flavors of block expressions that have unclosed endings.
|
||||
The grammar can’t disambiguate them, so we insert the implicit indentation.</p>
|
||||
@@ -1495,11 +1653,11 @@ SINGLE_CLOSERS = [<span class="hljs-string">'TERMINATOR'</span>, <span class="
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-62">
|
||||
<li id="section-68">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-62">¶</a>
|
||||
<a class="pilcrow" href="#section-68">¶</a>
|
||||
</div>
|
||||
<p>Tokens that end a line.</p>
|
||||
|
||||
@@ -1510,11 +1668,11 @@ SINGLE_CLOSERS = [<span class="hljs-string">'TERMINATOR'</span>, <span class="
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-63">
|
||||
<li id="section-69">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-63">¶</a>
|
||||
<a class="pilcrow" href="#section-69">¶</a>
|
||||
</div>
|
||||
<p>Tokens that close open calls when they follow a newline.</p>
|
||||
|
||||
@@ -1525,11 +1683,11 @@ SINGLE_CLOSERS = [<span class="hljs-string">'TERMINATOR'</span>, <span class="
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-64">
|
||||
<li id="section-70">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-64">¶</a>
|
||||
<a class="pilcrow" href="#section-70">¶</a>
|
||||
</div>
|
||||
<p>Tokens that prevent a subsequent indent from ending implicit calls/objects</p>
|
||||
|
||||
@@ -1540,11 +1698,11 @@ SINGLE_CLOSERS = [<span class="hljs-string">'TERMINATOR'</span>, <span class="
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-65">
|
||||
<li id="section-71">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-65">¶</a>
|
||||
<a class="pilcrow" href="#section-71">¶</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 +1716,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>
|
||||
|
||||
@@ -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> -></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>
|
||||
|
||||
|
||||
@@ -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">'<anonymous>'</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>
|
||||
|
||||
|
||||
351
docs/v2/announcing-coffeescript-2/index.html
Normal file
351
docs/v2/announcing-coffeescript-2/index.html
Normal 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 CoffeeScript’s hallmark. In a nutshell:</p>
|
||||
<ul>
|
||||
<li>The CoffeeScript 2 compiler now translates CoffeeScript code into modern JavaScript syntax. So a CoffeeScript <code>=></code> is now output as <code>=></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 compiler’s 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 we’re happy to stop outputting circa-1999 syntax for modern features.</p>
|
||||
<p>Many new JavaScript features, such as <code>=></code>, were informed by CoffeeScript and are one-to-one compatible, or very nearly so. This has made outputting many of CoffeeScript’s innovations into new JS syntax straightforward: not only does <code>=></code> become <code>=></code>, but <code>{ a } = obj</code> becomes <code>{ a } = obj</code>, <code>"a#{b}c"</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>=></code></li>
|
||||
<li>Function default parameters: <code>(options = {}) -></code></li>
|
||||
<li>Function splat/rest parameters: <code>(items...) -></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>"Hello, #{user}!"</code></li>
|
||||
<li>Tagged template literals: <code>html"<strong>coffee</strong>"</code></li>
|
||||
<li>JavaScript’s <code>for…of</code> is now available as CoffeeScript’s <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 JavaScript’s <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 Flow’s 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>. CoffeeScript’s 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 today’s 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, there’s 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>"Hello, #{name}!"</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 haven’t required any updates at all in CoffeeScript. New global objects, or new methods on global objects, don’t require any updates on CoffeeScript’s 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 ECMA’s 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; that’s what’s 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 CoffeeScript’s <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
3085
docs/v2/index.html
3085
docs/v2/index.html
File diff suppressed because one or more lines are too long
2665
docs/v2/test.html
2665
docs/v2/test.html
File diff suppressed because it is too large
Load Diff
@@ -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.
|
||||
|
||||
4
documentation/examples/breaking_change_super_this.coffee
Normal file
4
documentation/examples/breaking_change_super_this.coffee
Normal file
@@ -0,0 +1,4 @@
|
||||
class B extends A
|
||||
constructor: (arg) ->
|
||||
super arg
|
||||
@arg = arg
|
||||
@@ -2,5 +2,5 @@ $ 'body'
|
||||
.click (e) ->
|
||||
$ '.box'
|
||||
.fadeIn 'fast'
|
||||
.addClass '.active'
|
||||
.addClass 'show'
|
||||
.css 'background', 'white'
|
||||
|
||||
@@ -4,4 +4,4 @@ Released under the MIT License
|
||||
###
|
||||
|
||||
sayFortune = (fortune) ->
|
||||
console.log fortune # in bed!
|
||||
console.log fortune # in bed!
|
||||
|
||||
@@ -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 ', '
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 |
@@ -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 & 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 & 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 & Utility Functions — src/helpers](annotated-source/helpers.html)
|
||||
- [The CoffeeScript Module — src/coffeescript](annotated-source/coffeescript.html)
|
||||
- [Cake & 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)
|
||||
|
||||
78
documentation/sections/announcing_coffeescript_2.md
Normal file
78
documentation/sections/announcing_coffeescript_2.md
Normal 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 CoffeeScript’s 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 compiler’s 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 we’re 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 CoffeeScript’s 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>"`
|
||||
- JavaScript’s `for…of` is now available as CoffeeScript’s `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 JavaScript’s [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 Flow’s 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). CoffeeScript’s 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 today’s 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, there’s 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 haven’t required any updates at all in CoffeeScript. New global objects, or new methods on global objects, don’t require any updates on CoffeeScript’s 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 ECMA’s 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; that’s what’s 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 CoffeeScript’s `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!
|
||||
@@ -9,13 +9,6 @@ Class constructors can’t 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 don’t allow bound (fat arrow) methods. The CoffeeScript compiler goes through some contortions to preserve support for them, but one thing that can’t be accommodated is calling a bound method before it is bound:
|
||||
|
||||
```coffee
|
||||
|
||||
20
documentation/sections/breaking_changes_super_this.md
Normal file
20
documentation/sections/breaking_changes_super_this.md
Normal 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')
|
||||
```
|
||||
@@ -1,5 +1,107 @@
|
||||
## Changelog
|
||||
|
||||
```
|
||||
releaseHeader('2018-02-06', '2.2.1', '2.1.0')
|
||||
```
|
||||
* Bugfix for regression in 2.2.0 involving an error thrown by the compiler in certain cases when using destructuring with a splat or expansion in an array.
|
||||
* Bugfix for regression in 2.2.0 where in certain cases a range iterator variable was declared in the global scope.
|
||||
|
||||
```
|
||||
releaseHeader('2018-02-01', '2.2.0', '2.1.1')
|
||||
```
|
||||
* This release fixes *all* currently open bugs, dating as far back as 2014, 2012 and 2011.
|
||||
* **Potential breaking change:** An inline `if` or `switch` statement with an ambiguous `else`, such as `if no then if yes then alert 1 else alert 2`, now compiles where the `else` always corresponds to the closest open `then`. Previously the behavior of an ambiguous `else` was unpredictable. If your code has any `if … then` or `switch … then` statements with multiple `then`s (and one or more `else`s) the compiled output might be different now, unless you had resolved ambiguity via parentheses. We made this change because the previous behavior was inconsistent and basically a bug: depending on what grammar was where, for example if there was an inline function or something that implied a block, the `else` might bind to an earlier `then` rather than a later `then`. Now an `else` essentially closes a block opened by a `then`, similar to closing an open parenthesis.
|
||||
* When a required `then` is missing, the error more accurately points out the location of the mistake.
|
||||
* An error is thrown when the `coffee` command is run in an environment that doesn’t support some ES2015 JavaScript features that the CoffeeScript compiler itself requires. This can happen if CoffeeScript is installed in Node older than version 6.
|
||||
* Destructuring with a non-final splat/spread, e.g. `[open, contents..., close] = tag.split('')` is now output using ES2015 rest syntax.
|
||||
* Functions named `get` or `set` can be used without parentheses in more cases, including when attached to `this` or `@` or `?.`; or when the first argument is an implicit object, e.g. `@set key: 'val'`.
|
||||
* Statements such as `break` can now be used inside parentheses, e.g. `(doSomething(); break) while condition` or `(pick(key); break) for key of obj`.
|
||||
* Bugfix for assigning to a property attached to `this`/`@` in destructuring, e.g. `({@prop = yes, @otherProp = no}) ->`.
|
||||
* Bugfix for incorrect errors being thrown about calling `super` with a parameter attached to `this` when said parameter is in a lower scope, e.g. `class Child extends Parent then constructor: -> super(-> @prop)`.
|
||||
* Bugfix to prevent a possible infinite loop when a `for` loop is given a variable to step by, e.g. `for x in [1..3] by step` (as opposed to `by 0.5` or some other primitive numeric value).
|
||||
* Bugfix to no longer declare iterator variables twice when evaluating a range, e.g. `end = 3; fn [0..end]`.
|
||||
* Bugfix for incorrect scope of variables in chained calls, e.g. `start(x = 3).then(-> x = 4)`.
|
||||
* Bugfix for incorrect scope of variables in a function passed to `do`, e.g. `for [1..3] then masked = 10; do -> alert masked`.
|
||||
* Bugfix to no longer throw a syntax error for a trailing comma in a function call, e.g. `fn arg1, arg2,`.
|
||||
* Bugfix for an expression in a property access, e.g. `a[!b in c..]`.
|
||||
* Bugfix to allow a line continuation backslash (`\`) at any point in a `for` line.
|
||||
|
||||
```
|
||||
releaseHeader('2017-12-29', '2.1.1', '2.1.0')
|
||||
```
|
||||
|
||||
* Bugfix to set the correct context for executable class bodies. So in `class @B extends @A then @property = 1`, the `@` in `@property` now refers to the class, not the global object.
|
||||
* Bugfix where anonymous classes were getting created using the same automatic variable name. They now each receive unique names, so as not to override each other.
|
||||
|
||||
|
||||
```
|
||||
releaseHeader('2017-12-10', '2.1.0', '2.0.3')
|
||||
```
|
||||
|
||||
* Computed property keys in object literals are now supported: `obj = { ['key' + i]: 42 }`, or `obj = [Symbol.iterator]: -> yield i++`.
|
||||
* Skipping of array elements, a.k.a. elision, is now supported: `arr = [a, , b]`, or `[, protocol] = url.match /^(.*):\/\//`.
|
||||
* [JSX fragments syntax](https://reactjs.org/blog/2017/11/28/react-v16.2.0-fragment-support.html) is now supported.
|
||||
* Bugfix where `///` within a `#` line comment inside a `///` block regex was erroneously closing the regex, rather than being treated as part of the comment.
|
||||
* Bugfix for incorrect output for object rest destructuring inside array destructuring.
|
||||
|
||||
```
|
||||
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 aren’t 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 they’re 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 isn’t 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 user’s 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 shouldn’t 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 +261,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 +271,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 +278,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 +293,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.
|
||||
|
||||
@@ -1,17 +1 @@
|
||||
## CoffeeScript 2
|
||||
|
||||
### What’s 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 CoffeeScript’s 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, it’s possible to `extend` an ES class; that wasn’t 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 ES2017’s [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 There’s 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.
|
||||
|
||||
CoffeeScript’s intent, however, was never to be a superset of JavaScript. One of the guiding principles of CoffeeScript has been _simplicity:_ not just removing JavaScript’s “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.
|
||||
|
||||
@@ -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 compiler’s 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]`  | `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).
|
||||
5
documentation/sections/compatibility.md
Normal file
5
documentation/sections/compatibility.md
Normal 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 CoffeeScript’s 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, it’s possible to `extend` a JavaScript class; that wasn’t 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 we’ve documented the differences as [breaking changes](#breaking-changes).
|
||||
@@ -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 you’re looking for has already been discussed. As a general rule, we don’t support ECMAScript syntax for features that aren’t 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 you’re looking for has already been discussed. As a general rule, we don’t support ECMAScript syntax for features that aren’t 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).
|
||||
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
### ES2015+ Output
|
||||
|
||||
CoffeeScript 2 outputs the latest ES2015+ syntax. If you’re 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 2’s 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 you’re 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
|
||||
```
|
||||
@@ -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 project’s 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 project’s dependencies. Within that project’s 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.
|
||||
@@ -5,5 +5,9 @@ The golden rule of CoffeeScript is: _“It’s 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
|
||||
```
|
||||
|
||||
@@ -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).
|
||||
@@ -6,12 +6,6 @@ The CoffeeScript literals for objects and arrays look very similar to their Java
|
||||
codeFor('objects_and_arrays', 'song.join(" … ")')
|
||||
```
|
||||
|
||||
In JavaScript, you can’t use reserved words, like `class`, as properties of an object, without quoting them as strings. CoffeeScript notices reserved words used as keys in objects and quotes them for you, so you don’t have to worry about it (say, when using jQuery).
|
||||
|
||||
```
|
||||
codeFor('objects_reserved')
|
||||
```
|
||||
|
||||
CoffeeScript has a shortcut for creating objects when you want the key to be set with a variable of the same name.
|
||||
|
||||
```
|
||||
|
||||
@@ -18,7 +18,7 @@ You can use `in` to test for array presence, and `of` to test for JavaScript obj
|
||||
|
||||
In a `for` loop, `from` compiles to the [ES2015 `of`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of). (Yes, it’s unfortunate; the CoffeeScript `of` predates the ES2015 `of`.)
|
||||
|
||||
To simplify math expressions, `**` can be used for exponentiation and `//` performs integer division. `%` works just like in JavaScript, while `%%` provides [“dividend dependent modulo”](https://en.wikipedia.org/wiki/Modulo_operation):
|
||||
To simplify math expressions, `**` can be used for exponentiation and `//` performs floor division. `%` works just like in JavaScript, while `%%` provides [“dividend dependent modulo”](https://en.wikipedia.org/wiki/Modulo_operation):
|
||||
|
||||
```
|
||||
codeFor('modulo')
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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. It’s not going to be perfect (infer what your JavaScript classes are, when you need bound functions, and so on…) — but it’s a great starting point for converting simple scripts.
|
||||
* [High-Rez Logo](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.
|
||||
|
||||
@@ -2,6 +2,4 @@
|
||||
|
||||
While it’s not recommended for serious use, CoffeeScripts may be included directly within the browser using `<script type="text/coffeescript">` tags. The source includes a compressed and minified version of the compiler ([Download current version here, 51k when gzipped](/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.
|
||||
|
||||
@@ -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 compiler’s output is the correct syntax; the tests don’t 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)
|
||||
|
||||
49
documentation/sections/transpilation.md
Normal file
49
documentation/sections/transpilation.md
Normal 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 you’re 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 doesn’t do anything—it doesn’t 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 you’re 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 [Babel’s 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 you’re 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 CoffeeScript’s output through Babel using the options you’ve saved.
|
||||
|
||||
If you’re 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 CoffeeScript’s 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 doesn’t 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. You’ll 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/).
|
||||
@@ -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 they’re 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 = ->` can’t both be named `fn`) it’s 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 they’re assigned. Given that this is the case, it’s simplest to just preserve the current behavior.
|
||||
|
||||
5
documentation/sections/whats_new_in_coffeescript_2.md
Normal file
5
documentation/sections/whats_new_in_coffeescript_2.md
Normal file
@@ -0,0 +1,5 @@
|
||||
### What’s 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.
|
||||
@@ -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>
|
||||
47
documentation/site/code.coffee
Normal file
47
documentation/site/code.coffee
Normal 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 '&' else '<'
|
||||
|
||||
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}
|
||||
@@ -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 Bootstrap’s 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;
|
||||
}
|
||||
|
||||
@@ -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> <%= run.replace(/"/g, '"') %><% } %></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, '"') %></button>
|
||||
</div>
|
||||
</div>
|
||||
<% } %>
|
||||
193
documentation/site/docs.coffee
Normal file
193
documentation/site/docs.coffee
Normal 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' # Can’t 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 it’s 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 user’s 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 might’ve thrown off our vertical scroll position
|
||||
document.getElementById(window.location.hash.slice(1).replace(/try:.*/, '')).scrollIntoView()
|
||||
@@ -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;
|
||||
}
|
||||
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
6
documentation/site/logo.svg
Normal file
6
documentation/site/logo.svg
Normal 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 |
16
documentation/site/navbar.html
Normal file
16
documentation/site/navbar.html
Normal 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>
|
||||
3
documentation/site/play.svg
Normal file
3
documentation/site/play.svg
Normal 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 |
19
documentation/site/scripts.html
Normal file
19
documentation/site/scripts.html
Normal 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>
|
||||
83
documentation/site/sidebar.html
Normal file
83
documentation/site/sidebar.html
Normal 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">What’s 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><</code> and <code>></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>
|
||||
@@ -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 Google’s 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>
|
||||
@@ -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 assert’s fail
|
||||
@fail = ->
|
||||
ok no
|
||||
|
||||
# Polyfill Node assert's deepEqual with Underscore's isEqual
|
||||
# Polyfill Node assert’s deepEqual with Underscore’s 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>
|
||||
@@ -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> 
|
||||
<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> 
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
@@ -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 & 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 & 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>
|
||||
@@ -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, '"'
|
||||
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, '"'};#{append}">#{run}</div>""" else ''
|
||||
"<div class='code'>#{cshtml}#{jshtml}#{script}#{load}#{button}<br class='clear' /></div>"
|
||||
@@ -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
@@ -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>
|
||||
@@ -1,4 +0,0 @@
|
||||
<style>
|
||||
<%= include('docs.css') %>
|
||||
<%= include('tomorrow.css') %>
|
||||
</style>
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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}
|
||||
@@ -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' # Can’t 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 it’s 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 user’s 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 might’ve thrown off our vertical scroll position
|
||||
document.getElementById(window.location.hash.slice(1)).scrollIntoView()
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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><</code> and <code>></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>
|
||||
@@ -1,4 +1,4 @@
|
||||
// Generated by CoffeeScript 2.0.0-beta4
|
||||
// Generated by CoffeeScript 2.2.1
|
||||
(function() {
|
||||
// This **Browser** compatibility layer extends core CoffeeScript functions
|
||||
// to make things work smoothly when compiling code directly in the browser.
|
||||
@@ -77,7 +77,7 @@
|
||||
// all script tags with a content-type of `text/coffeescript`.
|
||||
// This happens on page load.
|
||||
runScripts = function() {
|
||||
var coffees, coffeetypes, execute, fn, i, index, j, len, s, script, scripts;
|
||||
var coffees, coffeetypes, execute, i, index, j, len, s, script, scripts;
|
||||
scripts = window.document.getElementsByTagName('script');
|
||||
coffeetypes = ['text/coffeescript', 'text/literate-coffeescript'];
|
||||
coffees = (function() {
|
||||
@@ -101,32 +101,31 @@
|
||||
return execute();
|
||||
}
|
||||
};
|
||||
fn = function(script, i) {
|
||||
var options, source;
|
||||
options = {
|
||||
literate: script.type === coffeetypes[1]
|
||||
};
|
||||
source = script.src || script.getAttribute('data-src');
|
||||
if (source) {
|
||||
options.filename = source;
|
||||
return CoffeeScript.load(source, function(param) {
|
||||
coffees[i] = param;
|
||||
return execute();
|
||||
}, options, true);
|
||||
} else {
|
||||
// `options.filename` defines the filename the source map appears as
|
||||
// in Developer Tools. If a script tag has an `id`, use that as the
|
||||
// filename; otherwise use `coffeescript`, or `coffeescript1` etc.,
|
||||
// leaving the first one unnumbered for the common case that there’s
|
||||
// only one CoffeeScript script block to parse.
|
||||
options.filename = script.id && script.id !== '' ? script.id : `coffeescript${(i !== 0 ? i : '')}`;
|
||||
options.sourceFiles = ['embedded'];
|
||||
return coffees[i] = [script.innerHTML, options];
|
||||
}
|
||||
};
|
||||
for (i = j = 0, len = coffees.length; j < len; i = ++j) {
|
||||
script = coffees[i];
|
||||
fn(script, i);
|
||||
(function(script, i) {
|
||||
var options, source;
|
||||
options = {
|
||||
literate: script.type === coffeetypes[1]
|
||||
};
|
||||
source = script.src || script.getAttribute('data-src');
|
||||
if (source) {
|
||||
options.filename = source;
|
||||
return CoffeeScript.load(source, function(param) {
|
||||
coffees[i] = param;
|
||||
return execute();
|
||||
}, options, true);
|
||||
} else {
|
||||
// `options.filename` defines the filename the source map appears as
|
||||
// in Developer Tools. If a script tag has an `id`, use that as the
|
||||
// filename; otherwise use `coffeescript`, or `coffeescript1` etc.,
|
||||
// leaving the first one unnumbered for the common case that there’s
|
||||
// only one CoffeeScript script block to parse.
|
||||
options.filename = script.id && script.id !== '' ? script.id : `coffeescript${(i !== 0 ? i : '')}`;
|
||||
options.sourceFiles = ['embedded'];
|
||||
return coffees[i] = [script.innerHTML, options];
|
||||
}
|
||||
})(script, i);
|
||||
}
|
||||
return execute();
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Generated by CoffeeScript 2.0.0-beta4
|
||||
// Generated by CoffeeScript 2.2.1
|
||||
(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))
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
// Generated by CoffeeScript 2.0.0-beta4
|
||||
// Generated by CoffeeScript 2.2.1
|
||||
(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 isn’t throwing
|
||||
// exceptions, it’s probably more efficient to compile twice only when we
|
||||
// need a stack trace, rather than always generating a source map even when
|
||||
// it’s not likely to be used. Save in form of `filename`: `(source)`
|
||||
// it’s 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 didn’t 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` that’s 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 isn’t 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()` doesn’t always work,
|
||||
// and it’s 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. That’s 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]);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Generated by CoffeeScript 2.0.0-beta4
|
||||
// Generated by CoffeeScript 2.2.1
|
||||
(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 don’t include Babel as a dependency because we want to
|
||||
// avoid dependencies in general, and most users probably won’t be relying
|
||||
// on us to transpile for them; we assume most users will probably either
|
||||
// run CoffeeScript’s 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']
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Generated by CoffeeScript 2.0.0-beta4
|
||||
// Generated by CoffeeScript 2.2.1
|
||||
(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
|
||||
@@ -97,7 +97,7 @@
|
||||
// Block and statements, which make up a line in a body. YieldReturn is a
|
||||
// statement, but not included in Statement because that results in an ambiguous
|
||||
// grammar.
|
||||
Line: [o('Expression'), o('Statement'), o('FuncDirective')],
|
||||
Line: [o('Expression'), o('ExpressionLine'), o('Statement'), o('FuncDirective')],
|
||||
FuncDirective: [o('YieldReturn'), o('AwaitReturn')],
|
||||
// Pure statements which cannot be expressions.
|
||||
Statement: [
|
||||
@@ -114,6 +114,10 @@
|
||||
// is one. Blocks serve as the building blocks of many other rules, making
|
||||
// them somewhat circular.
|
||||
Expression: [o('Value'), o('Code'), o('Operation'), o('Assign'), o('If'), o('Try'), o('While'), o('For'), o('Switch'), o('Class'), o('Throw'), o('Yield')],
|
||||
// Expressions which are written in single line and would otherwise require being
|
||||
// wrapped in braces: E.g `a = b if do -> f a is 1`, `if f (a) -> a*2 then ...`,
|
||||
// `for x in do (obj) -> f obj when x > 8 then f x`
|
||||
ExpressionLine: [o('CodeLine'), o('IfLine'), o('OperationLine')],
|
||||
Yield: [
|
||||
o('YIELD',
|
||||
function() {
|
||||
@@ -282,7 +286,15 @@
|
||||
});
|
||||
})
|
||||
],
|
||||
SimpleObjAssignable: [o('Identifier'), o('Property'), o('ThisProperty')],
|
||||
SimpleObjAssignable: [
|
||||
o('Identifier'),
|
||||
o('Property'),
|
||||
o('ThisProperty'),
|
||||
o('[ Expression ]',
|
||||
function() {
|
||||
return new Value(new ComputedPropertyName($2));
|
||||
})
|
||||
],
|
||||
ObjAssignable: [o('SimpleObjAssignable'), o('AlphaNumeric')],
|
||||
// Object literal spread properties.
|
||||
ObjRestValue: [
|
||||
@@ -389,7 +401,8 @@
|
||||
function() {
|
||||
return new Code($2,
|
||||
$5,
|
||||
$4);
|
||||
$4,
|
||||
LOC(1)(new Literal($1)));
|
||||
}),
|
||||
o('FuncGlyph Block',
|
||||
function() {
|
||||
@@ -398,6 +411,22 @@
|
||||
$1);
|
||||
})
|
||||
],
|
||||
// The Codeline is the **Code** node with **Line** instead of indented **Block**.
|
||||
CodeLine: [
|
||||
o('PARAM_START ParamList PARAM_END FuncGlyph Line',
|
||||
function() {
|
||||
return new Code($2,
|
||||
LOC(5)(Block.wrap([$5])),
|
||||
$4,
|
||||
LOC(1)(new Literal($1)));
|
||||
}),
|
||||
o('FuncGlyph Line',
|
||||
function() {
|
||||
return new Code([],
|
||||
LOC(2)(Block.wrap([$2])),
|
||||
$1);
|
||||
})
|
||||
],
|
||||
// CoffeeScript has two different symbols for functions. `->` is for ordinary
|
||||
// functions, and `=>` is for functions bound to the current value of *this*.
|
||||
FuncGlyph: [
|
||||
@@ -487,6 +516,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 +850,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),
|
||||
@@ -945,9 +982,14 @@
|
||||
function() {
|
||||
return new Arr([]);
|
||||
}),
|
||||
o('[ ArgList OptComma ]',
|
||||
o('[ Elisions ]',
|
||||
function() {
|
||||
return new Arr($2);
|
||||
}),
|
||||
o('[ ArgElisionList OptElisions ]',
|
||||
function() {
|
||||
return new Arr([].concat($2,
|
||||
$3));
|
||||
})
|
||||
],
|
||||
// Inclusive and exclusive range dots.
|
||||
@@ -968,6 +1010,12 @@
|
||||
return new Range($2,
|
||||
$4,
|
||||
$3);
|
||||
}),
|
||||
o('[ ExpressionLine RangeDots Expression ]',
|
||||
function() {
|
||||
return new Range($2,
|
||||
$4,
|
||||
$3);
|
||||
})
|
||||
],
|
||||
// Array slice literals.
|
||||
@@ -984,6 +1032,18 @@
|
||||
null,
|
||||
$2);
|
||||
}),
|
||||
o('ExpressionLine RangeDots Expression',
|
||||
function() {
|
||||
return new Range($1,
|
||||
$3,
|
||||
$2);
|
||||
}),
|
||||
o('ExpressionLine RangeDots',
|
||||
function() {
|
||||
return new Range($1,
|
||||
null,
|
||||
$2);
|
||||
}),
|
||||
o('RangeDots Expression',
|
||||
function() {
|
||||
return new Range(null,
|
||||
@@ -997,8 +1057,7 @@
|
||||
$1);
|
||||
})
|
||||
],
|
||||
// The **ArgList** is both the list of objects passed into a function call,
|
||||
// as well as the contents of an array literal
|
||||
// The **ArgList** is the list of objects passed into a function call
|
||||
// (i.e. comma-separated expressions). Newlines work as well.
|
||||
ArgList: [
|
||||
o('Arg',
|
||||
@@ -1025,21 +1084,88 @@
|
||||
// Valid arguments are Blocks or Splats.
|
||||
Arg: [
|
||||
o('Expression'),
|
||||
o('ExpressionLine'),
|
||||
o('Splat'),
|
||||
o('...',
|
||||
function() {
|
||||
return new Expansion;
|
||||
})
|
||||
],
|
||||
// The **ArgElisionList** is the list of objects, contents of an array literal
|
||||
// (i.e. comma-separated expressions and elisions). Newlines work as well.
|
||||
ArgElisionList: [
|
||||
o('ArgElision'),
|
||||
o('ArgElisionList , ArgElision',
|
||||
function() {
|
||||
return $1.concat($3);
|
||||
}),
|
||||
o('ArgElisionList OptElisions TERMINATOR ArgElision',
|
||||
function() {
|
||||
return $1.concat($2,
|
||||
$4);
|
||||
}),
|
||||
o('INDENT ArgElisionList OptElisions OUTDENT',
|
||||
function() {
|
||||
return $2.concat($3);
|
||||
}),
|
||||
o('ArgElisionList OptElisions INDENT ArgElisionList OptElisions OUTDENT',
|
||||
function() {
|
||||
return $1.concat($2,
|
||||
$4,
|
||||
$5);
|
||||
})
|
||||
],
|
||||
ArgElision: [
|
||||
o('Arg',
|
||||
function() {
|
||||
return [$1];
|
||||
}),
|
||||
o('Elisions Arg',
|
||||
function() {
|
||||
return $1.concat($2);
|
||||
})
|
||||
],
|
||||
OptElisions: [
|
||||
o('OptComma',
|
||||
function() {
|
||||
return [];
|
||||
}),
|
||||
o(', Elisions',
|
||||
function() {
|
||||
return [].concat($2);
|
||||
})
|
||||
],
|
||||
Elisions: [
|
||||
o('Elision',
|
||||
function() {
|
||||
return [$1];
|
||||
}),
|
||||
o('Elisions Elision',
|
||||
function() {
|
||||
return $1.concat($2);
|
||||
})
|
||||
],
|
||||
Elision: [
|
||||
o(',',
|
||||
function() {
|
||||
return new Elision;
|
||||
})
|
||||
],
|
||||
// Just simple, comma-separated, required arguments (no fancy syntax). We need
|
||||
// this to be separate from the **ArgList** for use in **Switch** blocks, where
|
||||
// having the newlines wouldn't make sense.
|
||||
SimpleArgs: [
|
||||
o('Expression'),
|
||||
o('ExpressionLine'),
|
||||
o('SimpleArgs , Expression',
|
||||
function() {
|
||||
return [].concat($1,
|
||||
$3);
|
||||
}),
|
||||
o('SimpleArgs , ExpressionLine',
|
||||
function() {
|
||||
return [].concat($1,
|
||||
$3);
|
||||
})
|
||||
],
|
||||
// The variants of *try/catch/finally* exception handling blocks.
|
||||
@@ -1113,6 +1239,34 @@
|
||||
})
|
||||
],
|
||||
// The condition portion of a while loop.
|
||||
WhileLineSource: [
|
||||
o('WHILE ExpressionLine',
|
||||
function() {
|
||||
return new While($2);
|
||||
}),
|
||||
o('WHILE ExpressionLine WHEN ExpressionLine',
|
||||
function() {
|
||||
return new While($2,
|
||||
{
|
||||
guard: $4
|
||||
});
|
||||
}),
|
||||
o('UNTIL ExpressionLine',
|
||||
function() {
|
||||
return new While($2,
|
||||
{
|
||||
invert: true
|
||||
});
|
||||
}),
|
||||
o('UNTIL ExpressionLine WHEN ExpressionLine',
|
||||
function() {
|
||||
return new While($2,
|
||||
{
|
||||
invert: true,
|
||||
guard: $4
|
||||
});
|
||||
})
|
||||
],
|
||||
WhileSource: [
|
||||
o('WHILE Expression',
|
||||
function() {
|
||||
@@ -1125,6 +1279,13 @@
|
||||
guard: $4
|
||||
});
|
||||
}),
|
||||
o('WHILE ExpressionLine WHEN Expression',
|
||||
function() {
|
||||
return new While($2,
|
||||
{
|
||||
guard: $4
|
||||
});
|
||||
}),
|
||||
o('UNTIL Expression',
|
||||
function() {
|
||||
return new While($2,
|
||||
@@ -1133,6 +1294,14 @@
|
||||
});
|
||||
}),
|
||||
o('UNTIL Expression WHEN Expression',
|
||||
function() {
|
||||
return new While($2,
|
||||
{
|
||||
invert: true,
|
||||
guard: $4
|
||||
});
|
||||
}),
|
||||
o('UNTIL ExpressionLine WHEN Expression',
|
||||
function() {
|
||||
return new While($2,
|
||||
{
|
||||
@@ -1148,6 +1317,10 @@
|
||||
function() {
|
||||
return $1.addBody($2);
|
||||
}),
|
||||
o('WhileLineSource Block',
|
||||
function() {
|
||||
return $1.addBody($2);
|
||||
}),
|
||||
o('Statement WhileSource',
|
||||
function() {
|
||||
return $2.addBody(LOC(1)(Block.wrap([$1])));
|
||||
@@ -1189,6 +1362,11 @@
|
||||
function() {
|
||||
return new For($2,
|
||||
$1);
|
||||
}),
|
||||
o('ForLineBody Block',
|
||||
function() {
|
||||
return new For($2,
|
||||
$1);
|
||||
})
|
||||
],
|
||||
ForBody: [
|
||||
@@ -1214,6 +1392,23 @@
|
||||
return $2;
|
||||
})
|
||||
],
|
||||
ForLineBody: [
|
||||
o('FOR Range BY ExpressionLine',
|
||||
function() {
|
||||
return {
|
||||
source: LOC(2)(new Value($2)),
|
||||
step: $4
|
||||
};
|
||||
}),
|
||||
o('ForStart ForLineSource',
|
||||
function() {
|
||||
$2.own = $1.own;
|
||||
$2.ownTag = $1.ownTag;
|
||||
$2.name = $1[0];
|
||||
$2.index = $1[1];
|
||||
return $2;
|
||||
})
|
||||
],
|
||||
ForStart: [
|
||||
o('FOR ForVariables',
|
||||
function() {
|
||||
@@ -1278,6 +1473,13 @@
|
||||
guard: $4
|
||||
};
|
||||
}),
|
||||
o('FORIN ExpressionLine WHEN Expression',
|
||||
function() {
|
||||
return {
|
||||
source: $2,
|
||||
guard: $4
|
||||
};
|
||||
}),
|
||||
o('FOROF Expression WHEN Expression',
|
||||
function() {
|
||||
return {
|
||||
@@ -1286,6 +1488,14 @@
|
||||
object: true
|
||||
};
|
||||
}),
|
||||
o('FOROF ExpressionLine WHEN Expression',
|
||||
function() {
|
||||
return {
|
||||
source: $2,
|
||||
guard: $4,
|
||||
object: true
|
||||
};
|
||||
}),
|
||||
o('FORIN Expression BY Expression',
|
||||
function() {
|
||||
return {
|
||||
@@ -1293,6 +1503,13 @@
|
||||
step: $4
|
||||
};
|
||||
}),
|
||||
o('FORIN ExpressionLine BY Expression',
|
||||
function() {
|
||||
return {
|
||||
source: $2,
|
||||
step: $4
|
||||
};
|
||||
}),
|
||||
o('FORIN Expression WHEN Expression BY Expression',
|
||||
function() {
|
||||
return {
|
||||
@@ -1301,6 +1518,30 @@
|
||||
step: $6
|
||||
};
|
||||
}),
|
||||
o('FORIN ExpressionLine WHEN Expression BY Expression',
|
||||
function() {
|
||||
return {
|
||||
source: $2,
|
||||
guard: $4,
|
||||
step: $6
|
||||
};
|
||||
}),
|
||||
o('FORIN Expression WHEN ExpressionLine BY Expression',
|
||||
function() {
|
||||
return {
|
||||
source: $2,
|
||||
guard: $4,
|
||||
step: $6
|
||||
};
|
||||
}),
|
||||
o('FORIN ExpressionLine WHEN ExpressionLine BY Expression',
|
||||
function() {
|
||||
return {
|
||||
source: $2,
|
||||
guard: $4,
|
||||
step: $6
|
||||
};
|
||||
}),
|
||||
o('FORIN Expression BY Expression WHEN Expression',
|
||||
function() {
|
||||
return {
|
||||
@@ -1309,6 +1550,30 @@
|
||||
guard: $6
|
||||
};
|
||||
}),
|
||||
o('FORIN ExpressionLine BY Expression WHEN Expression',
|
||||
function() {
|
||||
return {
|
||||
source: $2,
|
||||
step: $4,
|
||||
guard: $6
|
||||
};
|
||||
}),
|
||||
o('FORIN Expression BY ExpressionLine WHEN Expression',
|
||||
function() {
|
||||
return {
|
||||
source: $2,
|
||||
step: $4,
|
||||
guard: $6
|
||||
};
|
||||
}),
|
||||
o('FORIN ExpressionLine BY ExpressionLine WHEN Expression',
|
||||
function() {
|
||||
return {
|
||||
source: $2,
|
||||
step: $4,
|
||||
guard: $6
|
||||
};
|
||||
}),
|
||||
o('FORFROM Expression',
|
||||
function() {
|
||||
return {
|
||||
@@ -1317,6 +1582,160 @@
|
||||
};
|
||||
}),
|
||||
o('FORFROM Expression WHEN Expression',
|
||||
function() {
|
||||
return {
|
||||
source: $2,
|
||||
guard: $4,
|
||||
from: true
|
||||
};
|
||||
}),
|
||||
o('FORFROM ExpressionLine WHEN Expression',
|
||||
function() {
|
||||
return {
|
||||
source: $2,
|
||||
guard: $4,
|
||||
from: true
|
||||
};
|
||||
})
|
||||
],
|
||||
ForLineSource: [
|
||||
o('FORIN ExpressionLine',
|
||||
function() {
|
||||
return {
|
||||
source: $2
|
||||
};
|
||||
}),
|
||||
o('FOROF ExpressionLine',
|
||||
function() {
|
||||
return {
|
||||
source: $2,
|
||||
object: true
|
||||
};
|
||||
}),
|
||||
o('FORIN Expression WHEN ExpressionLine',
|
||||
function() {
|
||||
return {
|
||||
source: $2,
|
||||
guard: $4
|
||||
};
|
||||
}),
|
||||
o('FORIN ExpressionLine WHEN ExpressionLine',
|
||||
function() {
|
||||
return {
|
||||
source: $2,
|
||||
guard: $4
|
||||
};
|
||||
}),
|
||||
o('FOROF Expression WHEN ExpressionLine',
|
||||
function() {
|
||||
return {
|
||||
source: $2,
|
||||
guard: $4,
|
||||
object: true
|
||||
};
|
||||
}),
|
||||
o('FOROF ExpressionLine WHEN ExpressionLine',
|
||||
function() {
|
||||
return {
|
||||
source: $2,
|
||||
guard: $4,
|
||||
object: true
|
||||
};
|
||||
}),
|
||||
o('FORIN Expression BY ExpressionLine',
|
||||
function() {
|
||||
return {
|
||||
source: $2,
|
||||
step: $4
|
||||
};
|
||||
}),
|
||||
o('FORIN ExpressionLine BY ExpressionLine',
|
||||
function() {
|
||||
return {
|
||||
source: $2,
|
||||
step: $4
|
||||
};
|
||||
}),
|
||||
o('FORIN Expression WHEN Expression BY ExpressionLine',
|
||||
function() {
|
||||
return {
|
||||
source: $2,
|
||||
guard: $4,
|
||||
step: $6
|
||||
};
|
||||
}),
|
||||
o('FORIN ExpressionLine WHEN Expression BY ExpressionLine',
|
||||
function() {
|
||||
return {
|
||||
source: $2,
|
||||
guard: $4,
|
||||
step: $6
|
||||
};
|
||||
}),
|
||||
o('FORIN Expression WHEN ExpressionLine BY ExpressionLine',
|
||||
function() {
|
||||
return {
|
||||
source: $2,
|
||||
guard: $4,
|
||||
step: $6
|
||||
};
|
||||
}),
|
||||
o('FORIN ExpressionLine WHEN ExpressionLine BY ExpressionLine',
|
||||
function() {
|
||||
return {
|
||||
source: $2,
|
||||
guard: $4,
|
||||
step: $6
|
||||
};
|
||||
}),
|
||||
o('FORIN Expression BY Expression WHEN ExpressionLine',
|
||||
function() {
|
||||
return {
|
||||
source: $2,
|
||||
step: $4,
|
||||
guard: $6
|
||||
};
|
||||
}),
|
||||
o('FORIN ExpressionLine BY Expression WHEN ExpressionLine',
|
||||
function() {
|
||||
return {
|
||||
source: $2,
|
||||
step: $4,
|
||||
guard: $6
|
||||
};
|
||||
}),
|
||||
o('FORIN Expression BY ExpressionLine WHEN ExpressionLine',
|
||||
function() {
|
||||
return {
|
||||
source: $2,
|
||||
step: $4,
|
||||
guard: $6
|
||||
};
|
||||
}),
|
||||
o('FORIN ExpressionLine BY ExpressionLine WHEN ExpressionLine',
|
||||
function() {
|
||||
return {
|
||||
source: $2,
|
||||
step: $4,
|
||||
guard: $6
|
||||
};
|
||||
}),
|
||||
o('FORFROM ExpressionLine',
|
||||
function() {
|
||||
return {
|
||||
source: $2,
|
||||
from: true
|
||||
};
|
||||
}),
|
||||
o('FORFROM Expression WHEN ExpressionLine',
|
||||
function() {
|
||||
return {
|
||||
source: $2,
|
||||
guard: $4,
|
||||
from: true
|
||||
};
|
||||
}),
|
||||
o('FORFROM ExpressionLine WHEN ExpressionLine',
|
||||
function() {
|
||||
return {
|
||||
source: $2,
|
||||
@@ -1331,12 +1750,23 @@
|
||||
return new Switch($2,
|
||||
$4);
|
||||
}),
|
||||
o('SWITCH ExpressionLine INDENT Whens OUTDENT',
|
||||
function() {
|
||||
return new Switch($2,
|
||||
$4);
|
||||
}),
|
||||
o('SWITCH Expression INDENT Whens ELSE Block OUTDENT',
|
||||
function() {
|
||||
return new Switch($2,
|
||||
$4,
|
||||
$6);
|
||||
}),
|
||||
o('SWITCH ExpressionLine INDENT Whens ELSE Block OUTDENT',
|
||||
function() {
|
||||
return new Switch($2,
|
||||
$4,
|
||||
$6);
|
||||
}),
|
||||
o('SWITCH INDENT Whens OUTDENT',
|
||||
function() {
|
||||
return new Switch(null,
|
||||
@@ -1418,12 +1848,63 @@
|
||||
});
|
||||
})
|
||||
],
|
||||
IfBlockLine: [
|
||||
o('IF ExpressionLine Block',
|
||||
function() {
|
||||
return new If($2,
|
||||
$3,
|
||||
{
|
||||
type: $1
|
||||
});
|
||||
}),
|
||||
o('IfBlockLine ELSE IF ExpressionLine Block',
|
||||
function() {
|
||||
return $1.addElse(LOC(3,
|
||||
5)(new If($4,
|
||||
$5,
|
||||
{
|
||||
type: $3
|
||||
})));
|
||||
})
|
||||
],
|
||||
IfLine: [
|
||||
o('IfBlockLine'),
|
||||
o('IfBlockLine ELSE Block',
|
||||
function() {
|
||||
return $1.addElse($3);
|
||||
}),
|
||||
o('Statement POST_IF ExpressionLine',
|
||||
function() {
|
||||
return new If($3,
|
||||
LOC(1)(Block.wrap([$1])),
|
||||
{
|
||||
type: $2,
|
||||
statement: true
|
||||
});
|
||||
}),
|
||||
o('Expression POST_IF ExpressionLine',
|
||||
function() {
|
||||
return new If($3,
|
||||
LOC(1)(Block.wrap([$1])),
|
||||
{
|
||||
type: $2,
|
||||
statement: true
|
||||
});
|
||||
})
|
||||
],
|
||||
// Arithmetic and logical operators, working on one or more operands.
|
||||
// Here they are grouped by order of precedence. The actual precedence rules
|
||||
// are defined at the bottom of the page. It would be shorter if we could
|
||||
// combine most of these rules into a single generic *Operand OpSymbol Operand*
|
||||
// -type rule, but in order to make the precedence binding possible, separate
|
||||
// rules are necessary.
|
||||
OperationLine: [
|
||||
o('UNARY ExpressionLine',
|
||||
function() {
|
||||
return new Op($1,
|
||||
$2);
|
||||
})
|
||||
],
|
||||
Operation: [
|
||||
o('UNARY Expression',
|
||||
function() {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Generated by CoffeeScript 2.0.0-beta4
|
||||
// Generated by CoffeeScript 2.2.1
|
||||
(function() {
|
||||
// This file contains the common helper functions that we'd like to share among
|
||||
// the **Lexer**, **Rewriter**, and the **Nodes**. Merge objects, flatten
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Generated by CoffeeScript 2.0.0-beta4
|
||||
// Generated by CoffeeScript 2.2.1
|
||||
(function() {
|
||||
// Node.js Implementation
|
||||
var CoffeeScript, compile, ext, fn, fs, helpers, i, len, path, ref, vm,
|
||||
var CoffeeScript, ext, 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 don’t 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 {
|
||||
@@ -110,31 +137,30 @@
|
||||
// Throw error with deprecation warning when depending upon implicit `require.extensions` registration
|
||||
if (require.extensions) {
|
||||
ref = CoffeeScript.FILE_EXTENSIONS;
|
||||
fn = function(ext) {
|
||||
var base;
|
||||
return (base = require.extensions)[ext] != null ? base[ext] : base[ext] = function() {
|
||||
throw new Error(`Use CoffeeScript.register() or require the coffeescript/register module to require ${ext} files.`);
|
||||
};
|
||||
};
|
||||
for (i = 0, len = ref.length; i < len; i++) {
|
||||
ext = ref[i];
|
||||
fn(ext);
|
||||
(function(ext) {
|
||||
var base;
|
||||
return (base = require.extensions)[ext] != null ? base[ext] : base[ext] = function() {
|
||||
throw new Error(`Use CoffeeScript.register() or require the coffeescript/register module to require ${ext} files.`);
|
||||
};
|
||||
})(ext);
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Generated by CoffeeScript 2.0.0-beta4
|
||||
// Generated by CoffeeScript 2.2.1
|
||||
(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,
|
||||
@@ -10,8 +10,9 @@
|
||||
// where locationData is {first_line, first_column, last_line, last_column}, which is a
|
||||
// format that can be fed directly into [Jison](https://github.com/zaach/jison). These
|
||||
// are read by jison in the `parser.lexer` function defined in coffeescript.coffee.
|
||||
var BOM, BOOL, CALLABLE, CODE, COFFEE_ALIASES, COFFEE_ALIAS_MAP, COFFEE_KEYWORDS, COMMENT, COMPARABLE_LEFT_SIDE, COMPARE, COMPOUND_ASSIGN, CSX_ATTRIBUTE, CSX_IDENTIFIER, CSX_INTERPOLATION, HERECOMMENT_ILLEGAL, HEREDOC_DOUBLE, HEREDOC_INDENT, HEREDOC_SINGLE, HEREGEX, HEREGEX_OMIT, HERE_JSTOKEN, IDENTIFIER, INDENTABLE_CLOSERS, INDEXABLE, INSIDE_CSX, INVERSES, JSTOKEN, JS_KEYWORDS, LEADING_BLANK_LINE, LINE_BREAK, LINE_CONTINUER, Lexer, MATH, MULTI_DENT, NOT_REGEX, NUMBER, OPERATOR, POSSIBLY_DIVISION, REGEX, REGEX_FLAGS, REGEX_ILLEGAL, REGEX_INVALID_ESCAPE, RELATION, RESERVED, Rewriter, SHIFT, SIMPLE_STRING_OMIT, STRICT_PROSCRIBED, STRING_DOUBLE, STRING_INVALID_ESCAPE, STRING_OMIT, STRING_SINGLE, STRING_START, TRAILING_BLANK_LINE, TRAILING_SPACES, UNARY, UNARY_MATH, UNFINISHED, UNICODE_CODE_POINT_ESCAPE, VALID_FLAGS, WHITESPACE, attachCommentsToNode, compact, count, invertLiterate, isForFrom, isUnassignable, key, locationDataToString, merge, repeat, starts, throwSyntaxError,
|
||||
indexOf = [].indexOf;
|
||||
var BOM, BOOL, CALLABLE, CODE, COFFEE_ALIASES, COFFEE_ALIAS_MAP, COFFEE_KEYWORDS, COMMENT, COMPARABLE_LEFT_SIDE, COMPARE, COMPOUND_ASSIGN, CSX_ATTRIBUTE, CSX_FRAGMENT_IDENTIFIER, CSX_IDENTIFIER, CSX_INTERPOLATION, HERECOMMENT_ILLEGAL, HEREDOC_DOUBLE, HEREDOC_INDENT, HEREDOC_SINGLE, HEREGEX, HEREGEX_OMIT, HERE_JSTOKEN, IDENTIFIER, INDENTABLE_CLOSERS, INDEXABLE, INSIDE_CSX, INVERSES, JSTOKEN, JS_KEYWORDS, LEADING_BLANK_LINE, LINE_BREAK, LINE_CONTINUER, Lexer, MATH, MULTI_DENT, NOT_REGEX, NUMBER, OPERATOR, POSSIBLY_DIVISION, REGEX, REGEX_FLAGS, REGEX_ILLEGAL, REGEX_INVALID_ESCAPE, RELATION, RESERVED, Rewriter, SHIFT, SIMPLE_STRING_OMIT, STRICT_PROSCRIBED, STRING_DOUBLE, STRING_INVALID_ESCAPE, STRING_OMIT, STRING_SINGLE, STRING_START, TRAILING_BLANK_LINE, TRAILING_SPACES, UNARY, UNARY_MATH, UNFINISHED, UNICODE_CODE_POINT_ESCAPE, VALID_FLAGS, WHITESPACE, attachCommentsToNode, compact, count, invertLiterate, isForFrom, isUnassignable, key, locationDataToString, merge, repeat, starts, throwSyntaxError,
|
||||
indexOf = [].indexOf,
|
||||
slice = [].slice;
|
||||
|
||||
({Rewriter, INVERSES} = require('./rewriter'));
|
||||
|
||||
@@ -111,7 +112,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, ref10, ref2, ref3, ref4, ref5, ref6, ref7, ref8, ref9, regExSuper, regex, sup, tag, tagToken;
|
||||
inCSXTag = this.atCSXTag();
|
||||
regex = inCSXTag ? CSX_ATTRIBUTE : IDENTIFIER;
|
||||
if (!(match = regex.exec(this.chunk))) {
|
||||
@@ -132,19 +133,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 +166,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 +200,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.length > 1 && ((ref8 = this.tokens[this.tokens.length - 2][0]) !== '.' && ref8 !== '?.' && ref8 !== '@')) {
|
||||
this.error(`'${prev[1]}' cannot be used as a keyword, or as a function call without parentheses`, prev[2]);
|
||||
} else {
|
||||
} else if (this.tokens.length > 2) {
|
||||
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 (((ref9 = prev[0]) === '@' || ref9 === 'THIS') && prevprev && prevprev.spaced && /^[gs]et$/.test(prevprev[1]) && ((ref10 = this.tokens[this.tokens.length - 3][0]) !== '.' && ref10 !== '?.' && ref10 !== '@')) {
|
||||
this.error(`'${prevprev[1]}' cannot be used as a keyword, or as a function call without parentheses`, prevprev[2]);
|
||||
}
|
||||
}
|
||||
@@ -204,7 +214,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];
|
||||
@@ -577,12 +587,16 @@
|
||||
// Keeps track of the level of indentation, because a single outdent token
|
||||
// can close multiple indents, so we need to know how far in we happen to be.
|
||||
lineToken(chunk = this.chunk) {
|
||||
var diff, indent, match, minLiteralLength, newIndentLiteral, noNewlines, size;
|
||||
var backslash, diff, indent, match, minLiteralLength, newIndentLiteral, noNewlines, prev, size;
|
||||
if (!(match = MULTI_DENT.exec(chunk))) {
|
||||
return 0;
|
||||
}
|
||||
indent = match[0];
|
||||
this.seenFor = false;
|
||||
prev = this.prev();
|
||||
backslash = (prev != null) && prev[0] === '\\';
|
||||
if (!(backslash && this.seenFor)) {
|
||||
this.seenFor = false;
|
||||
}
|
||||
if (!this.importSpecifierList) {
|
||||
this.seenImport = false;
|
||||
}
|
||||
@@ -672,9 +686,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 +715,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);
|
||||
}
|
||||
@@ -736,7 +746,7 @@
|
||||
// Check the previous token to detect if attribute is spread.
|
||||
prevChar = this.tokens.length > 0 ? this.tokens[this.tokens.length - 1][0] : '';
|
||||
if (firstChar === '<') {
|
||||
match = CSX_IDENTIFIER.exec(this.chunk.slice(1));
|
||||
match = CSX_IDENTIFIER.exec(this.chunk.slice(1)) || CSX_FRAGMENT_IDENTIFIER.exec(this.chunk.slice(1));
|
||||
// Not the right hand side of an unspaced comparison (i.e. `a<b`).
|
||||
if (!(match && (this.csxDepth > 0 || !(prev = this.prev()) || prev.spaced || (ref = prev[0], indexOf.call(COMPARABLE_LEFT_SIDE, ref) < 0)))) {
|
||||
return 0;
|
||||
@@ -788,8 +798,8 @@
|
||||
delimiter: '>'
|
||||
});
|
||||
});
|
||||
match = CSX_IDENTIFIER.exec(this.chunk.slice(end));
|
||||
if (!match || match[0] !== csxTag.name) {
|
||||
match = CSX_IDENTIFIER.exec(this.chunk.slice(end)) || CSX_FRAGMENT_IDENTIFIER.exec(this.chunk.slice(end));
|
||||
if (!match || match[1] !== csxTag.name) {
|
||||
this.error(`expected corresponding CSX closing tag for ${csxTag.name}`, csxTag.origin[2]);
|
||||
}
|
||||
afterTag = end + csxTag.name.length;
|
||||
@@ -844,7 +854,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 +894,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 +915,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` can’t be a method you can call.
|
||||
tag = 'INDEX_START';
|
||||
switch (prev[0]) {
|
||||
case '?':
|
||||
@@ -1042,7 +1055,7 @@
|
||||
if (braceInterpolator) {
|
||||
// Turn the leading and trailing `{` and `}` into parentheses. Unnecessary
|
||||
// parentheses will be removed later.
|
||||
open = nested[0], close = nested[nested.length - 1];
|
||||
[open] = nested, [close] = slice.call(nested, -1);
|
||||
open[0] = open[1] = '(';
|
||||
close[0] = close[1] = ')';
|
||||
close.origin = ['', 'end of interpolation', close[2]];
|
||||
@@ -1067,7 +1080,7 @@
|
||||
length: delimiter.length
|
||||
});
|
||||
}
|
||||
firstToken = tokens[0], lastToken = tokens[tokens.length - 1];
|
||||
[firstToken] = tokens, [lastToken] = slice.call(tokens, -1);
|
||||
firstToken[2].first_column -= delimiter.length;
|
||||
if (lastToken[1].substr(-1) === '\n') {
|
||||
lastToken[2].last_line += 1;
|
||||
@@ -1089,7 +1102,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 +1113,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.
|
||||
@@ -1144,7 +1181,7 @@
|
||||
this.tokens.push(...tokensToPush);
|
||||
}
|
||||
if (lparen) {
|
||||
lastToken = tokens[tokens.length - 1];
|
||||
[lastToken] = slice.call(tokens, -1);
|
||||
lparen.origin = [
|
||||
'STRING',
|
||||
null,
|
||||
@@ -1170,7 +1207,7 @@
|
||||
// correctly balanced throughout the course of the token stream.
|
||||
pair(tag) {
|
||||
var lastIndent, prev, ref, ref1, wanted;
|
||||
ref = this.ends, prev = ref[ref.length - 1];
|
||||
ref = this.ends, [prev] = slice.call(ref, -1);
|
||||
if (tag !== (wanted = prev != null ? prev.tag : void 0)) {
|
||||
if ('OUTDENT' !== wanted) {
|
||||
this.error(`unmatched ${tag}`);
|
||||
@@ -1180,7 +1217,7 @@
|
||||
// el.click((event) ->
|
||||
// el.hide())
|
||||
|
||||
ref1 = this.indents, lastIndent = ref1[ref1.length - 1];
|
||||
ref1 = this.indents, [lastIndent] = slice.call(ref1, -1);
|
||||
this.outdentToken(lastIndent, true);
|
||||
return this.pair(tag);
|
||||
}
|
||||
@@ -1206,7 +1243,7 @@
|
||||
lineCount = count(string, '\n');
|
||||
column = this.chunkColumn;
|
||||
if (lineCount > 0) {
|
||||
ref = string.split('\n'), lastLine = ref[ref.length - 1];
|
||||
ref = string.split('\n'), [lastLine] = slice.call(ref, -1);
|
||||
column = lastLine.length;
|
||||
} else {
|
||||
column += string.length;
|
||||
@@ -1247,15 +1284,19 @@
|
||||
// Peek at the last tag in the token stream.
|
||||
tag() {
|
||||
var ref, token;
|
||||
ref = this.tokens, token = ref[ref.length - 1];
|
||||
ref = this.tokens, [token] = slice.call(ref, -1);
|
||||
return token != null ? token[0] : void 0;
|
||||
}
|
||||
|
||||
// Peek at the last value in the token stream.
|
||||
value() {
|
||||
var ref, token;
|
||||
ref = this.tokens, token = ref[ref.length - 1];
|
||||
return token != null ? token[1] : void 0;
|
||||
value(useOrigin = false) {
|
||||
var ref, ref1, token;
|
||||
ref = this.tokens, [token] = slice.call(ref, -1);
|
||||
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 +1424,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 = {}) {
|
||||
@@ -1491,6 +1546,9 @@
|
||||
CSX_IDENTIFIER = /^(?![\d<])((?:(?!\s)[\.\-$\w\x7f-\uffff])+)/; // Must not start with `<`.
|
||||
// Like `IDENTIFIER`, but includes `-`s and `.`s.
|
||||
|
||||
// Fragment: <></>
|
||||
CSX_FRAGMENT_IDENTIFIER = /^()>/; // Ends immediately with `>`.
|
||||
|
||||
CSX_ATTRIBUTE = /^(?!\d)((?:(?!\s)[\-$\w\x7f-\uffff])+)([^\S]*=(?!=))?/; // Like `IDENTIFIER`, but includes `-`s.
|
||||
// Is this an attribute with a value?
|
||||
|
||||
@@ -1552,7 +1610,12 @@
|
||||
|
||||
VALID_FLAGS = /^(?!.*(.).*\1)[imguy]*$/;
|
||||
|
||||
HEREGEX = /^(?:[^\\\/#]|\\[\s\S]|\/(?!\/\/)|\#(?!\{))*/;
|
||||
// Match any character, except those that need special handling below.
|
||||
// Match `\` followed by any character.
|
||||
// Match any `/` except `///`.
|
||||
// Match `#` which is not part of interpolation, e.g. `#{}`.
|
||||
// Comments consume everything until the end of the line, including `///`.
|
||||
HEREGEX = /^(?:[^\\\/#\s]|\\[\s\S]|\/(?!\/\/)|\#(?!\{)|\s+(?:#(?!\{).*)?)*/;
|
||||
|
||||
HEREGEX_OMIT = /((?:\\\\)+)|\\(\s)|\s+(?:#.*)?/g; // Consume (and preserve) an even number of backslashes.
|
||||
// Preserve escaped whitespace.
|
||||
@@ -1635,6 +1698,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);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
||||
// Generated by CoffeeScript 2.0.0-beta4
|
||||
// Generated by CoffeeScript 2.2.1
|
||||
(function() {
|
||||
var LONG_FLAG, MULTI_FLAG, OPTIONAL, OptionParser, SHORT_FLAG, buildRule, buildRules, normalizeArguments, repeat,
|
||||
slice = [].slice;
|
||||
splice = [].splice;
|
||||
|
||||
({repeat} = require('./helpers'));
|
||||
|
||||
@@ -44,8 +44,8 @@
|
||||
// `--` argument after, because that will fail on Linux (see #3946).
|
||||
({rules, positional} = normalizeArguments(args, this.rules.flagDict));
|
||||
options = {};
|
||||
// The `argument` field is added to the rule instance non-destructively by
|
||||
// `normalizeArguments`.
|
||||
// The `argument` field is added to the rule instance non-destructively by
|
||||
// `normalizeArguments`.
|
||||
for (i = 0, len = rules.length; i < len; i++) {
|
||||
({hasArgument, argument, isList, name} = rules[i]);
|
||||
if (hasArgument) {
|
||||
@@ -157,7 +157,7 @@
|
||||
};
|
||||
|
||||
normalizeArguments = function(args, flagDict) {
|
||||
var arg, argIndex, flag, i, innerOpts, j, k, lastOpt, len, len1, multiFlags, multiOpts, needsArgOpt, positional, ref, rule, rules, singleRule, withArg;
|
||||
var arg, argIndex, flag, i, innerOpts, j, lastOpt, len, len1, multiFlags, multiOpts, needsArgOpt, positional, ref, rule, rules, singleRule, withArg;
|
||||
rules = [];
|
||||
positional = [];
|
||||
needsArgOpt = null;
|
||||
@@ -187,9 +187,9 @@
|
||||
return {rule, flag};
|
||||
});
|
||||
// Only the last flag in a multi-flag may have an argument.
|
||||
innerOpts = 2 <= multiOpts.length ? slice.call(multiOpts, 0, j = multiOpts.length - 1) : (j = 0, []), lastOpt = multiOpts[j++];
|
||||
for (k = 0, len1 = innerOpts.length; k < len1; k++) {
|
||||
({rule, flag} = innerOpts[k]);
|
||||
[...innerOpts] = multiOpts, [lastOpt] = splice.call(innerOpts, -1);
|
||||
for (j = 0, len1 = innerOpts.length; j < len1; j++) {
|
||||
({rule, flag} = innerOpts[j]);
|
||||
if (rule.hasArgument) {
|
||||
throw new Error(`cannot use option ${flag} in multi-flag ${arg} except as the last option, because it needs an argument`);
|
||||
}
|
||||
|
||||
445
lib/coffeescript/parser.js
Executable file → Normal file
445
lib/coffeescript/parser.js
Executable file → Normal file
File diff suppressed because one or more lines are too long
@@ -1,6 +1,6 @@
|
||||
// Generated by CoffeeScript 2.0.0-beta4
|
||||
// Generated by CoffeeScript 2.2.1
|
||||
(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);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Generated by CoffeeScript 2.0.0-beta4
|
||||
// Generated by CoffeeScript 2.2.1
|
||||
(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) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Generated by CoffeeScript 2.0.0-beta4
|
||||
// Generated by CoffeeScript 2.2.1
|
||||
(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();
|
||||
@@ -217,7 +218,7 @@
|
||||
indexOfTag(i, ...pattern) {
|
||||
var fuzz, j, k, ref, ref1;
|
||||
fuzz = 0;
|
||||
for (j = k = 0, ref = pattern.length; 0 <= ref ? k < ref : k > ref; j = 0 <= ref ? ++k : --k) {
|
||||
for (j = k = 0, ref = pattern.length; undefined !== 0 && (0 <= ref ? 0 <= k && k < ref : 0 >= k && k > ref); j = 0 <= ref ? ++k : --k) {
|
||||
if (pattern[j] == null) {
|
||||
continue;
|
||||
}
|
||||
@@ -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, inControlFlow, 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] : [];
|
||||
@@ -419,10 +420,31 @@
|
||||
}
|
||||
start = stack.pop();
|
||||
}
|
||||
inControlFlow = () => {
|
||||
var controlFlow, isFunc, seenFor, tagCurrentLine;
|
||||
seenFor = this.findTagsBackwards(i, ['FOR']) && this.findTagsBackwards(i, ['FORIN', 'FOROF', 'FORFROM']);
|
||||
controlFlow = seenFor || this.findTagsBackwards(i, ['WHILE', 'UNTIL', 'LOOP', 'LEADING_WHEN']);
|
||||
if (!controlFlow) {
|
||||
return false;
|
||||
}
|
||||
isFunc = false;
|
||||
tagCurrentLine = token[2].first_line;
|
||||
this.detectEnd(i, function(token, i) {
|
||||
var ref;
|
||||
return ref = token[0], indexOf.call(LINEBREAKS, ref) >= 0;
|
||||
}, function(token, i) {
|
||||
var first_line;
|
||||
[prevTag, , {first_line}] = tokens[i - 1] || [];
|
||||
return isFunc = tagCurrentLine === first_line && (prevTag === '->' || prevTag === '=>');
|
||||
}, {
|
||||
returnOnNegativeLevel: true
|
||||
});
|
||||
return isFunc;
|
||||
};
|
||||
// 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) && !inControlFlow()) {
|
||||
if (tag === '?') {
|
||||
tag = token[0] = 'FUNC_EXIST';
|
||||
}
|
||||
@@ -456,9 +478,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 +488,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();
|
||||
@@ -505,11 +527,11 @@
|
||||
}
|
||||
}
|
||||
newLine = prevTag === 'OUTDENT' || prevToken.newLine;
|
||||
if (indexOf.call(IMPLICIT_END, tag) >= 0 || indexOf.call(CALL_CLOSERS, tag) >= 0 && newLine) {
|
||||
if (indexOf.call(IMPLICIT_END, tag) >= 0 || (indexOf.call(CALL_CLOSERS, tag) >= 0 && newLine) || ((tag === '..' || tag === '...') && this.findTagsBackwards(i, ["INDEX_START"]))) {
|
||||
while (inImplicit()) {
|
||||
[stackTag, stackIdx, {sameLine, startsLine}] = stackTop();
|
||||
// Close implicit calls when reached end of argument list
|
||||
if (inImplicitCall() && prevTag !== ',') {
|
||||
if (inImplicitCall() && prevTag !== ',' || (prevTag === ',' && tag === 'TERMINATOR' && (nextTag == null))) {
|
||||
endImplicitCall();
|
||||
// Close implicit objects such as:
|
||||
// return a: 1, b: 2 unless true
|
||||
@@ -538,7 +560,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,24 +756,97 @@
|
||||
});
|
||||
}
|
||||
|
||||
// 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 can’t handle some single-line
|
||||
// expressions that lack ending delimiters. The **Rewriter** adds the implicit
|
||||
// blocks, so it doesn’t need to. To keep the grammar clean and tidy, trailing
|
||||
// newlines within expressions are removed and the indentation tokens of empty
|
||||
// blocks are added.
|
||||
normalizeLines() {
|
||||
var action, condition, indent, outdent, starter;
|
||||
var action, closeElseTag, condition, ifThens, indent, leading_if_then, leading_switch_when, outdent, starter;
|
||||
starter = indent = outdent = null;
|
||||
leading_switch_when = null;
|
||||
leading_if_then = null;
|
||||
// Count `THEN` tags
|
||||
ifThens = [];
|
||||
condition = function(token, i) {
|
||||
var ref, ref1, ref2, ref3;
|
||||
return token[1] !== ';' && (ref = token[0], indexOf.call(SINGLE_CLOSERS, ref) >= 0) && !(token[0] === 'TERMINATOR' && (ref1 = this.tag(i + 1), indexOf.call(EXPRESSION_CLOSE, ref1) >= 0)) && !(token[0] === 'ELSE' && starter !== 'THEN') && !(((ref2 = token[0]) === 'CATCH' || ref2 === 'FINALLY') && (starter === '->' || starter === '=>')) || (ref3 = token[0], indexOf.call(CALL_CLOSERS, ref3) >= 0) && (this.tokens[i - 1].newLine || this.tokens[i - 1][0] === 'OUTDENT');
|
||||
return token[1] !== ';' && (ref = token[0], indexOf.call(SINGLE_CLOSERS, ref) >= 0) && !(token[0] === 'TERMINATOR' && (ref1 = this.tag(i + 1), indexOf.call(EXPRESSION_CLOSE, ref1) >= 0)) && !(token[0] === 'ELSE' && (starter !== 'THEN' || (leading_if_then || leading_switch_when))) && !(((ref2 = token[0]) === 'CATCH' || ref2 === 'FINALLY') && (starter === '->' || starter === '=>')) || (ref3 = token[0], indexOf.call(CALL_CLOSERS, ref3) >= 0) && (this.tokens[i - 1].newLine || this.tokens[i - 1][0] === 'OUTDENT');
|
||||
};
|
||||
action = function(token, i) {
|
||||
if (token[0] === 'ELSE' && starter === 'THEN') {
|
||||
ifThens.pop();
|
||||
}
|
||||
return this.tokens.splice((this.tag(i - 1) === ',' ? i - 1 : i), 0, outdent);
|
||||
};
|
||||
closeElseTag = (tokens, i) => {
|
||||
var lastThen, outdentElse, tlen;
|
||||
tlen = ifThens.length;
|
||||
if (!(tlen > 0)) {
|
||||
return i;
|
||||
}
|
||||
lastThen = ifThens.pop();
|
||||
[, outdentElse] = this.indentation(tokens[lastThen]);
|
||||
// Insert `OUTDENT` to close inner `IF`.
|
||||
outdentElse[1] = tlen * 2;
|
||||
tokens.splice(i, 0, outdentElse);
|
||||
// Insert `OUTDENT` to close outer `IF`.
|
||||
outdentElse[1] = 2;
|
||||
tokens.splice(i + 1, 0, outdentElse);
|
||||
// Remove outdents from the end.
|
||||
this.detectEnd(i + 2, function(token, i) {
|
||||
var ref;
|
||||
return (ref = token[0]) === 'OUTDENT' || ref === 'TERMINATOR';
|
||||
}, function(token, i) {
|
||||
if (this.tag(i) === 'OUTDENT' && this.tag(i + 1) === 'OUTDENT') {
|
||||
return tokens.splice(i, 2);
|
||||
}
|
||||
});
|
||||
return i + 2;
|
||||
};
|
||||
return this.scanTokens(function(token, i, tokens) {
|
||||
var j, k, ref, ref1, tag;
|
||||
var conditionTag, j, k, ref, ref1, tag;
|
||||
[tag] = token;
|
||||
conditionTag = (tag === '->' || tag === '=>') && this.findTagsBackwards(i, ['IF', 'WHILE', 'FOR', 'UNTIL', 'SWITCH', 'WHEN', 'LEADING_WHEN', '[', 'INDEX_START']) && !(this.findTagsBackwards(i, ['THEN', '..', '...']));
|
||||
if (tag === 'TERMINATOR') {
|
||||
if (this.tag(i + 1) === 'ELSE' && this.tag(i - 1) !== 'OUTDENT') {
|
||||
tokens.splice(i, 1, ...this.indentation());
|
||||
@@ -776,12 +871,23 @@
|
||||
tokens.splice(i + 1, 0, indent, outdent);
|
||||
return 1;
|
||||
}
|
||||
if (indexOf.call(SINGLE_LINERS, tag) >= 0 && this.tag(i + 1) !== 'INDENT' && !(tag === 'ELSE' && this.tag(i + 1) === 'IF')) {
|
||||
if (indexOf.call(SINGLE_LINERS, tag) >= 0 && this.tag(i + 1) !== 'INDENT' && !(tag === 'ELSE' && this.tag(i + 1) === 'IF') && !conditionTag) {
|
||||
starter = tag;
|
||||
[indent, outdent] = this.indentation(tokens[i]);
|
||||
if (starter === 'THEN') {
|
||||
indent.fromThen = true;
|
||||
}
|
||||
if (tag === 'THEN') {
|
||||
leading_switch_when = this.findTagsBackwards(i, ['LEADING_WHEN']) && this.tag(i + 1) === 'IF';
|
||||
leading_if_then = this.findTagsBackwards(i, ['IF']) && this.tag(i + 1) === 'IF';
|
||||
}
|
||||
if (tag === 'THEN' && this.findTagsBackwards(i, ['IF'])) {
|
||||
ifThens.push(i);
|
||||
}
|
||||
// `ELSE` tag is not closed.
|
||||
if (tag === 'ELSE' && this.tag(i - 1) !== 'OUTDENT') {
|
||||
i = closeElseTag(tokens, i);
|
||||
}
|
||||
tokens.splice(i + 1, 0, indent);
|
||||
this.detectEnd(i + 2, condition, action);
|
||||
if (tag === 'THEN') {
|
||||
@@ -845,7 +951,7 @@
|
||||
|
||||
return Rewriter;
|
||||
|
||||
})();
|
||||
}).call(this);
|
||||
|
||||
// Constants
|
||||
// ---------
|
||||
@@ -903,6 +1009,6 @@
|
||||
// `STRING_START` isn’t 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);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user