mirror of
https://github.com/jashkenas/coffeescript.git
synced 2026-01-13 16:57:54 -05:00
Compare commits
197 Commits
1.12.5
...
2.0.0-beta
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
db216ec384 | ||
|
|
9b77371ea8 | ||
|
|
d20f54967e | ||
|
|
be7c1be75f | ||
|
|
8292d25d29 | ||
|
|
76945ab458 | ||
|
|
0576eb3a10 | ||
|
|
7129f8347e | ||
|
|
4d25907155 | ||
|
|
b192e215a5 | ||
|
|
5e1d978946 | ||
|
|
a7447d5bba | ||
|
|
2d1addf5a4 | ||
|
|
962374aec1 | ||
|
|
ed4c8286a2 | ||
|
|
fcf7ddaf45 | ||
|
|
725fe8e018 | ||
|
|
5596dac5e1 | ||
|
|
57c0b16eeb | ||
|
|
0c06fb2b9f | ||
|
|
cfdec64958 | ||
|
|
d0c6e53b83 | ||
|
|
27caf62322 | ||
|
|
b8df321058 | ||
|
|
06f6efa6d5 | ||
|
|
c035d53fb0 | ||
|
|
5888ac56d8 | ||
|
|
a6bf72a791 | ||
|
|
3aa177c88f | ||
|
|
608799f5d0 | ||
|
|
97aef9b30d | ||
|
|
ccbf3152af | ||
|
|
f8c150f201 | ||
|
|
a5cb8cd7c3 | ||
|
|
32799ad732 | ||
|
|
d47f90599e | ||
|
|
5817aeb837 | ||
|
|
7de06c3dcb | ||
|
|
6f0f173795 | ||
|
|
221a8720fe | ||
|
|
ff56533e0b | ||
|
|
e88619a3bb | ||
|
|
4cc701a9da | ||
|
|
d2e94c6ebd | ||
|
|
d7d32cf0b6 | ||
|
|
ebe32d35e2 | ||
|
|
ecafe7ce0f | ||
|
|
41a229e22e | ||
|
|
d9194b2670 | ||
|
|
365d1968e9 | ||
|
|
eebc432efb | ||
|
|
dd5aa2b7a4 | ||
|
|
d1d2c16fdd | ||
|
|
ef1898ba42 | ||
|
|
81cbca5bb8 | ||
|
|
da3db1be39 | ||
|
|
396bd4f2f2 | ||
|
|
cbea7b5d1c | ||
|
|
3e7973e08d | ||
|
|
ec5adf53a7 | ||
|
|
48eb173bcd | ||
|
|
69a07dfa6d | ||
|
|
800116d859 | ||
|
|
4f6073f283 | ||
|
|
9e13100f58 | ||
|
|
52bc1dab0b | ||
|
|
ff9f078a89 | ||
|
|
8d81804fee | ||
|
|
0fc625d7e9 | ||
|
|
ef1005b920 | ||
|
|
5cf8256d2e | ||
|
|
f0e884dc4e | ||
|
|
24bef3a1f5 | ||
|
|
5d557a54e1 | ||
|
|
3379f233e8 | ||
|
|
26b1584fd8 | ||
|
|
5fa91e7b95 | ||
|
|
d8bd2b7fd0 | ||
|
|
d02376c4c6 | ||
|
|
69fbb361f2 | ||
|
|
4468ca69c0 | ||
|
|
a4b3a3ba39 | ||
|
|
ad90f4ad99 | ||
|
|
cc8dd150f5 | ||
|
|
7ced071934 | ||
|
|
28d077c08a | ||
|
|
31ff5e4194 | ||
|
|
ea269104bd | ||
|
|
78b21c2483 | ||
|
|
fc42b3ed24 | ||
|
|
c8a3c1a6fd | ||
|
|
58f9428c58 | ||
|
|
3c6e235b32 | ||
|
|
35cfba06b4 | ||
|
|
f01dcd3894 | ||
|
|
e48fea1892 | ||
|
|
47bd5aca58 | ||
|
|
0aa3166709 | ||
|
|
51aaef3d76 | ||
|
|
d62f7adc9b | ||
|
|
853dd456a8 | ||
|
|
462a60da7b | ||
|
|
4abd0fa06d | ||
|
|
b1313962a7 | ||
|
|
2a862d533f | ||
|
|
a825336ba9 | ||
|
|
a55dbc0c37 | ||
|
|
818d262843 | ||
|
|
e05a4e9000 | ||
|
|
c3b3af8746 | ||
|
|
4889109b8d | ||
|
|
93f1f3777c | ||
|
|
14382abc2d | ||
|
|
85b3be9ce3 | ||
|
|
512b580820 | ||
|
|
e90cf16965 | ||
|
|
59001f2fe3 | ||
|
|
db055bb916 | ||
|
|
80fdc6ecc3 | ||
|
|
ff1725b367 | ||
|
|
d278c730ea | ||
|
|
4aa0130a92 | ||
|
|
c7ad70731a | ||
|
|
16dda9c496 | ||
|
|
b2e10e597f | ||
|
|
b2bf505e4c | ||
|
|
9c9058ebb4 | ||
|
|
ece610d682 | ||
|
|
d61d4272ce | ||
|
|
618e851cd6 | ||
|
|
2167a7ab2e | ||
|
|
ec9e559ec0 | ||
|
|
07e4047b7f | ||
|
|
7bb5ccfd80 | ||
|
|
eb36d6e7a2 | ||
|
|
000dc03360 | ||
|
|
0dd727e6eb | ||
|
|
6a845aa4f6 | ||
|
|
9eb7c63158 | ||
|
|
0f10082a21 | ||
|
|
6bd087ebb2 | ||
|
|
c7539e3310 | ||
|
|
e139d59896 | ||
|
|
b481bd1f73 | ||
|
|
2392a91033 | ||
|
|
0145bf397a | ||
|
|
d524dc8ad0 | ||
|
|
d2fb1b5ce8 | ||
|
|
286eec74f9 | ||
|
|
fb3e1a8e65 | ||
|
|
ba3411a1ac | ||
|
|
6685771255 | ||
|
|
e38866b2bf | ||
|
|
6f6df0e48d | ||
|
|
33e6242f6f | ||
|
|
aff191fc53 | ||
|
|
dd0a4f33ee | ||
|
|
4d4839011b | ||
|
|
0ef9eef87d | ||
|
|
14a63149f4 | ||
|
|
ceca091816 | ||
|
|
bc471da960 | ||
|
|
6f595f8fd3 | ||
|
|
42a10ba39e | ||
|
|
a21ce38fdf | ||
|
|
f8fa52a5d7 | ||
|
|
57ffe14fab | ||
|
|
9524159e68 | ||
|
|
dc25f462a9 | ||
|
|
663595ba94 | ||
|
|
8b1c109b9c | ||
|
|
ea3f044816 | ||
|
|
993f459880 | ||
|
|
43e580321a | ||
|
|
327395d793 | ||
|
|
acb3c8d79c | ||
|
|
ad4a6c4877 | ||
|
|
496fd5d3d3 | ||
|
|
a1bcf7f1d9 | ||
|
|
9e0a4f844a | ||
|
|
fb2be8e1e3 | ||
|
|
c04c3850ec | ||
|
|
f14e8b279c | ||
|
|
70a7265f35 | ||
|
|
b35bb20a18 | ||
|
|
def685a4e1 | ||
|
|
8647e50941 | ||
|
|
8b50fd0461 | ||
|
|
01890cd415 | ||
|
|
a1809277a0 | ||
|
|
8138c663a8 | ||
|
|
c5c4d7c8f8 | ||
|
|
f8b0c8049c | ||
|
|
1d230fe055 | ||
|
|
329b2d1cb2 | ||
|
|
bb40b1188c | ||
|
|
98068611b1 |
@@ -4,6 +4,6 @@
|
||||
|
||||
* Before sending a pull request for a feature, be sure to have [tests](https://github.com/jashkenas/coffeescript/tree/master/test).
|
||||
|
||||
* Use the same coding style as the rest of the [codebase](https://github.com/jashkenas/coffeescript/tree/master/src). If you're just getting started with CoffeeScript, there's a nice [style guide](https://github.com/polarmobile/coffeescript-style-guide).
|
||||
* Use the same coding style as the rest of the [codebase](https://github.com/jashkenas/coffeescript/tree/master/src). If you’re just getting started with CoffeeScript, there’s a nice [style guide](https://github.com/polarmobile/coffeescript-style-guide).
|
||||
|
||||
* In your pull request, do not add documentation to `index.html` or re-build the minified `coffee-script.js` file. We'll do those things before cutting a new release.
|
||||
* In your pull request, do not add documentation to `index.html` or re-build the minified `coffeescript.js` file. We’ll do those things before cutting a new release.
|
||||
|
||||
58
Cakefile
58
Cakefile
@@ -2,8 +2,8 @@ fs = require 'fs'
|
||||
path = require 'path'
|
||||
_ = require 'underscore'
|
||||
{ spawn, exec, execSync } = require 'child_process'
|
||||
CoffeeScript = require './lib/coffee-script'
|
||||
helpers = require './lib/coffee-script/helpers'
|
||||
CoffeeScript = require './lib/coffeescript'
|
||||
helpers = require './lib/coffeescript/helpers'
|
||||
|
||||
# ANSI Terminal Colors.
|
||||
bold = red = green = reset = ''
|
||||
@@ -51,7 +51,7 @@ run = (args, callback) ->
|
||||
buildParser = ->
|
||||
helpers.extend global, require 'util'
|
||||
require 'jison'
|
||||
parser = require('./lib/coffee-script/grammar').parser.generate()
|
||||
parser = require('./lib/coffeescript/grammar').parser.generate()
|
||||
# Patch Jison’s output, until https://github.com/zaach/jison/pull/339 is accepted,
|
||||
# to ensure that require('fs') is only called where it exists.
|
||||
parser = parser.replace "var source = require('fs')", """
|
||||
@@ -59,19 +59,19 @@ buildParser = ->
|
||||
var fs = require('fs');
|
||||
if (typeof fs !== 'undefined' && fs !== null)
|
||||
source = fs"""
|
||||
fs.writeFileSync 'lib/coffee-script/parser.js', parser
|
||||
fs.writeFileSync 'lib/coffeescript/parser.js', parser
|
||||
|
||||
buildExceptParser = (callback) ->
|
||||
files = fs.readdirSync 'src'
|
||||
files = ('src/' + file for file in files when file.match(/\.(lit)?coffee$/))
|
||||
run ['-c', '-o', 'lib/coffee-script'].concat(files), callback
|
||||
run ['-c', '-o', 'lib/coffeescript'].concat(files), callback
|
||||
|
||||
build = (callback) ->
|
||||
buildParser()
|
||||
buildExceptParser callback
|
||||
|
||||
testBuiltCode = (watch = no) ->
|
||||
csPath = './lib/coffee-script'
|
||||
csPath = './lib/coffeescript'
|
||||
csDir = path.dirname require.resolve csPath
|
||||
|
||||
for mod of require.cache when csDir is mod[0 ... csDir.length]
|
||||
@@ -122,11 +122,19 @@ task 'build:browser', 'build the merged script for inclusion in the browser', ->
|
||||
return #{fs.readFileSync "./package.json"};
|
||||
})();
|
||||
"""
|
||||
for name in ['helpers', 'rewriter', 'lexer', 'parser', 'scope', 'nodes', 'sourcemap', 'coffee-script', 'browser']
|
||||
for {name, src} in [{name: 'markdown-it', src: 'dist/markdown-it.min.js'}]
|
||||
code += """
|
||||
require['#{name}'] = (function() {
|
||||
var exports = {}, module = {exports: exports};
|
||||
#{fs.readFileSync "node_modules/#{name}/#{src}"}
|
||||
return module.exports;
|
||||
})();
|
||||
"""
|
||||
for name in ['helpers', 'rewriter', 'lexer', 'parser', 'scope', 'nodes', 'sourcemap', 'coffeescript', 'browser']
|
||||
code += """
|
||||
require['./#{name}'] = (function() {
|
||||
var exports = {}, module = {exports: exports};
|
||||
#{fs.readFileSync "lib/coffee-script/#{name}.js"}
|
||||
#{fs.readFileSync "lib/coffeescript/#{name}.js"}
|
||||
return module.exports;
|
||||
})();
|
||||
"""
|
||||
@@ -135,7 +143,7 @@ task 'build:browser', 'build the merged script for inclusion in the browser', ->
|
||||
var CoffeeScript = function() {
|
||||
function require(path){ return require[path]; }
|
||||
#{code}
|
||||
return require['./coffee-script'];
|
||||
return require['./coffeescript'];
|
||||
}();
|
||||
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
@@ -153,7 +161,7 @@ task 'build:browser', 'build the merged script for inclusion in the browser', ->
|
||||
]
|
||||
outputFolder = "docs/v#{majorVersion}/browser-compiler"
|
||||
fs.mkdirSync outputFolder unless fs.existsSync outputFolder
|
||||
fs.writeFileSync "#{outputFolder}/coffee-script.js", header + '\n' + code
|
||||
fs.writeFileSync "#{outputFolder}/coffeescript.js", header + '\n' + code
|
||||
console.log "built ... running browser tests:"
|
||||
invoke 'test:browser'
|
||||
|
||||
@@ -191,9 +199,19 @@ buildDocs = (watch = no) ->
|
||||
codeFor = require "./documentation/v#{majorVersion}/code.coffee"
|
||||
|
||||
htmlFor = ->
|
||||
hljs = require 'highlight.js'
|
||||
hljs.configure classPrefix: ''
|
||||
markdownRenderer = require('markdown-it')
|
||||
html: yes
|
||||
typographer: yes
|
||||
highlight: (str, lang) ->
|
||||
# From https://github.com/markdown-it/markdown-it#syntax-highlighting
|
||||
if lang and hljs.getLanguage(lang)
|
||||
try
|
||||
return hljs.highlight(lang, str).value
|
||||
catch ex
|
||||
return '' # No syntax highlighting
|
||||
|
||||
|
||||
# Add some custom overrides to Markdown-It’s rendering, per
|
||||
# https://github.com/markdown-it/markdown-it/blob/master/docs/architecture.md#renderer
|
||||
@@ -327,8 +345,8 @@ task 'release', 'build and test the CoffeeScript source, and build the documenta
|
||||
invoke 'doc:source'
|
||||
|
||||
task 'bench', 'quick benchmark of compilation time', ->
|
||||
{Rewriter} = require './lib/coffee-script/rewriter'
|
||||
sources = ['coffee-script', 'grammar', 'helpers', 'lexer', 'nodes', 'rewriter']
|
||||
{Rewriter} = require './lib/coffeescript/rewriter'
|
||||
sources = ['coffeescript', 'grammar', 'helpers', 'lexer', 'nodes', 'rewriter']
|
||||
coffee = sources.map((name) -> fs.readFileSync "src/#{name}.coffee").join '\n'
|
||||
litcoffee = fs.readFileSync("src/scope.litcoffee").toString()
|
||||
fmt = (ms) -> " #{bold}#{ " #{ms}".slice -4 }#{reset} ms"
|
||||
@@ -351,16 +369,20 @@ task 'bench', 'quick benchmark of compilation time', ->
|
||||
# Run the CoffeeScript test suite.
|
||||
runTests = (CoffeeScript) ->
|
||||
CoffeeScript.register()
|
||||
startTime = Date.now()
|
||||
currentFile = null
|
||||
passedTests = 0
|
||||
failures = []
|
||||
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
|
||||
# `global.test`.
|
||||
global.currentFile = null
|
||||
global.passedTests = 0
|
||||
global.failures = []
|
||||
|
||||
global[name] = func for name, func of require 'assert'
|
||||
|
||||
# Convenience aliases.
|
||||
global.CoffeeScript = CoffeeScript
|
||||
global.Repl = require './lib/coffee-script/repl'
|
||||
global.Repl = require './lib/coffeescript/repl'
|
||||
|
||||
# Our test helper function for delimiting different test cases.
|
||||
global.test = (description, fn) ->
|
||||
@@ -411,7 +433,7 @@ task 'test', 'run the CoffeeScript language test suite', ->
|
||||
|
||||
|
||||
task 'test:browser', 'run the test suite against the merged browser script', ->
|
||||
source = fs.readFileSync "docs/v#{majorVersion}/browser-compiler/coffee-script.js", 'utf-8'
|
||||
source = fs.readFileSync "docs/v#{majorVersion}/browser-compiler/coffeescript.js", 'utf-8'
|
||||
result = {}
|
||||
global.testingBrowser = yes
|
||||
(-> eval source).call result
|
||||
|
||||
@@ -25,7 +25,7 @@ CoffeeScript is a little language that compiles into JavaScript.
|
||||
If you have the node package manager, npm, installed:
|
||||
|
||||
```shell
|
||||
npm install --global coffee-script
|
||||
npm install --global coffeescript
|
||||
```
|
||||
|
||||
Leave off the `--global` if you don’t wish to install globally.
|
||||
|
||||
2
bin/cake
2
bin/cake
@@ -4,4 +4,4 @@ var path = require('path');
|
||||
var fs = require('fs');
|
||||
var lib = path.join(path.dirname(fs.realpathSync(__filename)), '../lib');
|
||||
|
||||
require(lib + '/coffee-script/cake').run();
|
||||
require(lib + '/coffeescript/cake').run();
|
||||
|
||||
@@ -4,4 +4,4 @@ var path = require('path');
|
||||
var fs = require('fs');
|
||||
var lib = path.join(path.dirname(fs.realpathSync(__filename)), '../lib');
|
||||
|
||||
require(lib + '/coffee-script/command').run();
|
||||
require(lib + '/coffeescript/command').run();
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "coffee-script",
|
||||
"name": "coffeescript",
|
||||
"main": [
|
||||
"lib/coffee-script/coffee-script.js"
|
||||
"lib/coffeescript/coffeescript.js"
|
||||
],
|
||||
"description": "Unfancy JavaScript",
|
||||
"keywords": [
|
||||
|
||||
@@ -996,6 +996,7 @@ and optional references to the superclass.</p>
|
||||
o <span class="hljs-string">'Identifier AS Identifier'</span>, <span class="hljs-function">-></span> <span class="hljs-keyword">new</span> ExportSpecifier $<span class="hljs-number">1</span>, $<span class="hljs-number">3</span>
|
||||
o <span class="hljs-string">'Identifier AS DEFAULT'</span>, <span class="hljs-function">-></span> <span class="hljs-keyword">new</span> ExportSpecifier $<span class="hljs-number">1</span>, <span class="hljs-keyword">new</span> Literal $<span class="hljs-number">3</span>
|
||||
o <span class="hljs-string">'DEFAULT'</span>, <span class="hljs-function">-></span> <span class="hljs-keyword">new</span> ExportSpecifier <span class="hljs-keyword">new</span> Literal $<span class="hljs-number">1</span>
|
||||
o <span class="hljs-string">'DEFAULT AS Identifier'</span>, <span class="hljs-function">-></span> <span class="hljs-keyword">new</span> ExportSpecifier <span class="hljs-keyword">new</span> Literal($<span class="hljs-number">1</span>), $<span class="hljs-number">3</span>
|
||||
]</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -122,7 +122,7 @@ arrays, count characters, that sort of thing.</p>
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre>
|
||||
marked = <span class="hljs-built_in">require</span> <span class="hljs-string">'marked'</span></pre></div></div>
|
||||
md = <span class="hljs-built_in">require</span>(<span class="hljs-string">'markdown-it'</span>)()</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -133,27 +133,6 @@ marked = <span class="hljs-built_in">require</span> <span class="hljs-string">'m
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-2">¶</a>
|
||||
</div>
|
||||
<p>marked.setOptions
|
||||
renderer: new marked.Renderer()
|
||||
gfm: true
|
||||
tables: true
|
||||
breaks: false
|
||||
pedantic: false
|
||||
sanitize: true
|
||||
smartLists: true
|
||||
smartypants: false</p>
|
||||
|
||||
</div>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-3">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-3">¶</a>
|
||||
</div>
|
||||
<p>Peek at the beginning of a given string to see if it matches a sequence.</p>
|
||||
|
||||
</div>
|
||||
@@ -164,11 +143,11 @@ marked = <span class="hljs-built_in">require</span> <span class="hljs-string">'m
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-4">
|
||||
<li id="section-3">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-4">¶</a>
|
||||
<a class="pilcrow" href="#section-3">¶</a>
|
||||
</div>
|
||||
<p>Peek at the end of a given string to see if it matches a sequence.</p>
|
||||
|
||||
@@ -181,11 +160,11 @@ marked = <span class="hljs-built_in">require</span> <span class="hljs-string">'m
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-5">
|
||||
<li id="section-4">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-5">¶</a>
|
||||
<a class="pilcrow" href="#section-4">¶</a>
|
||||
</div>
|
||||
<p>Repeat a string <code>n</code> times.</p>
|
||||
|
||||
@@ -196,11 +175,11 @@ marked = <span class="hljs-built_in">require</span> <span class="hljs-string">'m
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-6">
|
||||
<li id="section-5">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-6">¶</a>
|
||||
<a class="pilcrow" href="#section-5">¶</a>
|
||||
</div>
|
||||
<p>Use clever algorithm to have O(log(n)) string concatenation operations.</p>
|
||||
|
||||
@@ -216,11 +195,11 @@ marked = <span class="hljs-built_in">require</span> <span class="hljs-string">'m
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-7">
|
||||
<li id="section-6">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-7">¶</a>
|
||||
<a class="pilcrow" href="#section-6">¶</a>
|
||||
</div>
|
||||
<p>Trim out all falsy values from an array.</p>
|
||||
|
||||
@@ -232,11 +211,11 @@ marked = <span class="hljs-built_in">require</span> <span class="hljs-string">'m
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-8">
|
||||
<li id="section-7">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-8">¶</a>
|
||||
<a class="pilcrow" href="#section-7">¶</a>
|
||||
</div>
|
||||
<p>Count the number of occurrences of a string in a string.</p>
|
||||
|
||||
@@ -251,11 +230,11 @@ marked = <span class="hljs-built_in">require</span> <span class="hljs-string">'m
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-9">
|
||||
<li id="section-8">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-9">¶</a>
|
||||
<a class="pilcrow" href="#section-8">¶</a>
|
||||
</div>
|
||||
<p>Merge objects, returning a fresh copy with attributes from both sides.
|
||||
Used every time <code>Base#compile</code> is called, to allow properties in the
|
||||
@@ -269,11 +248,11 @@ options hash to propagate down the tree without polluting other branches.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-10">
|
||||
<li id="section-9">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-10">¶</a>
|
||||
<a class="pilcrow" href="#section-9">¶</a>
|
||||
</div>
|
||||
<p>Extend a source object with the properties of another object (shallow copy).</p>
|
||||
|
||||
@@ -287,11 +266,11 @@ options hash to propagate down the tree without polluting other branches.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-11">
|
||||
<li id="section-10">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-11">¶</a>
|
||||
<a class="pilcrow" href="#section-10">¶</a>
|
||||
</div>
|
||||
<p>Return a flattened version of an array.
|
||||
Handy for getting a list of <code>children</code> from the nodes.</p>
|
||||
@@ -310,11 +289,11 @@ Handy for getting a list of <code>children</code> from the nodes.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-12">
|
||||
<li id="section-11">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-12">¶</a>
|
||||
<a class="pilcrow" href="#section-11">¶</a>
|
||||
</div>
|
||||
<p>Delete a key from an object, returning the value. Useful when a node is
|
||||
looking for a particular method in an options hash.</p>
|
||||
@@ -329,11 +308,11 @@ looking for a particular method in an options hash.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-13">
|
||||
<li id="section-12">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-13">¶</a>
|
||||
<a class="pilcrow" href="#section-12">¶</a>
|
||||
</div>
|
||||
<p>Typical Array::some</p>
|
||||
|
||||
@@ -346,19 +325,43 @@ looking for a particular method in an options hash.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-13">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-13">¶</a>
|
||||
</div>
|
||||
<p>Simple function for extracting code from Literate CoffeeScript by stripping
|
||||
out all non-code blocks, producing a string of CoffeeScript code that can
|
||||
be compiled “normally.” Uses <a href="https://markdown-it.github.io/">MarkdownIt</a>
|
||||
to tell the difference between Markdown and code blocks.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre>exports.invertLiterate = <span class="hljs-function"><span class="hljs-params">(code)</span> -></span>
|
||||
out = []
|
||||
md.renderer.rules =</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-14">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-14">¶</a>
|
||||
</div>
|
||||
<p>Simple function for extracting code from Literate CoffeeScript by stripping
|
||||
out all non-code blocks, producing a string of CoffeeScript code that can
|
||||
be compiled “normally.”</p>
|
||||
<p>Delete all other rules, since all we want are the code blocks.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre>exports.invertLiterate = <span class="hljs-function"><span class="hljs-params">(code)</span> -></span></pre></div></div>
|
||||
<div class="content"><div class='highlight'><pre> code_block: <span class="hljs-function"><span class="hljs-params">(tokens, idx, options, env, slf)</span> -></span>
|
||||
startLine = tokens[idx].map[<span class="hljs-number">0</span>]
|
||||
lines = tokens[idx].content.split <span class="hljs-string">'\n'</span>
|
||||
<span class="hljs-keyword">for</span> line, i <span class="hljs-keyword">in</span> lines
|
||||
out[startLine + i] = line
|
||||
md.render code
|
||||
out.join <span class="hljs-string">'\n'</span></pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -369,60 +372,6 @@ be compiled “normally.”</p>
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-15">¶</a>
|
||||
</div>
|
||||
<p>Create a placeholder for tabs, that isn’t used anywhere in <code>code</code>, and then
|
||||
re-insert the tabs after code extraction.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre><span class="hljs-function"> <span class="hljs-title">generateRandomToken</span> = -></span>
|
||||
<span class="hljs-string">"<span class="hljs-subst">#{Math.random() * Date.now()}</span>"</span>
|
||||
<span class="hljs-keyword">while</span> token <span class="hljs-keyword">is</span> <span class="hljs-literal">undefined</span> <span class="hljs-keyword">or</span> code.indexOf(token) <span class="hljs-keyword">isnt</span> <span class="hljs-number">-1</span>
|
||||
token = generateRandomToken()
|
||||
|
||||
code = code.replace <span class="hljs-string">"\t"</span>, token</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-16">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-16">¶</a>
|
||||
</div>
|
||||
<p>Parse as markdown, discard everything except code blocks.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> out = <span class="hljs-string">""</span>
|
||||
<span class="hljs-keyword">for</span> item <span class="hljs-keyword">in</span> marked.lexer code, {}
|
||||
out += <span class="hljs-string">"<span class="hljs-subst">#{item.text}</span>\n"</span> <span class="hljs-keyword">if</span> item.type <span class="hljs-keyword">is</span> <span class="hljs-string">'code'</span></pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-17">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-17">¶</a>
|
||||
</div>
|
||||
<p>Put the tabs back in.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> out.replace token, <span class="hljs-string">"\t"</span>
|
||||
out</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-18">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-18">¶</a>
|
||||
</div>
|
||||
<p>Merge two jison-style location data objects together.
|
||||
If <code>last</code> is not provided, this will simply return <code>first</code>.</p>
|
||||
|
||||
@@ -440,11 +389,11 @@ If <code>last</code> is not provided, this will simply return <code>first</code>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-19">
|
||||
<li id="section-16">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-19">¶</a>
|
||||
<a class="pilcrow" href="#section-16">¶</a>
|
||||
</div>
|
||||
<p>This returns a function which takes an object as a parameter, and if that
|
||||
object is an AST node, updates that object’s locationData.
|
||||
@@ -462,11 +411,11 @@ The object is returned either way.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-20">
|
||||
<li id="section-17">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-20">¶</a>
|
||||
<a class="pilcrow" href="#section-17">¶</a>
|
||||
</div>
|
||||
<p>Convert jison location data to a string.
|
||||
<code>obj</code> can be a token, or a locationData.</p>
|
||||
@@ -486,11 +435,11 @@ The object is returned either way.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-21">
|
||||
<li id="section-18">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-21">¶</a>
|
||||
<a class="pilcrow" href="#section-18">¶</a>
|
||||
</div>
|
||||
<p>A <code>.coffee.md</code> compatible version of <code>basename</code>, that returns the file sans-extension.</p>
|
||||
|
||||
@@ -509,11 +458,11 @@ The object is returned either way.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-22">
|
||||
<li id="section-19">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-22">¶</a>
|
||||
<a class="pilcrow" href="#section-19">¶</a>
|
||||
</div>
|
||||
<p>Determine if a filename represents a CoffeeScript file.</p>
|
||||
|
||||
@@ -524,11 +473,11 @@ The object is returned either way.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-23">
|
||||
<li id="section-20">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-23">¶</a>
|
||||
<a class="pilcrow" href="#section-20">¶</a>
|
||||
</div>
|
||||
<p>Determine if a filename represents a Literate CoffeeScript file.</p>
|
||||
|
||||
@@ -539,11 +488,11 @@ The object is returned either way.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-24">
|
||||
<li id="section-21">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-24">¶</a>
|
||||
<a class="pilcrow" href="#section-21">¶</a>
|
||||
</div>
|
||||
<p>Throws a SyntaxError from a given location.
|
||||
The error’s <code>toString</code> will return an error message following the “standard”
|
||||
@@ -560,11 +509,11 @@ marker showing where the error is.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-25">
|
||||
<li id="section-22">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-25">¶</a>
|
||||
<a class="pilcrow" href="#section-22">¶</a>
|
||||
</div>
|
||||
<p>Instead of showing the compiler’s stacktrace, show our custom error message
|
||||
(this is useful when the error bubbles up in Node.js applications that
|
||||
@@ -579,11 +528,11 @@ compile CoffeeScript for example).</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-26">
|
||||
<li id="section-23">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-26">¶</a>
|
||||
<a class="pilcrow" href="#section-23">¶</a>
|
||||
</div>
|
||||
<p>Update a compiler SyntaxError with source code information if it didn’t have
|
||||
it already.</p>
|
||||
@@ -595,11 +544,11 @@ it already.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-27">
|
||||
<li id="section-24">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-27">¶</a>
|
||||
<a class="pilcrow" href="#section-24">¶</a>
|
||||
</div>
|
||||
<p>Avoid screwing up the <code>stack</code> property of other errors (i.e. possible bugs).</p>
|
||||
|
||||
@@ -625,11 +574,11 @@ it already.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-28">
|
||||
<li id="section-25">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-28">¶</a>
|
||||
<a class="pilcrow" href="#section-25">¶</a>
|
||||
</div>
|
||||
<p>Show only the first line on multi-line errors.</p>
|
||||
|
||||
@@ -641,11 +590,11 @@ it already.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-29">
|
||||
<li id="section-26">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-29">¶</a>
|
||||
<a class="pilcrow" href="#section-26">¶</a>
|
||||
</div>
|
||||
<p>Check to see if we’re running on a color-enabled TTY.</p>
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
@@ -440,7 +440,8 @@ test "#1192: assignment starting with object literals", ->
|
||||
# Destructuring Assignment
|
||||
|
||||
test "empty destructuring assignment", ->
|
||||
{} = [] = undefined
|
||||
{} = {}
|
||||
[] = []
|
||||
|
||||
test "chained destructuring assignments", ->
|
||||
[a] = {0: b} = {'0': c} = [nonce={}]
|
||||
@@ -603,7 +604,7 @@ test "simple array destructuring defaults", ->
|
||||
[a = 2] = [undefined]
|
||||
eq 2, a
|
||||
[a = 3] = [null]
|
||||
eq 3, a
|
||||
eq null, a # Breaking change in CS2: per ES2015, default values are applied for `undefined` but not for `null`.
|
||||
[a = 4] = [0]
|
||||
eq 0, a
|
||||
arr = [a = 5]
|
||||
@@ -616,7 +617,7 @@ test "simple object destructuring defaults", ->
|
||||
{b = 2} = {b: undefined}
|
||||
eq b, 2
|
||||
{b = 3} = {b: null}
|
||||
eq b, 3
|
||||
eq b, null # Breaking change in CS2: per ES2015, default values are applied for `undefined` but not for `null`.
|
||||
{b = 4} = {b: 0}
|
||||
eq b, 0
|
||||
|
||||
@@ -625,17 +626,17 @@ test "simple object destructuring defaults", ->
|
||||
{b: c = 2} = {b: undefined}
|
||||
eq c, 2
|
||||
{b: c = 3} = {b: null}
|
||||
eq c, 3
|
||||
eq c, null # Breaking change in CS2: per ES2015, default values are applied for `undefined` but not for `null`.
|
||||
{b: c = 4} = {b: 0}
|
||||
eq c, 0
|
||||
|
||||
test "multiple array destructuring defaults", ->
|
||||
[a = 1, b = 2, c] = [null, 12, 13]
|
||||
[a = 1, b = 2, c] = [undefined, 12, 13]
|
||||
eq a, 1
|
||||
eq b, 12
|
||||
eq c, 13
|
||||
[a, b = 2, c = 3] = [null, 12, 13]
|
||||
eq a, null
|
||||
[a, b = 2, c = 3] = [undefined, 12, 13]
|
||||
eq a, undefined
|
||||
eq b, 12
|
||||
eq c, 13
|
||||
[a = 1, b, c = 3] = [11, 12]
|
||||
@@ -666,7 +667,7 @@ test "destructuring assignment with context (@) properties and defaults", ->
|
||||
a={}; b={}; c={}; d={}; e={}
|
||||
obj =
|
||||
fn: () ->
|
||||
local = [a, {b, c: null}, d]
|
||||
local = [a, {b, c: undefined}, d]
|
||||
[@a, {b: @b = b, @c = c}, @d, @e = e] = local
|
||||
eq undefined, obj[key] for key in ['a','b','c','d','e']
|
||||
obj.fn()
|
||||
@@ -685,7 +686,7 @@ test "destructuring assignment with defaults single evaluation", ->
|
||||
[a = fn()] = [10]
|
||||
eq 10, a
|
||||
eq 1, callCount
|
||||
{a = fn(), b: c = fn()} = {a: 20, b: null}
|
||||
{a = fn(), b: c = fn()} = {a: 20, b: undefined}
|
||||
eq 20, a
|
||||
eq c, 1
|
||||
eq callCount, 2
|
||||
@@ -4874,6 +4875,13 @@ test "octal escapes", ->
|
||||
/a\\0\\tb\\\\\\07c/
|
||||
\ \ \ \ ^\^^
|
||||
'''
|
||||
assertErrorFormat '''
|
||||
/a\\1\\tb\\\\\\07c/
|
||||
''', '''
|
||||
[stdin]:1:10: error: octal escape sequences are not allowed \\07
|
||||
/a\\1\\tb\\\\\\07c/
|
||||
\ \ \ \ ^\^^
|
||||
'''
|
||||
assertErrorFormat '''
|
||||
///a
|
||||
#{b} \\01///
|
||||
@@ -5771,6 +5779,142 @@ test "new with 'super'", ->
|
||||
^^^^^
|
||||
'''
|
||||
|
||||
test "getter keyword in object", ->
|
||||
assertErrorFormat '''
|
||||
obj =
|
||||
get foo: ->
|
||||
''', '''
|
||||
[stdin]:2:3: error: 'get' cannot be used as a keyword, or as a function call without parentheses
|
||||
get foo: ->
|
||||
^^^
|
||||
'''
|
||||
|
||||
test "setter keyword in object", ->
|
||||
assertErrorFormat '''
|
||||
obj =
|
||||
set foo: ->
|
||||
''', '''
|
||||
[stdin]:2:3: error: 'set' cannot be used as a keyword, or as a function call without parentheses
|
||||
set foo: ->
|
||||
^^^
|
||||
'''
|
||||
|
||||
test "getter keyword in inline implicit object", ->
|
||||
assertErrorFormat 'obj = get foo: ->', '''
|
||||
[stdin]:1:7: error: 'get' cannot be used as a keyword, or as a function call without parentheses
|
||||
obj = get foo: ->
|
||||
^^^
|
||||
'''
|
||||
|
||||
test "setter keyword in inline implicit object", ->
|
||||
assertErrorFormat 'obj = set foo: ->', '''
|
||||
[stdin]:1:7: error: 'set' cannot be used as a keyword, or as a function call without parentheses
|
||||
obj = set foo: ->
|
||||
^^^
|
||||
'''
|
||||
|
||||
test "getter keyword in inline explicit object", ->
|
||||
assertErrorFormat 'obj = {get foo: ->}', '''
|
||||
[stdin]:1:8: error: 'get' cannot be used as a keyword, or as a function call without parentheses
|
||||
obj = {get foo: ->}
|
||||
^^^
|
||||
'''
|
||||
|
||||
test "setter keyword in inline explicit object", ->
|
||||
assertErrorFormat 'obj = {set foo: ->}', '''
|
||||
[stdin]:1:8: error: 'set' cannot be used as a keyword, or as a function call without parentheses
|
||||
obj = {set foo: ->}
|
||||
^^^
|
||||
'''
|
||||
|
||||
test "getter keyword in function", ->
|
||||
assertErrorFormat '''
|
||||
f = ->
|
||||
get foo: ->
|
||||
''', '''
|
||||
[stdin]:2:3: error: 'get' cannot be used as a keyword, or as a function call without parentheses
|
||||
get foo: ->
|
||||
^^^
|
||||
'''
|
||||
|
||||
test "setter keyword in function", ->
|
||||
assertErrorFormat '''
|
||||
f = ->
|
||||
set foo: ->
|
||||
''', '''
|
||||
[stdin]:2:3: error: 'set' cannot be used as a keyword, or as a function call without parentheses
|
||||
set foo: ->
|
||||
^^^
|
||||
'''
|
||||
|
||||
test "getter keyword in inline function", ->
|
||||
assertErrorFormat 'f = -> get foo: ->', '''
|
||||
[stdin]:1:8: error: 'get' cannot be used as a keyword, or as a function call without parentheses
|
||||
f = -> get foo: ->
|
||||
^^^
|
||||
'''
|
||||
|
||||
test "setter keyword in inline function", ->
|
||||
assertErrorFormat 'f = -> set foo: ->', '''
|
||||
[stdin]:1:8: error: 'set' cannot be used as a keyword, or as a function call without parentheses
|
||||
f = -> set foo: ->
|
||||
^^^
|
||||
'''
|
||||
|
||||
test "getter keyword in class", ->
|
||||
assertErrorFormat '''
|
||||
class A
|
||||
get foo: ->
|
||||
''', '''
|
||||
[stdin]:2:3: error: 'get' cannot be used as a keyword, or as a function call without parentheses
|
||||
get foo: ->
|
||||
^^^
|
||||
'''
|
||||
|
||||
test "setter keyword in class", ->
|
||||
assertErrorFormat '''
|
||||
class A
|
||||
set foo: ->
|
||||
''', '''
|
||||
[stdin]:2:3: error: 'set' cannot be used as a keyword, or as a function call without parentheses
|
||||
set foo: ->
|
||||
^^^
|
||||
'''
|
||||
|
||||
test "getter keyword in inline class", ->
|
||||
assertErrorFormat 'class A then get foo: ->', '''
|
||||
[stdin]:1:14: error: 'get' cannot be used as a keyword, or as a function call without parentheses
|
||||
class A then get foo: ->
|
||||
^^^
|
||||
'''
|
||||
|
||||
test "setter keyword in inline class", ->
|
||||
assertErrorFormat 'class A then set foo: ->', '''
|
||||
[stdin]:1:14: error: 'set' cannot be used as a keyword, or as a function call without parentheses
|
||||
class A then set foo: ->
|
||||
^^^
|
||||
'''
|
||||
|
||||
test "getter keyword before static method", ->
|
||||
assertErrorFormat '''
|
||||
class A
|
||||
get @foo = ->
|
||||
''', '''
|
||||
[stdin]:2:3: error: 'get' cannot be used as a keyword, or as a function call without parentheses
|
||||
get @foo = ->
|
||||
^^^
|
||||
'''
|
||||
|
||||
test "setter keyword before static method", ->
|
||||
assertErrorFormat '''
|
||||
class A
|
||||
set @foo = ->
|
||||
''', '''
|
||||
[stdin]:2:3: error: 'set' cannot be used as a keyword, or as a function call without parentheses
|
||||
set @foo = ->
|
||||
^^^
|
||||
'''
|
||||
|
||||
</script>
|
||||
<script type="text/x-coffeescript" class="test" id="eval">
|
||||
if vm = require? 'vm'
|
||||
@@ -6241,6 +6385,23 @@ test "tabs and spaces cannot be mixed for indentation", ->
|
||||
catch e
|
||||
eq 'mixed indentation', e.message
|
||||
|
||||
test "#4487: Handle unusual outdentation", ->
|
||||
a =
|
||||
switch 1
|
||||
when 2
|
||||
no
|
||||
when 3 then no
|
||||
when 1 then yes
|
||||
eq yes, a
|
||||
|
||||
b = do ->
|
||||
if no
|
||||
if no
|
||||
1
|
||||
2
|
||||
3
|
||||
eq b, undefined
|
||||
|
||||
</script>
|
||||
<script type="text/x-coffeescript" class="test" id="function_invocation">
|
||||
# Function Invocation
|
||||
@@ -6920,7 +7081,7 @@ test "Non-callable literals shouldn't compile", ->
|
||||
cantCompile '[1..10][2..9] 2'
|
||||
cantCompile '[1..10][2..9](2)'
|
||||
|
||||
test 'implicit invocation with implicit object literal', ->
|
||||
test "implicit invocation with implicit object literal", ->
|
||||
f = (obj) -> eq 1, obj.a
|
||||
|
||||
f
|
||||
@@ -6952,6 +7113,48 @@ test 'implicit invocation with implicit object literal', ->
|
||||
"#{a}": 1
|
||||
eq 2, obj.a
|
||||
|
||||
test "get and set can be used as function names when not ambiguous with `get`/`set` keywords", ->
|
||||
get = (val) -> val
|
||||
set = (val) -> val
|
||||
eq 2, get(2)
|
||||
eq 3, set(3)
|
||||
eq 'a', get('a')
|
||||
eq 'b', set('b')
|
||||
|
||||
get = ({val}) -> val
|
||||
set = ({val}) -> val
|
||||
eq 4, get({val: 4})
|
||||
eq 5, set({val: 5})
|
||||
eq 'c', get({val: 'c'})
|
||||
eq 'd', set({val: 'd'})
|
||||
|
||||
test "get and set can be used as variable and property names", ->
|
||||
get = 2
|
||||
set = 3
|
||||
eq 2, get
|
||||
eq 3, set
|
||||
|
||||
{get} = {get: 4}
|
||||
{set} = {set: 5}
|
||||
eq 4, get
|
||||
eq 5, set
|
||||
|
||||
test "get and set can be used as class method names", ->
|
||||
class A
|
||||
get: -> 2
|
||||
set: -> 3
|
||||
|
||||
a = new A()
|
||||
eq 2, a.get()
|
||||
eq 3, a.set()
|
||||
|
||||
class B
|
||||
@get = -> 4
|
||||
@set = -> 5
|
||||
|
||||
eq 4, B.get()
|
||||
eq 5, B.set()
|
||||
|
||||
</script>
|
||||
<script type="text/x-coffeescript" class="test" id="functions">
|
||||
# Function Literals
|
||||
@@ -7135,7 +7338,7 @@ test "destructuring in function definition", ->
|
||||
{url, async, beforeSend, cache, method, data}
|
||||
|
||||
fn = ->
|
||||
deepEqual ajax('/home', beforeSend: fn, cache: null, method: 'post'), {
|
||||
deepEqual ajax('/home', beforeSend: fn, method: 'post'), {
|
||||
url: '/home', async: true, beforeSend: fn, cache: true, method: 'post', data: {}
|
||||
}
|
||||
|
||||
@@ -7309,6 +7512,16 @@ test "#4406 Destructured parameter default evaluation order with generator funct
|
||||
foo = ({ a = next() }, b = next()) -> [ a, b ]
|
||||
arrayEq foo({}), [1, 2]
|
||||
|
||||
test "Destructured parameter with default value, that itself has a default value", ->
|
||||
# Adapted from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment
|
||||
draw = ({size = 'big', coords = {x: 0, y: 0}, radius = 25} = {}) -> "#{size}-#{coords.x}-#{coords.y}-#{radius}"
|
||||
output = draw
|
||||
coords:
|
||||
x: 18
|
||||
y: 30
|
||||
radius: 30
|
||||
eq output, 'big-18-30-30'
|
||||
|
||||
</script>
|
||||
<script type="text/x-coffeescript" class="test" id="generators">
|
||||
# Generators
|
||||
@@ -8055,22 +8268,21 @@ test "escaped JavaScript blocks speed round", ->
|
||||
|
||||
</script>
|
||||
<script type="text/x-literate-coffeescript" class="test" id="literate">
|
||||
Literate CoffeeScript Test
|
||||
--------------------------
|
||||
# Literate CoffeeScript Test
|
||||
|
||||
comment comment
|
||||
|
||||
test "basic literate CoffeeScript parsing", ->
|
||||
ok yes
|
||||
|
||||
|
||||
now with a...
|
||||
|
||||
|
||||
test "broken up indentation", ->
|
||||
|
||||
|
||||
... broken up ...
|
||||
|
||||
do ->
|
||||
|
||||
|
||||
... nested block.
|
||||
|
||||
ok yes
|
||||
@@ -8082,36 +8294,36 @@ Code must be separated from text by a blank line.
|
||||
The next line is part of the text and will not be executed.
|
||||
fail()
|
||||
|
||||
ok yes
|
||||
|
||||
ok yes
|
||||
|
||||
Code in `backticks is not parsed` and...
|
||||
|
||||
test "comments in indented blocks work", ->
|
||||
do ->
|
||||
do ->
|
||||
# Regular comment.
|
||||
|
||||
|
||||
###
|
||||
Block comment.
|
||||
###
|
||||
|
||||
|
||||
ok yes
|
||||
|
||||
Regular [Markdown](http://example.com/markdown) features, like links
|
||||
|
||||
Regular [Markdown](http://example.com/markdown) features, like links
|
||||
and unordered lists, are fine:
|
||||
|
||||
* I
|
||||
|
||||
* I
|
||||
|
||||
* Am
|
||||
|
||||
|
||||
* A
|
||||
|
||||
|
||||
* List
|
||||
|
||||
Tabs work too:
|
||||
|
||||
test "tabbed code", ->
|
||||
ok yes
|
||||
test "tabbed code", ->
|
||||
ok yes
|
||||
|
||||
---
|
||||
|
||||
@@ -8120,11 +8332,12 @@ Tabs work too:
|
||||
|
||||
<p>
|
||||
|
||||
executed = true # should not execute, this is just HTML para, not code!
|
||||
if true
|
||||
executed = true # should not execute, this is just HTML para, not code!
|
||||
|
||||
</p>
|
||||
|
||||
test "should ignore indented sections inside HTML", ->
|
||||
test "should ignore code blocks inside HTML", ->
|
||||
eq executed, false
|
||||
|
||||
---
|
||||
@@ -8176,24 +8389,8 @@ Tabs work too:
|
||||
|
||||
---
|
||||
|
||||
This next one probably passes because a string is inoffensive in compiled js, also, can't get `marked` to parse it correctly, and not sure if empty line is permitted between title and reference
|
||||
|
||||
This is [an example][id] reference-style link.
|
||||
[id]: http://example.com/
|
||||
|
||||
"Optional Title Here"
|
||||
|
||||
---
|
||||
|
||||
executed = no
|
||||
|
||||
1986. What a great season.
|
||||
executed = yes
|
||||
|
||||
and test...
|
||||
|
||||
test "should recognise indented code blocks in lists", ->
|
||||
ok executed
|
||||
[id]: http://example.com/ "Optional Title Here"
|
||||
|
||||
---
|
||||
|
||||
@@ -8205,7 +8402,7 @@ and test...
|
||||
|
||||
and test...
|
||||
|
||||
test "should recognise indented code blocks in lists with empty line as separator", ->
|
||||
test "should recognize indented code blocks in lists with empty line as separator", ->
|
||||
ok executed
|
||||
|
||||
---
|
||||
@@ -8220,6 +8417,174 @@ and test...
|
||||
test "should ignore indented code in escaped list like number", ->
|
||||
eq executed, no
|
||||
|
||||
one last test!
|
||||
|
||||
test "block quotes should render correctly", ->
|
||||
quote = '''
|
||||
foo
|
||||
and bar!
|
||||
'''
|
||||
eq quote, 'foo\n and bar!'
|
||||
|
||||
</script>
|
||||
<script type="text/x-literate-coffeescript" class="test" id="literate_tabbed">
|
||||
# Tabbed Literate CoffeeScript Test
|
||||
|
||||
comment comment
|
||||
|
||||
test "basic literate CoffeeScript parsing", ->
|
||||
ok yes
|
||||
|
||||
now with a...
|
||||
|
||||
test "broken up indentation", ->
|
||||
|
||||
... broken up ...
|
||||
|
||||
do ->
|
||||
|
||||
... nested block.
|
||||
|
||||
ok yes
|
||||
|
||||
Code must be separated from text by a blank line.
|
||||
|
||||
test "code blocks must be preceded by a blank line", ->
|
||||
|
||||
The next line is part of the text and will not be executed.
|
||||
fail()
|
||||
|
||||
ok yes
|
||||
|
||||
Code in `backticks is not parsed` and...
|
||||
|
||||
test "comments in indented blocks work", ->
|
||||
do ->
|
||||
do ->
|
||||
# Regular comment.
|
||||
|
||||
###
|
||||
Block comment.
|
||||
###
|
||||
|
||||
ok yes
|
||||
|
||||
Regular [Markdown](http://example.com/markdown) features, like links
|
||||
and unordered lists, are fine:
|
||||
|
||||
* I
|
||||
|
||||
* Am
|
||||
|
||||
* A
|
||||
|
||||
* List
|
||||
|
||||
Spaces work too:
|
||||
|
||||
test "spaced code", ->
|
||||
ok yes
|
||||
|
||||
---
|
||||
|
||||
# keep track of whether code blocks are executed or not
|
||||
executed = false
|
||||
|
||||
<p>
|
||||
|
||||
if true
|
||||
executed = true # should not execute, this is just HTML para, not code!
|
||||
|
||||
</p>
|
||||
|
||||
test "should ignore code blocks inside HTML", ->
|
||||
eq executed, false
|
||||
|
||||
---
|
||||
|
||||
* A list item with a code block:
|
||||
|
||||
test "basic literate CoffeeScript parsing", ->
|
||||
ok yes
|
||||
|
||||
---
|
||||
|
||||
* Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
|
||||
Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi,
|
||||
viverra nec, fringilla in, laoreet vitae, risus.
|
||||
|
||||
* Donec sit amet nisl. Aliquam semper ipsum sit amet velit.
|
||||
Suspendisse id sem consectetuer libero luctus adipiscing.
|
||||
|
||||
---
|
||||
|
||||
1. This is a list item with two paragraphs. Lorem ipsum dolor
|
||||
sit amet, consectetuer adipiscing elit. Aliquam hendrerit
|
||||
mi posuere lectus.
|
||||
|
||||
Vestibulum enim wisi, viverra nec, fringilla in, laoreet
|
||||
vitae, risus. Donec sit amet nisl. Aliquam semper ipsum
|
||||
sit amet velit.
|
||||
|
||||
2. Suspendisse id sem consectetuer libero luctus adipiscing.
|
||||
|
||||
---
|
||||
|
||||
1. This is a list item with two paragraphs. Lorem ipsum dolor
|
||||
sit amet, consectetuer adipiscing elit. Aliquam hendrerit
|
||||
mi posuere lectus.
|
||||
|
||||
Vestibulum enim wisi, viverra nec, fringilla in, laoreet
|
||||
vitae, risus. Donec sit amet nisl. Aliquam semper ipsum
|
||||
sit amet velit.
|
||||
|
||||
2. Suspendisse id sem consectetuer libero luctus adipiscing.
|
||||
|
||||
---
|
||||
|
||||
* A list item with a blockquote:
|
||||
|
||||
> This is a blockquote
|
||||
> inside a list item.
|
||||
|
||||
---
|
||||
|
||||
This is [an example][id] reference-style link.
|
||||
[id]: http://example.com/ "Optional Title Here"
|
||||
|
||||
---
|
||||
|
||||
executed = no
|
||||
|
||||
1986. What a great season.
|
||||
|
||||
executed = yes
|
||||
|
||||
and test...
|
||||
|
||||
test "should recognize indented code blocks in lists with empty line as separator", ->
|
||||
ok executed
|
||||
|
||||
---
|
||||
|
||||
executed = no
|
||||
|
||||
1986\. What a great season.
|
||||
executed = yes
|
||||
|
||||
and test...
|
||||
|
||||
test "should ignore indented code in escaped list like number", ->
|
||||
eq executed, no
|
||||
|
||||
one last test!
|
||||
|
||||
test "block quotes should render correctly", ->
|
||||
quote = '''
|
||||
foo
|
||||
and bar!
|
||||
'''
|
||||
eq quote, 'foo\n\t\tand bar!'
|
||||
|
||||
</script>
|
||||
<script type="text/x-coffeescript" class="test" id="location">
|
||||
@@ -9561,7 +9926,7 @@ test "export an aliased member named default", ->
|
||||
};"""
|
||||
eq toJS(input), output
|
||||
|
||||
test "export an imported member named default", ->
|
||||
test "import an imported member named default", ->
|
||||
input = "import { default } from 'lib'"
|
||||
output = """
|
||||
import {
|
||||
@@ -9569,7 +9934,7 @@ test "export an imported member named default", ->
|
||||
} from 'lib';"""
|
||||
eq toJS(input), output
|
||||
|
||||
test "export an imported aliased member named default", ->
|
||||
test "import an imported aliased member named default", ->
|
||||
input = "import { default as def } from 'lib'"
|
||||
output = """
|
||||
import {
|
||||
@@ -9577,6 +9942,22 @@ test "export an imported aliased member named default", ->
|
||||
} from 'lib';"""
|
||||
eq toJS(input), output
|
||||
|
||||
test "export an imported member named default", ->
|
||||
input = "export { default } from 'lib'"
|
||||
output = """
|
||||
export {
|
||||
default
|
||||
} from 'lib';"""
|
||||
eq toJS(input), output
|
||||
|
||||
test "export an imported aliased member named default", ->
|
||||
input = "export { default as def } from 'lib'"
|
||||
output = """
|
||||
export {
|
||||
default as def
|
||||
} from 'lib';"""
|
||||
eq toJS(input), output
|
||||
|
||||
test "#4394: export shouldn't prevent variable declarations", ->
|
||||
input = """
|
||||
x = 1
|
||||
@@ -9593,6 +9974,121 @@ test "#4394: export shouldn't prevent variable declarations", ->
|
||||
"""
|
||||
eq toJS(input), output
|
||||
|
||||
test "#4451: `default` in an export statement is only treated as a keyword when it follows `export` or `as`", ->
|
||||
input = "export default { default: 1 }"
|
||||
output = """
|
||||
export default {
|
||||
"default": 1
|
||||
};
|
||||
"""
|
||||
eq toJS(input), output
|
||||
|
||||
test "#4491: import- and export-specific lexing should stop after import/export statement", ->
|
||||
input = """
|
||||
import {
|
||||
foo,
|
||||
bar as baz
|
||||
} from 'lib'
|
||||
|
||||
foo as
|
||||
3 * as 4
|
||||
from 'foo'
|
||||
"""
|
||||
output = """
|
||||
import {
|
||||
foo,
|
||||
bar as baz
|
||||
} from 'lib';
|
||||
|
||||
foo(as);
|
||||
|
||||
3 * as(4);
|
||||
|
||||
from('foo');
|
||||
"""
|
||||
eq toJS(input), output
|
||||
|
||||
input = """
|
||||
import { foo, bar as baz } from 'lib'
|
||||
|
||||
foo as
|
||||
3 * as 4
|
||||
from 'foo'
|
||||
"""
|
||||
output = """
|
||||
import {
|
||||
foo,
|
||||
bar as baz
|
||||
} from 'lib';
|
||||
|
||||
foo(as);
|
||||
|
||||
3 * as(4);
|
||||
|
||||
from('foo');
|
||||
"""
|
||||
eq toJS(input), output
|
||||
|
||||
input = """
|
||||
import * as lib from 'lib'
|
||||
|
||||
foo as
|
||||
3 * as 4
|
||||
from 'foo'
|
||||
"""
|
||||
output = """
|
||||
import * as lib from 'lib';
|
||||
|
||||
foo(as);
|
||||
|
||||
3 * as(4);
|
||||
|
||||
from('foo');
|
||||
"""
|
||||
eq toJS(input), output
|
||||
|
||||
input = """
|
||||
export {
|
||||
foo,
|
||||
bar
|
||||
}
|
||||
|
||||
foo as
|
||||
3 * as 4
|
||||
from 'foo'
|
||||
"""
|
||||
output = """
|
||||
export {
|
||||
foo,
|
||||
bar
|
||||
};
|
||||
|
||||
foo(as);
|
||||
|
||||
3 * as(4);
|
||||
|
||||
from('foo');
|
||||
"""
|
||||
eq toJS(input), output
|
||||
|
||||
input = """
|
||||
export * from 'lib'
|
||||
|
||||
foo as
|
||||
3 * as 4
|
||||
from 'foo'
|
||||
"""
|
||||
output = """
|
||||
export * from 'lib';
|
||||
|
||||
foo(as);
|
||||
|
||||
3 * as(4);
|
||||
|
||||
from('foo');
|
||||
"""
|
||||
eq toJS(input), output
|
||||
|
||||
</script>
|
||||
<script type="text/x-coffeescript" class="test" id="numbers">
|
||||
# Number Literals
|
||||
@@ -11861,7 +12357,7 @@ test "SourceMap tests", ->
|
||||
# Strict Early Errors
|
||||
# -------------------
|
||||
|
||||
# The following are prohibited under ES5's `strict` mode
|
||||
# The following are prohibited under ES5’s `strict` mode
|
||||
# * `Octal Integer Literals`
|
||||
# * `Octal Escape Sequences`
|
||||
# * duplicate property definitions in `Object Literal`s
|
||||
|
||||
18
documentation/examples/async.coffee
Normal file
18
documentation/examples/async.coffee
Normal file
@@ -0,0 +1,18 @@
|
||||
# Your browser must support async/await and speech synthesis
|
||||
# to run this example.
|
||||
|
||||
sleep = (ms) ->
|
||||
new Promise (resolve) ->
|
||||
window.setTimeout resolve, ms
|
||||
|
||||
say = (text) ->
|
||||
window.speechSynthesis.cancel()
|
||||
window.speechSynthesis.speak new SpeechSynthesisUtterance text
|
||||
|
||||
countdown = (seconds) ->
|
||||
for i in [seconds..1]
|
||||
say i
|
||||
await sleep 1000 # wait one second
|
||||
say "Blastoff!"
|
||||
|
||||
countdown 3
|
||||
@@ -0,0 +1,2 @@
|
||||
self = this
|
||||
f = -> yield self
|
||||
@@ -0,0 +1,3 @@
|
||||
{a = 1} = {a: null}
|
||||
|
||||
a # Equals 1 in CoffeeScript 1.x, null in CoffeeScript 2
|
||||
@@ -0,0 +1,3 @@
|
||||
f = (a = 1) -> a
|
||||
|
||||
f(null) # Returns 1 in CoffeeScript 1.x, null in CoffeeScript 2
|
||||
@@ -0,0 +1,4 @@
|
||||
A = ->
|
||||
B = ->
|
||||
B extends A
|
||||
B.prototype.foo = -> A::foo.apply this, arguments
|
||||
@@ -0,0 +1,3 @@
|
||||
class A
|
||||
class B extends A
|
||||
foo: -> super arguments...
|
||||
@@ -0,0 +1,2 @@
|
||||
class B extends A
|
||||
foo: -> super arguments...
|
||||
@@ -0,0 +1,2 @@
|
||||
class B extends A
|
||||
foo: -> super()
|
||||
1
documentation/examples/comment.coffee
Normal file
1
documentation/examples/comment.coffee
Normal file
@@ -0,0 +1 @@
|
||||
code = 2 * 617 # The code is 1234
|
||||
9
documentation/examples/get_set.coffee
Normal file
9
documentation/examples/get_set.coffee
Normal file
@@ -0,0 +1,9 @@
|
||||
screen =
|
||||
width: 1200
|
||||
ratio: 16/9
|
||||
|
||||
Object.defineProperty screen, 'height',
|
||||
get: ->
|
||||
this.width / this.ratio
|
||||
set: (val) ->
|
||||
this.width = val / this.ratio
|
||||
@@ -1,5 +1,5 @@
|
||||
import 'local-file.coffee'
|
||||
import 'coffee-script'
|
||||
import 'coffeescript'
|
||||
|
||||
import _ from 'underscore'
|
||||
import * as underscore from 'underscore'
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
$('.account').attr class: 'active'
|
||||
$('.account').prop class: 'active'
|
||||
|
||||
log object.class
|
||||
|
||||
9
documentation/examples/static.coffee
Normal file
9
documentation/examples/static.coffee
Normal file
@@ -0,0 +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 ', '
|
||||
1
documentation/images/link.svg
Normal file
1
documentation/images/link.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg aria-hidden="true" version="1.1" viewBox="0 0 16 16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>
|
||||
|
After Width: | Height: | Size: 436 B |
16
documentation/sections/annotated_source.md
Normal file
16
documentation/sections/annotated_source.md
Normal file
@@ -0,0 +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:
|
||||
|
||||
- [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)
|
||||
142
documentation/sections/breaking_changes.md
Normal file
142
documentation/sections/breaking_changes.md
Normal file
@@ -0,0 +1,142 @@
|
||||
## Breaking Changes From CoffeeScript 1.x to 2
|
||||
|
||||
CoffeeScript 2 aims to output as much idiomatic ES2015+ syntax as possible with as few breaking changes from CoffeeScript 1.x as possible. Some breaking changes, unfortunately, were unavoidable.
|
||||
|
||||
<section id="breaking-changes-default-values">
|
||||
|
||||
### Default values for function parameters and destructured elements
|
||||
|
||||
Per the [ES2015 spec regarding function default parameters](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Default_parameters) and [destructuring default values](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment#Default_values), default values are only applied when a value is missing or `undefined`. In CoffeeScript 1.x, the default value would be applied in those cases but also if the value was `null`.
|
||||
|
||||
```
|
||||
codeFor('breaking_change_function_parameter_default_values', 'f(null)')
|
||||
```
|
||||
|
||||
```
|
||||
codeFor('breaking_change_destructuring_default_values', 'a')
|
||||
```
|
||||
|
||||
</section>
|
||||
<section id="breaking-changes-bound-generator-functions">
|
||||
|
||||
### Bound generator functions
|
||||
|
||||
Bound generator functions, a.k.a. generator arrow functions, [aren’t allowed in ECMAScript](http://stackoverflow.com/questions/27661306/can-i-use-es6s-arrow-function-syntax-with-generators-arrow-notation). You can write `function*` or `=>`, but not both. Therefore, CoffeeScript code like this:
|
||||
|
||||
```coffee
|
||||
f = => yield this
|
||||
# Throws a compiler error
|
||||
```
|
||||
|
||||
Needs to be rewritten the old-fashioned way:
|
||||
|
||||
```
|
||||
codeFor('breaking_change_bound_generator_function')
|
||||
```
|
||||
|
||||
</section>
|
||||
<section id="breaking-changes-classes">
|
||||
|
||||
### Classes are compiled to ES2015 classes
|
||||
|
||||
ES2015 classes and their methods have some restrictions beyond those on regular functions.
|
||||
|
||||
Class constructors can’t be invoked without `new`:
|
||||
|
||||
```coffee
|
||||
(class)()
|
||||
# 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
|
||||
```
|
||||
|
||||
Class methods can’t be used with `new` (uncommon):
|
||||
|
||||
```coffee
|
||||
class Namespace
|
||||
@Klass = ->
|
||||
new Namespace.Klass
|
||||
# Throws a TypeError at runtime
|
||||
```
|
||||
|
||||
</section>
|
||||
<section id="breaking-changes-bare-super">
|
||||
|
||||
### Bare `super`
|
||||
|
||||
Due to a syntax clash with `super` with accessors, bare `super` no longer compiles to a super call forwarding all arguments.
|
||||
|
||||
```coffee
|
||||
class B extends A
|
||||
foo: -> super
|
||||
# Throws a compiler error
|
||||
```
|
||||
|
||||
Arguments can be forwarded explicitly using splats:
|
||||
|
||||
```
|
||||
codeFor('breaking_change_super_with_arguments')
|
||||
```
|
||||
|
||||
Or if you know that the parent function doesn’t require arguments, just call `super()`:
|
||||
|
||||
```
|
||||
codeFor('breaking_change_super_without_arguments')
|
||||
```
|
||||
|
||||
</section>
|
||||
<section id="breaking-changes-super-in-non-class-methods">
|
||||
|
||||
### `super` in non-class methods
|
||||
|
||||
In CoffeeScript 1.x it is possible to use `super` in more than just class methods, such as in manually prototype-assigned functions:
|
||||
|
||||
```coffee
|
||||
A = ->
|
||||
B = ->
|
||||
B extends A
|
||||
B.prototype.foo = -> super arguments...
|
||||
# Throws a compiler error
|
||||
```
|
||||
|
||||
Due to the switch to ES2015 `super`, this is no longer supported. The above case could be refactored to:
|
||||
|
||||
```
|
||||
codeFor('breaking_change_super_in_non-class_methods_refactor_with_apply')
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```
|
||||
codeFor('breaking_change_super_in_non-class_methods_refactor_with_class')
|
||||
```
|
||||
|
||||
</section>
|
||||
<section id="breaking-changes-dynamic-class-keys-exclude-executable-class-scope">
|
||||
|
||||
### Dynamic class keys exclude executable class scope
|
||||
|
||||
Due to the hoisting required to compile to ES2015 classes, dynamic keys in class methods can’t use values from the executable class body unless the methods are assigned in prototype style.
|
||||
|
||||
```coffee
|
||||
class A
|
||||
name = 'method'
|
||||
"#{name}": -> # This method will be named 'undefined'
|
||||
@::[name] = -> # This will work; assigns to `A.prototype.method`
|
||||
```
|
||||
|
||||
</section>
|
||||
|
||||
<section id="breaking-changes-literate-coffeescript">
|
||||
|
||||
### Literate CoffeeScript now parsed by a Markdown library
|
||||
|
||||
The CoffeeScript 1.x implementation of Literate CoffeeScript relies on indentation to tell apart code blocks from documentation, and as such it can get confused by Markdown features that also use indentation like lists. In CoffeeScript 2 this has been refactored to now use [Markdown-It](https://github.com/markdown-it/markdown-it) to detect Markdown sections rather than just looking at indentation. The only significant difference is that now if you want to include a code block in documentation, as opposed to the compiler recognizing that code block as code, it must have at least one line fully unindented. Wrapping it in HTML tags is no longer sufficient.
|
||||
|
||||
Code blocks interspersed with lists may need to be refactored. In general, code blocks should be separated by a blank line between documentation, and should maintain a consistent indentation level—so an indentation of one tab (or whatever you consider to be a tab stop, like 2 spaces or 4 spaces) should be treated as your code’s “left margin,” with all code in the file relative to that column.
|
||||
@@ -8,4 +8,4 @@ Task definitions are written in CoffeeScript, so you can put arbitrary code in y
|
||||
codeFor('cake_tasks')
|
||||
```
|
||||
|
||||
If you need to invoke one task before another — for example, running `build` before `test`, you can use the `invoke` function: `invoke 'build'`. Cake tasks are a minimal way to expose your CoffeeScript functions to the command line, so [don’t expect any fanciness built-in](v<%= majorVersion %>/annotated-source/cake.html). If you need dependencies, or async callbacks, it’s best to put them in your code itself — not the cake task.
|
||||
If you need to invoke one task before another — for example, running `build` before `test`, you can use the `invoke` function: `invoke 'build'`. Cake tasks are a minimal way to expose your CoffeeScript functions to the command line, so [don’t expect any fanciness built-in](/v<%= majorVersion %>/annotated-source/cake.html). If you need dependencies, or async callbacks, it’s best to put them in your code itself — not the cake task.
|
||||
|
||||
@@ -1,5 +1,15 @@
|
||||
## Change Log
|
||||
|
||||
```
|
||||
releaseHeader('2017-04-14', '2.0.0-beta1', '2.0.0-alpha1')
|
||||
```
|
||||
|
||||
* Initial beta release of CoffeeScript 2. No further breaking changes are anticipated.
|
||||
* Destructured objects and arrays now output using ES2015+ syntax whenever possible.
|
||||
* Literate CoffeeScript now has much better support for parsing Markdown, thanks to using [Markdown-It](https://github.com/markdown-it/markdown-it) to detect Markdown sections rather than just looking at indentation.
|
||||
* Calling a function named `get` or `set` now requires parentheses, to disambiguate from the `get` or `set` keywords (which are [disallowed](#unsupported-get-set)).
|
||||
* The compiler now requires Node 7.6+, the first version of Node to support asynchronous functions without requiring a flag.
|
||||
|
||||
```
|
||||
releaseHeader('2017-04-10', '1.12.5', '1.12.4')
|
||||
```
|
||||
@@ -7,6 +17,24 @@ releaseHeader('2017-04-10', '1.12.5', '1.12.4')
|
||||
* Better handling of `default`, `from`, `as` and `*` within `import` and `export` statements. You can now import or export a member named `default` and the compiler won’t interpret it as the `default` keyword.
|
||||
* Fixed a bug where invalid octal escape sequences weren’t throwing errors in the compiler.
|
||||
|
||||
|
||||
```
|
||||
releaseHeader('2017-02-21', '2.0.0-alpha1', '1.12.4')
|
||||
```
|
||||
|
||||
* Initial alpha release of CoffeeScript 2. The CoffeeScript compiler now outputs ES2015+ syntax whenever possible. See [breaking changes](#breaking-changes).
|
||||
* Classes are output using ES2015 `class` and `extends` keywords.
|
||||
* Added support for `async`/`await`.
|
||||
* Bound (arrow) functions now output as `=>` functions.
|
||||
* Function parameters with default values now use ES2015 default values syntax.
|
||||
* Splat function parameters now use ES2015 spread syntax.
|
||||
* Computed properties now use ES2015 syntax.
|
||||
* Interpolated strings (template literals) now use ES2015 backtick syntax.
|
||||
* Improved support for recognizing Markdown in Literate CoffeeScript files.
|
||||
* Mixing tabs and spaces in indentation is now disallowed.
|
||||
* Browser compiler is now minified using the Google Closure Compiler (JavaScript version).
|
||||
* Node 7+ required for CoffeeScript 2.
|
||||
|
||||
```
|
||||
releaseHeader('2017-02-18', '1.12.4', '1.12.3')
|
||||
```
|
||||
@@ -31,7 +59,7 @@ releaseHeader('2016-12-16', '1.12.2', '1.12.1')
|
||||
* The browser compiler can once again be built unminified via `MINIFY=false cake build:browser`.
|
||||
* The error-prone patched version of `Error.prepareStackTrace` has been removed.
|
||||
* Command completion in the REPL (pressing tab to get suggestions) has been fixed for Node 6.9.1+.
|
||||
* The [browser-based tests](v<%= majorVersion %>/test.html) now include all the tests as the Node-based version.
|
||||
* The [browser-based tests](/v<%= majorVersion %>/test.html) now include all the tests as the Node-based version.
|
||||
|
||||
```
|
||||
releaseHeader('2016-12-07', '1.12.1', '1.12.0')
|
||||
@@ -48,7 +76,7 @@ releaseHeader('2016-12-04', '1.12.0', '1.11.1')
|
||||
* CoffeeScript now provides a [`for…from`](#generator-iteration) syntax for outputting ES2015 [`for…of`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of). (Sorry they couldn’t match, but we came up with `for…of` first for something else.) This allows iterating over generators or any other iterable object. Note that using `for…from` in your code makes you responsible for ensuring that either your runtime supports `for…of` or that you transpile the output JavaScript further to a version your target runtime(s) support.
|
||||
* Triple backticks (`` `````) 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.
|
||||
* Within single-backtick embedded JavaScript, backticks can now be escaped via `` \```.
|
||||
* The browser tests now run in the browser again, and are accessible [here](v<%= majorVersion %>/test.html) if you would like to test your browser.
|
||||
* The browser tests now run in the browser again, and are accessible [here](/v<%= majorVersion %>/test.html) if you would like to test your browser.
|
||||
* CoffeeScript-only keywords in ES2015 `import`s and `export`s are now ignored.
|
||||
* The compiler now throws an error on trying to export an anonymous class.
|
||||
* Bugfixes related to tokens and location data, for better source maps and improved compatibility with downstream tools.
|
||||
@@ -162,7 +190,7 @@ releaseHeader('2014-08-26', '1.8.0', '1.7.1')
|
||||
* Fixed a slight formatting error in CoffeeScript’s source map-patched stack traces.
|
||||
* The `%%` operator now coerces its right operand only once.
|
||||
* It is now possible to require CoffeeScript files from Cakefiles without having to register the compiler first.
|
||||
* The CoffeeScript REPL is now exported and can be required using `require 'coffee-script/repl'`.
|
||||
* The CoffeeScript REPL is now exported and can be required using `require 'coffeescript/repl'`.
|
||||
* Fixes for the REPL in Node 0.11.
|
||||
|
||||
```
|
||||
@@ -175,7 +203,7 @@ releaseHeader('2014-01-29', '1.7.1', '1.7.0')
|
||||
releaseHeader('2014-01-28', '1.7.0', '1.6.3')
|
||||
```
|
||||
|
||||
* When requiring CoffeeScript files in Node you must now explicitly register the compiler. This can be done with `require 'coffee-script/register'` or `CoffeeScript.register()`. Also for configuration such as Mocha’s, use **coffee-script/register**.
|
||||
* When requiring CoffeeScript files in Node you must now explicitly register the compiler. This can be done with `require 'coffeescript/register'` or `CoffeeScript.register()`. Also for configuration such as Mocha’s, use **coffeescript/register**.
|
||||
* Improved error messages, source maps and stack traces. Source maps now use the updated `//#` syntax.
|
||||
* Leading `.` now closes all open calls, allowing for simpler chaining syntax.
|
||||
|
||||
@@ -275,7 +303,7 @@ releaseHeader('2011-11-08', '1.1.3', '1.1.2')
|
||||
* Ahh, whitespace. CoffeeScript’s compiled JS now tries to space things out and keep it readable, as you can see in the examples on this page.
|
||||
* You can now call `super` in class level methods in class bodies, and bound class methods now preserve their correct context.
|
||||
* JavaScript has always supported octal numbers `010 is 8`, and hexadecimal numbers `0xf is 15`, but CoffeeScript now also supports binary numbers: `0b10 is 2`.
|
||||
* The CoffeeScript module has been nested under a subdirectory to make it easier to `require` individual components separately, without having to use **npm**. For example, after adding the CoffeeScript folder to your path: `require('coffee-script/lexer')`
|
||||
* The CoffeeScript module has been nested under a subdirectory to make it easier to `require` individual components separately, without having to use **npm**. For example, after adding the CoffeeScript folder to your path: `require('coffeescript/lexer')`
|
||||
* There’s a new “link” feature in Try CoffeeScript on this webpage. Use it to get a shareable permalink for your example script.
|
||||
* The `coffee --watch` feature now only works on Node.js 0.6.0 and higher, but now also works properly on Windows.
|
||||
* Lots of small bug fixes from **[@michaelficarra](https://github.com/michaelficarra)**, **[@geraldalewis](https://github.com/geraldalewis)**, **[@satyr](https://github.com/satyr)**, and **[@trevorburnham](https://github.com/trevorburnham)**.
|
||||
@@ -394,7 +422,7 @@ Trailing commas are now allowed, a-la Python. Static properties may be assigned
|
||||
releaseHeader('2010-03-23', '0.5.6', '0.5.5')
|
||||
```
|
||||
|
||||
Interpolation can now be used within regular expressions and heredocs, as well as strings. Added the `<-` bind operator. Allowing assignment to half-expressions instead of special `||=`-style operators. The arguments object is no longer automatically converted into an array. After requiring `coffee-script`, Node.js can now directly load `.coffee` files, thanks to **registerExtension**. Multiple splats can now be used in function calls, arrays, and pattern matching.
|
||||
Interpolation can now be used within regular expressions and heredocs, as well as strings. Added the `<-` bind operator. Allowing assignment to half-expressions instead of special `||=`-style operators. The arguments object is no longer automatically converted into an array. After requiring `coffeescript`, Node.js can now directly load `.coffee` files, thanks to **registerExtension**. Multiple splats can now be used in function calls, arrays, and pattern matching.
|
||||
|
||||
```
|
||||
releaseHeader('2010-03-08', '0.5.5', '0.5.4')
|
||||
@@ -419,7 +447,7 @@ releaseHeader('2010-02-25', '0.5.2', '0.5.1')
|
||||
```
|
||||
|
||||
Added a compressed version of the compiler for inclusion in web pages as
|
||||
`v<%= majorVersion %>/browser-compiler/coffee-script.js`. It’ll automatically run any script tags with type `text/coffeescript` for you. Added a `--stdio` option to the `coffee` command, for piped-in compiles.
|
||||
`v<%= majorVersion %>/browser-compiler/coffeescript.js`. It’ll automatically run any script tags with type `text/coffeescript` for you. Added a `--stdio` option to the `coffee` command, for piped-in compiles.
|
||||
|
||||
```
|
||||
releaseHeader('2010-02-24', '0.5.1', '0.5.0')
|
||||
@@ -508,7 +536,7 @@ Bugfix for running `coffee --interactive` and `--run` from outside of the Coffee
|
||||
releaseHeader('2009-12-26', '0.1.5', '0.1.4')
|
||||
```
|
||||
|
||||
Array slice literals and array comprehensions can now both take Ruby-style ranges to specify the start and end. JavaScript variable declaration is now pushed up to the top of the scope, making all assignment statements into expressions. You can use `\` to escape newlines. The `coffee-script` command is now called `coffee`.
|
||||
Array slice literals and array comprehensions can now both take Ruby-style ranges to specify the start and end. JavaScript variable declaration is now pushed up to the top of the scope, making all assignment statements into expressions. You can use `\` to escape newlines. The `coffeescript` command is now called `coffee`.
|
||||
|
||||
```
|
||||
releaseHeader('2009-12-25', '0.1.4', '0.1.3')
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
## Web Chat (IRC)
|
||||
|
||||
Quick help and advice can usually be found in the CoffeeScript IRC room. Join `#coffeescript` on `irc.freenode.net`, or click the button below to open a webchat session on this page.
|
||||
|
||||
<button id="open_webchat">click to open #coffeescript</button>
|
||||
Quick help and advice can often be found in the CoffeeScript IRC room `#coffeescript` on `irc.freenode.net`, which you can [join via your web browser](http://webchat.freenode.net/?channels=coffeescript).
|
||||
|
||||
@@ -1,20 +1,15 @@
|
||||
## Classes, Inheritance, and Super
|
||||
## Classes
|
||||
|
||||
JavaScript’s prototypal inheritance has always been a bit of a brain-bender, with a whole family tree of libraries that provide a cleaner syntax for classical inheritance on top of JavaScript’s prototypes: [Base2](http://code.google.com/p/base2/), [Prototype.js](http://prototypejs.org/), [JS.Class](http://jsclass.jcoglan.com/), etc. The libraries provide syntactic sugar, but the built-in inheritance would be completely usable if it weren’t for a couple of small exceptions: it’s awkward to call **super** (the prototype object’s implementation of the current function), and it’s awkward to correctly set the prototype chain.
|
||||
|
||||
Instead of repetitively attaching functions to a prototype, CoffeeScript provides a basic `class` structure that allows you to name your class, set the superclass, assign prototypal properties, and define the constructor, in a single assignable expression.
|
||||
|
||||
Constructor functions are named, to better support helpful stack traces. In the first class in the example below, `this.constructor.name is "Animal"`.
|
||||
CoffeeScript 1 provided the `class` and `extends` keywords as syntactic sugar for working with prototypal functions. With ES2015, JavaScript has adopted those keywords; so CoffeeScript 2 compiles its `class` and `extends` keywords to ES2015 classes.
|
||||
|
||||
```
|
||||
codeFor('classes', true)
|
||||
```
|
||||
|
||||
If structuring your prototypes classically isn’t your cup of tea, CoffeeScript provides a couple of lower-level conveniences. The `extends` operator helps with proper prototype setup, and can be used to create an inheritance chain between any pair of constructor functions; `::` gives you quick access to an object’s prototype; and `super()` is converted into a call against the immediate ancestor’s method of the same name.
|
||||
Static methods can be defined using `@` before the method name:
|
||||
|
||||
```
|
||||
codeFor('prototypes', '"one_two".dasherize()')
|
||||
codeFor('static', 'Teenager.say("Are we there yet?")')
|
||||
```
|
||||
|
||||
Finally, class definitions are blocks of executable code, which make for interesting metaprogramming possibilities. Because in the context of a class definition, `this` is the class object itself (the constructor function), you can assign static properties by using
|
||||
`@property: value`, and call functions defined in parent classes: `@attr 'title', type: 'text'`
|
||||
Finally, class definitions are blocks of executable code, which make for interesting metaprogramming possibilities. In the context of a class definition, `this` is the class object itself; therefore, you can assign static properties by using `@property: value`.
|
||||
|
||||
21
documentation/sections/coffeescript_2.md
Normal file
21
documentation/sections/coffeescript_2.md
Normal file
@@ -0,0 +1,21 @@
|
||||
## CoffeeScript 2
|
||||
|
||||
### 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 a cleaner, terser syntax that uses less punctuation and enforces indentation, to make code easier to read and reason about. Increased clarity leads to increased quality, and fewer bugs. This benefit of CoffeeScript remains, even in an ES2015+ world.
|
||||
|
||||
### ES2015+ Output
|
||||
|
||||
CoffeeScript 2 supports many of the latest ES2015+ features, output using 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 the [CoffeeScript 1.x branch](/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 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 -p *.coffee | babel --presets env > app.js
|
||||
```
|
||||
13
documentation/sections/comments.md
Normal file
13
documentation/sections/comments.md
Normal file
@@ -0,0 +1,13 @@
|
||||
## Comments
|
||||
|
||||
In CoffeeScript, comments are denoted by the `#` character. Everything from a `#` to the end of the line is ignored by the compiler, and will be excluded from the JavaScript output.
|
||||
|
||||
```
|
||||
codeFor('comment')
|
||||
```
|
||||
|
||||
Sometimes you’d like to pass a block comment through to the generated JavaScript. For example, when you need to embed a licensing header at the top of a file. Block comments, which mirror the syntax for block strings, are preserved in the generated output.
|
||||
|
||||
```
|
||||
codeFor('block_comment')
|
||||
```
|
||||
16
documentation/sections/contributing.md
Normal file
16
documentation/sections/contributing.md
Normal file
@@ -0,0 +1,16 @@
|
||||
## Contributing
|
||||
|
||||
Contributions are welcome! Feel free to fork [the repo](http://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).
|
||||
|
||||
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).
|
||||
|
||||
There are several things you can do to increase your odds of having your pull request accepted:
|
||||
|
||||
* Create tests! Any pull request should probably include basic tests to verify you didn’t break anything, or future changes won’t break your code.
|
||||
* Follow the style of the rest of the CoffeeScript codebase.
|
||||
* Ensure any ECMAScript syntax is mature (at Stage 4), with no further potential changes.
|
||||
* Add only features that have broad utility, rather than a feature aimed at a specific use case or framework.
|
||||
|
||||
Of course, it’s entirely possible that you have a great addition, but it doesn’t fit within these constraints. Feel free to roll your own solution; you will have [plenty of company](https://github.com/jashkenas/coffeescript/wiki/In-The-Wild).
|
||||
@@ -1,4 +1,4 @@
|
||||
## Bound Functions, Generator Functions
|
||||
## Function Modifiers
|
||||
|
||||
In JavaScript, the `this` keyword is dynamically scoped to mean the object that the current function is attached to. If you pass a function as a callback or attach it to a different object, the original value of `this` will be lost. If you’re not familiar with this behavior, [this Digital Web article](http://64.13.255.16/articles/scope_in_javascript/) gives a good overview of the quirks.
|
||||
|
||||
@@ -12,7 +12,7 @@ If we had used `->` in the callback above, `@customer` would have referred to th
|
||||
|
||||
When used in a class definition, methods declared with the fat arrow will be automatically bound to each instance of the class when the instance is constructed.
|
||||
|
||||
CoffeeScript functions also support [ES2015 generator functions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*) through the `yield` keyword. There’s no `function*(){}` nonsense — a generator in CoffeeScript is simply a function that yields.
|
||||
CoffeeScript also supports [generator functions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*) and [async functions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function) through the `yield` and `await` keywords respectively. There's no `function*(){}` or `async function(){}` nonsense — a generator in CoffeeScript is simply a function that yields, and an async function in CoffeeScript is simply a function that awaits.
|
||||
|
||||
```
|
||||
codeFor('generators', 'ps.next().value')
|
||||
@@ -25,3 +25,9 @@ You can iterate over a generator function using `for…from`.
|
||||
```
|
||||
codeFor('generator_iteration', 'getFibonacciNumbers(10)')
|
||||
```
|
||||
|
||||
Similar to how `yield return` forces a generator, `await return` may be used to force a function to be async.
|
||||
|
||||
```
|
||||
codeFor('async', true)
|
||||
```
|
||||
|
||||
@@ -6,7 +6,7 @@ Functions are defined by an optional list of parameters in parentheses, an arrow
|
||||
codeFor('functions', 'cube(5)')
|
||||
```
|
||||
|
||||
Functions may also have default values for arguments, which will be used if the incoming argument is missing (`null` or `undefined`).
|
||||
Functions may also have default values for arguments, which will be used if the incoming argument is missing (`undefined`).
|
||||
|
||||
```
|
||||
codeFor('default_args', 'fill("cup")')
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
## Installation
|
||||
|
||||
The command-line version of `coffee` is available as a [Node.js](http://nodejs.org/) utility. The [core compiler](v<%= majorVersion %>/browser-compiler/coffee-script.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](http://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)).
|
||||
|
||||
To install, first make sure you have a working copy of the latest stable version of [Node.js](http://nodejs.org/). You can then install CoffeeScript globally with [npm](http://npmjs.org):
|
||||
|
||||
```bash
|
||||
npm install --global coffee-script
|
||||
npm install --global coffeescript@next
|
||||
```
|
||||
|
||||
When you need CoffeeScript as a dependency of a project, within that project’s folder you can install it locally:
|
||||
|
||||
```bash
|
||||
npm install --save coffee-script
|
||||
npm install --save coffeescript@next
|
||||
```
|
||||
|
||||
@@ -1,13 +1,9 @@
|
||||
**CoffeeScript is a little language that compiles into JavaScript.** 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.
|
||||
|
||||
The golden rule of CoffeeScript is: _“It’s just JavaScript”_. 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.
|
||||
|
||||
The CoffeeScript compiler goes to great lengths to generate output JavaScript that runs in every JavaScript runtime, but there are exceptions. Use [generator functions](#generator-functions), [`for…from`](#generator-iteration), or [tagged template literals](#tagged-template-literals) only if you know that your [target runtimes can support them](http://kangax.github.io/compat-table/es6/). If you use [modules](#modules), you will need to [use an additional tool to resolve them](#modules-note).
|
||||
The golden rule of CoffeeScript is: _“It’s just JavaScript.”_ 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.
|
||||
|
||||
**Latest Version:** [<%= fullVersion %>](http://github.com/jashkenas/coffeescript/tarball/<%= fullVersion %>)
|
||||
|
||||
```bash
|
||||
npm install -g coffee-script
|
||||
npm install -g coffeescript@next
|
||||
```
|
||||
|
||||
**CoffeeScript 2 is coming!** It adds support for [ES2015 classes](/v2/#classes), [`async`/`await`](/v2/#fat-arrow), and generates JavaScript using ES2015+ syntax. <a href="/v2/">Learn more</a>.</p>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
_This reference is structured so that it can be read from top to bottom, if you like. Later sections use ideas and syntax previously introduced. Familiarity with JavaScript is assumed. In all of the following examples, the source CoffeeScript is provided on the left, and the direct compilation into JavaScript is on the right._
|
||||
|
||||
_Many of the examples can be run (where it makes sense) by pressing the **run** button on the right, and can be loaded into the “Try CoffeeScript” console by pressing the **load** button on the left._
|
||||
_Many of the examples can be run (where it makes sense) by pressing the_ <small>▶</small> _button on the right. The CoffeeScript on the left is editable, and the JavaScript will update as you edit._
|
||||
|
||||
First, the basics: CoffeeScript uses significant whitespace to delimit blocks of code. You don’t need to use semicolons `;` to terminate expressions, ending the line will do just as well (although semicolons can still be used to fit multiple expressions onto a single line). Instead of using curly braces `{ }` to surround blocks of code in [functions](#literals), [if-statements](#conditionals), [switch](#switch), and [try/catch](#try), use indentation.
|
||||
|
||||
|
||||
@@ -3,5 +3,3 @@
|
||||
Besides being used as an ordinary programming language, CoffeeScript may also be written in “literate” mode. If you name your file with a `.litcoffee` extension, you can write it as a Markdown document — a document that also happens to be executable CoffeeScript code. The compiler will treat any indented blocks (Markdown’s way of indicating source code) as code, and ignore the rest as comments.
|
||||
|
||||
Just for kicks, a little bit of the compiler is currently implemented in this fashion: See it [as a document](https://gist.github.com/jashkenas/3fc3c1a8b1009c00d9df), [raw](https://raw.github.com/jashkenas/coffeescript/master/src/scope.litcoffee), and [properly highlighted in a text editor](http://cl.ly/LxEu).
|
||||
|
||||
I’m fairly excited about this direction for the language, and am looking forward to writing (and more importantly, reading) more programs in this style. More information about Literate CoffeeScript, including an [example program](https://github.com/jashkenas/journo), are [available in this blog post](http://ashkenas.com/literate-coffeescript).
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
## Overview
|
||||
|
||||
_CoffeeScript on the left, compiled JavaScript output on the right._
|
||||
_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!_
|
||||
|
||||
```
|
||||
codeFor('overview', 'cubes', false)
|
||||
|
||||
7
documentation/sections/prototypal_inheritance.md
Normal file
7
documentation/sections/prototypal_inheritance.md
Normal file
@@ -0,0 +1,7 @@
|
||||
## Prototypal Inheritance
|
||||
|
||||
In addition to supporting ES2015 classes, CoffeeScript provides a few shortcuts for working with prototypes. The `extends` operator can be used to create an inheritance chain between any pair of constructor functions, and `::` gives you quick access to an object’s prototype:
|
||||
|
||||
```
|
||||
codeFor('prototypes', '"one_two".dasherize()')
|
||||
```
|
||||
@@ -1,14 +1,6 @@
|
||||
## Resources
|
||||
|
||||
* [Source Code](http://github.com/jashkenas/coffeescript/)<br>
|
||||
Use `bin/coffee` to test your changes,<br>
|
||||
`bin/cake test` to run the test suite,<br>
|
||||
`bin/cake build` to rebuild the full CoffeeScript compiler, and<br>
|
||||
`bin/cake build:except-parser` to recompile much faster if you’re not editing `grammar.coffee`.
|
||||
|
||||
`git checkout lib && bin/cake build:full` is a good command to run when you’re working on the core language. It’ll refresh the `lib` folder (in case you broke something), build your altered compiler, use that to rebuild itself (a good sanity test) and then run all of the tests. If they pass, there’s a good chance you’ve made a successful change.
|
||||
* [Browser Tests](v<%= majorVersion %>/test.html)<br>
|
||||
Run CoffeeScript’s test suite in your current browser.
|
||||
* [CoffeeScript on GitHub](http://github.com/jashkenas/coffeescript/)
|
||||
* [CoffeeScript Issues](http://github.com/jashkenas/coffeescript/issues)<br>
|
||||
Bug reports, feature proposals, and ideas for changes to the language belong here.
|
||||
* [CoffeeScript Google Group](https://groups.google.com/forum/#!forum/coffeescript)<br>
|
||||
@@ -17,7 +9,7 @@
|
||||
If you’ve ever learned a neat CoffeeScript tip or trick, or ran into a gotcha — share it on the wiki. The wiki also serves as a directory of handy [text editor extensions](http://github.com/jashkenas/coffeescript/wiki/Text-editor-plugins), [web framework plugins](http://github.com/jashkenas/coffeescript/wiki/Web-framework-plugins), and general [CoffeeScript build tools](http://github.com/jashkenas/coffeescript/wiki/Build-tools).
|
||||
* [The FAQ](http://github.com/jashkenas/coffeescript/wiki/FAQ)<br>
|
||||
Perhaps your CoffeeScript-related question has been asked before. Check the FAQ first.
|
||||
* [JS2Coffee](http://js2coffee.org)<br>
|
||||
* [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>
|
||||
The CoffeeScript logo is available in SVG for use in presentations.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
## "text/coffeescript" Script Tags
|
||||
## `"text/coffeescript"` Script Tags
|
||||
|
||||
While it’s not recommended for serious use, CoffeeScripts may be included directly within the browser using `<script type="text/coffeescript">` tags. The source includes a compressed and minified version of the compiler ([Download current version here, 51k when gzipped](v<%= majorVersion %>/browser-compiler/coffee-script.js)) as `v<%= majorVersion %>/browser-compiler/coffee-script.js`. Include this file on a page with inline CoffeeScript tags, and it will compile and evaluate them in order.
|
||||
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 `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” above, as well as the jQuery for the menu, is implemented in just this way. View source and look at the bottom of the page to see the example. Including the script also gives you access to `CoffeeScript.compile()` so you can pop open Firebug and try compiling some strings.
|
||||
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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
## Source Maps
|
||||
|
||||
CoffeeScript 1.6.1 and above include support for generating source maps, a way to tell your JavaScript engine what part of your CoffeeScript program matches up with the code being evaluated. Browsers that support it can automatically use source maps to show your original source code in the debugger. To generate source maps alongside your JavaScript files, pass the `--map` or `-m` flag to the compiler.
|
||||
CoffeeScript includes support for generating source maps, a way to tell your JavaScript engine what part of your CoffeeScript program matches up with the code being evaluated. Browsers that support it can automatically use source maps to show your original source code in the debugger. To generate source maps alongside your JavaScript files, pass the `--map` or `-m` flag to the compiler.
|
||||
|
||||
For a full introduction to source maps, how they work, and how to hook them up in your browser, read the [HTML5 Tutorial](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/).
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
## String Interpolation, Block Strings, and Block Comments
|
||||
## Strings
|
||||
|
||||
Ruby-style string interpolation is included in CoffeeScript. Double-quoted strings allow for interpolated values, using `#{ … }`, and single-quoted strings are literal. You may even use interpolation in object keys.
|
||||
Like JavaScript and many other languages, CoffeeScript supports strings as delimited by the `"` or `'` characters. CoffeeScript also supports string interpolation within `"`-quoted strings, using `#{ … }`. Single-quoted strings are literal. You may even use interpolation in object keys.
|
||||
|
||||
```
|
||||
codeFor('interpolation', 'sentence')
|
||||
@@ -12,16 +12,10 @@ Multiline strings are allowed in CoffeeScript. Lines are joined by a single spac
|
||||
codeFor('strings', 'mobyDick')
|
||||
```
|
||||
|
||||
Block strings can be used to hold formatted or indentation-sensitive text (or, if you just don’t feel like escaping quotes and apostrophes). The indentation level that begins the block is maintained throughout, so you can keep it all aligned with the body of your code.
|
||||
Block strings, delimited by `"""` or `'''`, can be used to hold formatted or indentation-sensitive text (or, if you just don’t feel like escaping quotes and apostrophes). The indentation level that begins the block is maintained throughout, so you can keep it all aligned with the body of your code.
|
||||
|
||||
```
|
||||
codeFor('heredocs', 'html')
|
||||
```
|
||||
|
||||
Double-quoted block strings, like other double-quoted strings, allow interpolation.
|
||||
|
||||
Sometimes you’d like to pass a block comment through to the generated JavaScript. For example, when you need to embed a licensing header at the top of a file. Block comments, which mirror the syntax for block strings, are preserved in the generated code.
|
||||
|
||||
```
|
||||
codeFor('block_comment')
|
||||
```
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
CoffeeScript supports [ES2015 tagged template literals](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Template_literals#Tagged_template_literals), which enable customized string interpolation. If you immediately prefix a string with a function name (no space between the two), CoffeeScript will output this “function plus string” combination as an ES2015 tagged template literal, which will [behave accordingly](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Template_literals#Tagged_template_literals): the function is called, with the parameters being the input text and expression parts that make up the interpolated string. The function can then assemble these parts into an output string, providing custom string interpolation.
|
||||
|
||||
Be aware that the CoffeeScript compiler is outputting ES2015 syntax for this feature, so your target JavaScript runtime(s) must support this syntax for your code to work; or you could use tools like [Babel](http://babeljs.io/) or [Traceur Compiler](https://github.com/google/traceur-compiler) to convert this ES2015 syntax into compatible JavaScript.
|
||||
|
||||
```
|
||||
codeFor('tagged_template_literals', 'greet("greg", "awesome")')
|
||||
```
|
||||
|
||||
7
documentation/sections/test.md
Normal file
7
documentation/sections/test.md
Normal file
@@ -0,0 +1,7 @@
|
||||
## Browser-based Tests
|
||||
|
||||
CoffeeScript includes an extensive test suite, which verifies that the compiler generates JavaScript that behaves as it should. The tests canonically run via the Node runtime, and must all pass there before we consider publishing a new release of CoffeeScript; but you can also run the tests in a web browser. This can be a good way to determine which features of CoffeeScript your current browser may not support. In general, the latest version of [Google Chrome Canary](https://www.google.com/chrome/browser/canary.html) should pass all the tests.
|
||||
|
||||
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.dev/v<%= majorVersion %>/test.html)
|
||||
34
documentation/sections/unsupported.md
Normal file
34
documentation/sections/unsupported.md
Normal file
@@ -0,0 +1,34 @@
|
||||
## Unsupported ECMAScript Features
|
||||
|
||||
There are a few ECMAScript features that CoffeeScript intentionally doesn’t support.
|
||||
|
||||
<section id="unsupported-let-const">
|
||||
|
||||
### `let` and `const`: Block-Scoped and Reassignment-Protected Variables
|
||||
|
||||
When CoffeeScript was designed, `var` was [intentionally omitted](https://github.com/jashkenas/coffeescript/issues/238#issuecomment-153502). This was to spare developers the mental housekeeping of needing to worry about variable _declaration_ (`var foo`) as opposed to variable _assignment_ (`foo = 1`). The CoffeeScript compiler automatically takes care of declaration for you, by generating `var` statements at the top of every function scope. This makes it impossible to accidentally declare a global variable.
|
||||
|
||||
`let` and `const` add a useful ability to JavaScript in that you can use them to declare variables within a _block_ scope, for example within an `if` statement body or a `for` loop body, whereas `var` always declares variables in the scope of an entire function. When CoffeeScript 2 was designed, there was much discussion of whether this functionality was useful enough to outweigh the simplicity offered by never needing to consider variable declaration in CoffeeScript. In the end, it was decided that the simplicity was more valued. In CoffeeScript there remains only one type of variable.
|
||||
|
||||
Keep in mind that `const` only protects you from _reassigning_ a variable; it doesn’t prevent the variable’s value from changing, the way constants usually do in other languages:
|
||||
|
||||
```js
|
||||
const obj = {foo: 'bar'};
|
||||
obj.foo = 'baz'; // Allowed!
|
||||
obj = {}; // Throws error
|
||||
```
|
||||
|
||||
</section>
|
||||
<section id="unsupported-get-set">
|
||||
|
||||
### `get` and `set` Keyword Shorthand Syntax
|
||||
|
||||
`get` and `set`, as keywords preceding functions or class methods, are intentionally unimplemented in CoffeeScript.
|
||||
|
||||
This is to avoid grammatical ambiguity, since in CoffeeScript such a construct looks identical to a function call (e.g. `get(function foo() {})`); and because there is an [alternate syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty) that is slightly more verbose but just as effective:
|
||||
|
||||
```
|
||||
codeFor('get_set', 'screen.height')
|
||||
```
|
||||
|
||||
</section>
|
||||
@@ -3,7 +3,7 @@
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
|
||||
<title>CoffeeScript Test Suite</title>
|
||||
<script src="browser-compiler/coffee-script.js"></script>
|
||||
<script src="browser-compiler/coffeescript.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/underscorejs/1.8.3/underscore-min.js"></script>
|
||||
<style>
|
||||
body, pre {
|
||||
@@ -39,9 +39,10 @@
|
||||
<script type="text/coffeescript">
|
||||
@testingBrowser = yes
|
||||
@global = window
|
||||
stdout = document.getElementById 'stdout'
|
||||
start = new Date
|
||||
success = total = done = failed = 0
|
||||
stdout = document.getElementById 'stdout'
|
||||
start = new Date
|
||||
@currentFile = ''
|
||||
@passedTests = failedTests = total = done = 0
|
||||
|
||||
say = (msg, className) ->
|
||||
div = document.createElement 'div'
|
||||
@@ -54,12 +55,20 @@ say = (msg, className) ->
|
||||
++total
|
||||
try
|
||||
fn.call(fn)
|
||||
++success
|
||||
catch exception
|
||||
say "#{description}:", 'bad'
|
||||
say fn.toString(), 'subtle' if fn.toString?
|
||||
say exception, 'bad'
|
||||
console.error exception
|
||||
++passedTests
|
||||
catch error
|
||||
failures.push
|
||||
error: error
|
||||
description: description
|
||||
source: fn.toString() if fn.toString?
|
||||
|
||||
@failures =
|
||||
push: (failure) -> # Match function called by regular tests
|
||||
++failedTests
|
||||
say "#{failure.description}:", 'bad'
|
||||
say failure.source, 'subtle' if failure.source?
|
||||
say failure.error, 'bad'
|
||||
console.error failure.error
|
||||
|
||||
@ok = (good, msg = 'Error') ->
|
||||
throw Error msg unless good
|
||||
@@ -99,14 +108,15 @@ say = (msg, className) ->
|
||||
for test in document.getElementsByClassName 'test'
|
||||
say '\u2714 ' + test.id
|
||||
options = {}
|
||||
options.filename = currentFile = test.id
|
||||
options.literate = yes if test.type is 'text/x-literate-coffeescript'
|
||||
CoffeeScript.run test.innerHTML, options
|
||||
|
||||
# Finish up
|
||||
yay = success is total and not failed
|
||||
yay = passedTests is total and not failedTests
|
||||
sec = (new Date - start) / 1000
|
||||
msg = "passed #{success} tests in #{ sec.toFixed 2 } seconds"
|
||||
msg = "failed #{ total - success } tests and #{msg}" unless yay
|
||||
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')
|
||||
</script>
|
||||
|
||||
|
||||
@@ -70,7 +70,7 @@
|
||||
<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/coffeescript.html">The CoffeeScript Module — src/coffeescript</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>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
fs = require 'fs'
|
||||
CoffeeScript = require '../../lib/coffee-script'
|
||||
CoffeeScript = require '../../lib/coffeescript'
|
||||
|
||||
|
||||
module.exports = ->
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
</script>
|
||||
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
|
||||
<script src="v<%= majorVersion %>/browser-compiler/coffee-script.js"></script>
|
||||
<script src="v<%= majorVersion %>/browser-compiler/coffeescript.js"></script>
|
||||
|
||||
146
documentation/v2/body.html
Normal file
146
documentation/v2/body.html
Normal file
@@ -0,0 +1,146 @@
|
||||
<%= include('navbar.html') %>
|
||||
|
||||
<%= 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">
|
||||
<%= 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') %>
|
||||
</header>
|
||||
|
||||
<section id="overview">
|
||||
<%= htmlFor('introduction') %>
|
||||
<%= htmlFor('overview') %>
|
||||
</section>
|
||||
<section id="coffeescript-2">
|
||||
<%= htmlFor('coffeescript_2') %>
|
||||
</section>
|
||||
<section id="installation">
|
||||
<%= htmlFor('installation') %>
|
||||
</section>
|
||||
<section id="usage">
|
||||
<%= htmlFor('usage') %>
|
||||
</section>
|
||||
<section id="language">
|
||||
<%= htmlFor('language') %>
|
||||
<section id="functions">
|
||||
<%= htmlFor('functions') %>
|
||||
</section>
|
||||
<section id="strings">
|
||||
<%= htmlFor('strings') %>
|
||||
</section>
|
||||
<section id="objects-and-arrays">
|
||||
<%= htmlFor('objects_and_arrays') %>
|
||||
</section>
|
||||
<section id="comments">
|
||||
<%= htmlFor('comments') %>
|
||||
</section>
|
||||
<section id="lexical-scope">
|
||||
<%= htmlFor('lexical_scope') %>
|
||||
</section>
|
||||
<section id="conditionals">
|
||||
<%= htmlFor('conditionals') %>
|
||||
</section>
|
||||
<section id="splats">
|
||||
<%= htmlFor('splats') %>
|
||||
</section>
|
||||
<section id="loops">
|
||||
<%= htmlFor('loops') %>
|
||||
</section>
|
||||
<section id="slices">
|
||||
<%= htmlFor('slices') %>
|
||||
</section>
|
||||
<section id="expressions">
|
||||
<%= htmlFor('expressions') %>
|
||||
</section>
|
||||
<section id="operators">
|
||||
<%= htmlFor('operators') %>
|
||||
</section>
|
||||
<section id="existential-operator">
|
||||
<%= htmlFor('existential_operator') %>
|
||||
</section>
|
||||
<section id="classes">
|
||||
<%= htmlFor('classes') %>
|
||||
</section>
|
||||
<section id="prototypal-inheritance">
|
||||
<%= htmlFor('prototypal_inheritance') %>
|
||||
</section>
|
||||
<section id="destructuring">
|
||||
<%= htmlFor('destructuring') %>
|
||||
</section>
|
||||
<section id="fat-arrow">
|
||||
<%= htmlFor('fat_arrow') %>
|
||||
</section>
|
||||
<section id="switch">
|
||||
<%= htmlFor('switch') %>
|
||||
</section>
|
||||
<section id="try">
|
||||
<%= htmlFor('try') %>
|
||||
</section>
|
||||
<section id="comparisons">
|
||||
<%= htmlFor('comparisons') %>
|
||||
</section>
|
||||
<section id="regexes">
|
||||
<%= htmlFor('heregexes') %>
|
||||
</section>
|
||||
<section id="tagged-template-literals">
|
||||
<%= htmlFor('tagged_template_literals') %>
|
||||
</section>
|
||||
<section id="modules">
|
||||
<%= htmlFor('modules') %>
|
||||
</section>
|
||||
<section id="embedded">
|
||||
<%= htmlFor('embedded') %>
|
||||
</section>
|
||||
</section>
|
||||
<section id="unsupported">
|
||||
<%= htmlFor('unsupported') %>
|
||||
</section>
|
||||
<section id="literate">
|
||||
<%= htmlFor('literate') %>
|
||||
</section>
|
||||
<section id="source-maps">
|
||||
<%= htmlFor('source_maps') %>
|
||||
</section>
|
||||
<section id="cake">
|
||||
<%= htmlFor('cake') %>
|
||||
</section>
|
||||
<section id="scripts">
|
||||
<%= htmlFor('scripts') %>
|
||||
</section>
|
||||
<section id="resources">
|
||||
<%= htmlFor('resources') %>
|
||||
<section id="books">
|
||||
<%= htmlFor('books') %>
|
||||
</section>
|
||||
<section id="screencasts">
|
||||
<%= htmlFor('screencasts') %>
|
||||
</section>
|
||||
<section id="examples">
|
||||
<%= htmlFor('examples') %>
|
||||
</section>
|
||||
<section id="chat">
|
||||
<%= htmlFor('chat') %>
|
||||
</section>
|
||||
<section id="annotated-source">
|
||||
<%= htmlFor('annotated_source') %>
|
||||
</section>
|
||||
<section id="contributing">
|
||||
<%= htmlFor('contributing') %>
|
||||
</section>
|
||||
</section>
|
||||
<section id="breaking-changes">
|
||||
<%= htmlFor('breaking_changes') %>
|
||||
</section>
|
||||
<section id="changelog">
|
||||
<%= htmlFor('changelog') %>
|
||||
</section>
|
||||
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
11
documentation/v2/code.coffee
Normal file
11
documentation/v2/code.coffee
Normal file
@@ -0,0 +1,11 @@
|
||||
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}
|
||||
17
documentation/v2/code.html
Normal file
17
documentation/v2/code.html
Normal file
@@ -0,0 +1,17 @@
|
||||
<aside class="code-example container-fluid bg-ribbed-dark" data-example="<%= file %>">
|
||||
<div class="row">
|
||||
<div class="col-md-6 coffeescript-input-column">
|
||||
<textarea class="coffeescript-input" id="<%= file %>-coffee"><%= cs %></textarea>
|
||||
</div>
|
||||
<div class="col-md-6 javascript-output-column">
|
||||
<textarea class="javascript-output" id="<%= file %>-js"><%= js %></textarea>
|
||||
</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>
|
||||
</div>
|
||||
<% } %>
|
||||
</aside>
|
||||
101
documentation/v2/docs.coffee
Normal file
101
documentation/v2/docs.coffee
Normal file
@@ -0,0 +1,101 @@
|
||||
$(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
|
||||
|
||||
|
||||
# Try CoffeeScript
|
||||
toggleTry = ->
|
||||
$('#try, #try-link').toggleClass 'active'
|
||||
closeTry = ->
|
||||
$('#try, #try-link').removeClass 'active'
|
||||
|
||||
$('[data-toggle="try"]').click toggleTry
|
||||
$('[data-close="try"]').click closeTry
|
||||
|
||||
|
||||
# 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 mode is 'coffeescript'
|
||||
pending = null
|
||||
editor.on 'change', (instance, change) ->
|
||||
clearTimeout pending
|
||||
pending = setTimeout ->
|
||||
lastCompilationStartTime = Date.now()
|
||||
try
|
||||
output = CoffeeScript.compile editor.getValue(), bare: yes
|
||||
lastCompilationElapsedTime = Math.max(200, Date.now() - lastCompilationStartTime)
|
||||
catch exception
|
||||
output = "#{exception}"
|
||||
editors[index + 1].setValue output
|
||||
, lastCompilationElapsedTime
|
||||
|
||||
|
||||
# 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
|
||||
|
||||
$('[data-action="link"]').click ->
|
||||
index = $("##{$(@).data('example')}-coffee").data 'index'
|
||||
coffee = editors[index].getValue()
|
||||
link = "try:#{encodeURIComponent coffee}"
|
||||
window.history.pushState {}, 'CoffeeScript', "#{location.href.split('#')[0]}##{link}"
|
||||
|
||||
|
||||
# Configure the initial state
|
||||
if window.location.hash?
|
||||
if window.location.hash is '#try'
|
||||
toggleTry()
|
||||
else if window.location.hash.indexOf('#try') is 0
|
||||
editors[0].setValue decodeURIComponent window.location.hash[5..]
|
||||
toggleTry()
|
||||
else
|
||||
initializeScrollspyFromHash window.location.hash
|
||||
416
documentation/v2/docs.css
Normal file
416
documentation/v2/docs.css
Normal file
@@ -0,0 +1,416 @@
|
||||
/* 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 */
|
||||
overflow-x: hidden;
|
||||
}
|
||||
body {
|
||||
/* Required for Scrollspy */
|
||||
position: relative;
|
||||
/* Push below header bar */
|
||||
margin-top: 3.5rem;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
.bg-inverse {
|
||||
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
|
||||
*/
|
||||
.navbar-fixed-top {
|
||||
height: 3.5rem;
|
||||
}
|
||||
|
||||
.navbar-brand {
|
||||
height: 2em;
|
||||
margin-right: 2em;
|
||||
}
|
||||
|
||||
.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;
|
||||
border-radius: 0.4em;
|
||||
}
|
||||
.navbar-nav .nav-link:hover,
|
||||
.navbar-nav .nav-link:active,
|
||||
.navbar-nav .nav-link.active {
|
||||
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%;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Sidebar
|
||||
*/
|
||||
|
||||
.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%;
|
||||
/* Scrollable contents if viewport is shorter than content */
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
.sidebar .nav-link.active,
|
||||
.sidebar .nav-link.active a:hover,
|
||||
.sidebar .nav-link.active a:focus {
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.nav .nav {
|
||||
margin-left: 1em;
|
||||
font-size: 0.9em;
|
||||
line-height: 1.7;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 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%;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Main content
|
||||
*/
|
||||
|
||||
.main {
|
||||
padding: 1.3em;
|
||||
}
|
||||
@media (min-width: 992px) {
|
||||
.main {
|
||||
padding-right: 2em;
|
||||
padding-left: 2em;
|
||||
}
|
||||
}
|
||||
|
||||
.title-logo {
|
||||
width: 30rem;
|
||||
margin: 3rem auto;
|
||||
}
|
||||
.title-logo path {
|
||||
fill: #2f2625;
|
||||
}
|
||||
|
||||
.main p, .main li, .main td, .main th {
|
||||
font-family: Lato;
|
||||
font-size: 1.3rem;
|
||||
font-weight: 300;
|
||||
}
|
||||
.main td {
|
||||
vertical-align: top;
|
||||
padding: 0.3em 0;
|
||||
}
|
||||
.main strong, .main th {
|
||||
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 {
|
||||
font-size: 1.3rem;
|
||||
}
|
||||
.main blockquote pre {
|
||||
background-color: #f8f3f0;
|
||||
color: #2f2625;
|
||||
border-radius: .3em;
|
||||
padding: 0.4em 0.6em;
|
||||
}
|
||||
|
||||
p, blockquote, table, .code-example {
|
||||
margin-bottom: 1.3rem;
|
||||
}
|
||||
|
||||
td code {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
h2, h3 {
|
||||
margin-top: 1.3em;
|
||||
margin-bottom: 0.6em;
|
||||
font-family: 'Alegreya Sans';
|
||||
}
|
||||
h2 {
|
||||
font-weight: 800;
|
||||
}
|
||||
h3, h2 time {
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.main section {
|
||||
/* Offset the anchor so that clicking on the sidebar links don’t hide the heading under the header bar */
|
||||
padding-top: 2.3rem;
|
||||
margin-top: -2.3rem;
|
||||
}
|
||||
|
||||
code, button {
|
||||
font-family: 'Roboto Mono';
|
||||
font-weight: 400;
|
||||
}
|
||||
code {
|
||||
background-color: #f8f3f0;
|
||||
color: #2f2625;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Code examples
|
||||
*/
|
||||
|
||||
textarea {
|
||||
position: absolute;
|
||||
left: -99999px; /* Hide off canvas, while still remaining visible */
|
||||
}
|
||||
|
||||
.code-example {
|
||||
background-color: #2f2625;
|
||||
padding: 1em;
|
||||
border-radius: 0.3em;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
.javascript-output-column {
|
||||
border-left: 1px solid rgba(255, 255, 255, 0.2);
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background-color: #69f0ae;
|
||||
color: #0b140f;
|
||||
border-color: #53d88f;
|
||||
transition: 0.2s ease-in-out;
|
||||
min-width: 3.125rem;
|
||||
}
|
||||
.btn-primary:active, .btn-primary:focus, .btn-primary:hover, .btn-primary:active:hover, .btn-primary:active:focus {
|
||||
background-color: #61fea8;
|
||||
color: #060a08;
|
||||
border-color: #4de486;
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
.CodeMirror {
|
||||
/* https://codemirror.net/demo/resize.html */
|
||||
height: auto;
|
||||
background: transparent;
|
||||
font-family: 'Roboto Mono';
|
||||
font-weight: 400;
|
||||
line-height: 1.25;
|
||||
}
|
||||
.javascript-output-column .CodeMirror-cursor {
|
||||
/* https://github.com/codemirror/CodeMirror/issues/2568 */
|
||||
display: none;
|
||||
}
|
||||
|
||||
/*
|
||||
* Try CoffeeScript
|
||||
*/
|
||||
.try-coffeescript {
|
||||
position: fixed;
|
||||
height: calc(100% - 3.5rem);
|
||||
top: 3.5rem;
|
||||
left: 0;
|
||||
right: 0;
|
||||
opacity: 0;
|
||||
transition: opacity 0.15s ease-in-out;
|
||||
}
|
||||
.try-coffeescript.active {
|
||||
opacity: 1;
|
||||
z-index: 1001;
|
||||
}
|
||||
|
||||
.try-coffeescript .CodeMirror {
|
||||
height: calc(100vh - 7rem);
|
||||
cursor: text;
|
||||
}
|
||||
|
||||
.try-coffeescript .code-column {
|
||||
overflow: hidden;
|
||||
background-color: #2f2625;
|
||||
color: #2f2625;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 767px) {
|
||||
.try-coffeescript .code-column {
|
||||
height: calc(50vh - 0.5 * 3.5rem);
|
||||
}
|
||||
}
|
||||
@media screen and (min-width: 768px) {
|
||||
.try-coffeescript .code-column {
|
||||
padding-bottom: 100%;
|
||||
margin-bottom: -100%;
|
||||
}
|
||||
}
|
||||
|
||||
.try-coffeescript button svg {
|
||||
height: 1em;
|
||||
transform: scale(1.3) translateY(0.1em);
|
||||
fill: #0b140f;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 767px) {
|
||||
.try-coffeescript .try-buttons {
|
||||
position: absolute;
|
||||
bottom: 1em;
|
||||
z-index: 1002;
|
||||
}
|
||||
}
|
||||
17
documentation/v2/navbar.html
Normal file
17
documentation/v2/navbar.html
Normal file
@@ -0,0 +1,17 @@
|
||||
<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>
|
||||
11
documentation/v2/scripts.html
Normal file
11
documentation/v2/scripts.html
Normal file
@@ -0,0 +1,11 @@
|
||||
<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>
|
||||
134
documentation/v2/sidebar.html
Normal file
134
documentation/v2/sidebar.html
Normal file
@@ -0,0 +1,134 @@
|
||||
<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>
|
||||
</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…</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="#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="#destructuring" class="nav-link" data-action="sidebar-nav">Destructuring Assignment</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a href="#fat-arrow" class="nav-link" data-action="sidebar-nav">Function Modifiers</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="#unsupported" class="nav-link" data-action="sidebar-nav">Unsupported ECMAScript Features</a>
|
||||
</li>
|
||||
</ul>
|
||||
</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="#breaking-changes" class="nav-link" data-action="sidebar-nav">Breaking Changes From 1.x</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a href="#changelog" class="nav-link" data-action="sidebar-nav">Change Log</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
8
documentation/v2/styles.html
Normal file
8
documentation/v2/styles.html
Normal file
@@ -0,0 +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">
|
||||
<!-- 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') %>
|
||||
</style>
|
||||
16
documentation/v2/try.html
Normal file
16
documentation/v2/try.html
Normal file
@@ -0,0 +1,16 @@
|
||||
<aside id="try" class="try-coffeescript container-fluid" data-example="try">
|
||||
<div class="row">
|
||||
<div class="col-md-6 code-column bg-ribbed-dark coffeescript-input-column">
|
||||
<textarea class="coffeescript-input" id="try-coffeescript-coffee">alert 'Hello CoffeeScript!'</textarea>
|
||||
</div>
|
||||
<div class="col-md-6 code-column bg-ribbed-dark javascript-output-column">
|
||||
<textarea class="javascript-output" id="try-coffeescript-js">alert('Hello CoffeeScript!');</textarea>
|
||||
</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> 
|
||||
<button type="button" class="btn btn-primary" data-action="link" data-example="try-coffeescript"><%= include('documentation/images/link.svg') %></button>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
75
documentation/v2/twilight.css
Normal file
75
documentation/v2/twilight.css
Normal file
@@ -0,0 +1,75 @@
|
||||
/* Adapted from https://github.com/FarhadG/code-mirror-themes/blob/master/themes/twilight.css */
|
||||
|
||||
.cm-s-twilight {
|
||||
letter-spacing: 0.3px;
|
||||
color: #f8f8f8;
|
||||
}
|
||||
.cm-s-twilight .CodeMirror-lines {
|
||||
padding: 0.5em 0;
|
||||
}
|
||||
.cm-s-twilight div.CodeMirror-cursor {
|
||||
border-left: 3px solid #f8f8f8;
|
||||
}
|
||||
.cm-s-twilight .CodeMirror-activeline-background {
|
||||
background: #ffffff08;
|
||||
}
|
||||
.cm-s-twilight .CodeMirror-selected {
|
||||
background: #ddf0ff33;
|
||||
}
|
||||
.cm-s-twilight .cm-comment {
|
||||
font-style: italic;
|
||||
color: #5f5a60;
|
||||
}
|
||||
.cm-s-twilight .cm-keyword {
|
||||
color: #cda869;
|
||||
}
|
||||
.cm-s-twilight .cm-string {
|
||||
color: #8f9d6a;
|
||||
}
|
||||
.cm-s-twilight .cm-property {
|
||||
color: #dad085;
|
||||
}
|
||||
.cm-s-twilight .cm-atom {
|
||||
color: #dad085;
|
||||
}
|
||||
.cm-s-twilight .cm-number {
|
||||
color: #dad085;
|
||||
}
|
||||
.cm-s-twilight .cm-operator {
|
||||
color: #cda869;
|
||||
}
|
||||
|
||||
/* Uneditable code blocks are inverted, so use darker versions of the above */
|
||||
|
||||
.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;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@@ -1,522 +0,0 @@
|
||||
// Generated by CoffeeScript 1.12.5
|
||||
(function() {
|
||||
var BALANCED_PAIRS, CALL_CLOSERS, EXPRESSION_CLOSE, EXPRESSION_END, EXPRESSION_START, IMPLICIT_CALL, IMPLICIT_END, IMPLICIT_FUNC, IMPLICIT_UNSPACED_CALL, INVERSES, LINEBREAKS, SINGLE_CLOSERS, SINGLE_LINERS, generate, k, left, len, ref, rite,
|
||||
indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; },
|
||||
slice = [].slice;
|
||||
|
||||
generate = function(tag, value, origin) {
|
||||
var tok;
|
||||
tok = [tag, value];
|
||||
tok.generated = true;
|
||||
if (origin) {
|
||||
tok.origin = origin;
|
||||
}
|
||||
return tok;
|
||||
};
|
||||
|
||||
exports.Rewriter = (function() {
|
||||
function Rewriter() {}
|
||||
|
||||
Rewriter.prototype.rewrite = function(tokens1) {
|
||||
this.tokens = tokens1;
|
||||
this.removeLeadingNewlines();
|
||||
this.closeOpenCalls();
|
||||
this.closeOpenIndexes();
|
||||
this.normalizeLines();
|
||||
this.tagPostfixConditionals();
|
||||
this.addImplicitBracesAndParens();
|
||||
this.addLocationDataToGeneratedTokens();
|
||||
this.fixOutdentLocationData();
|
||||
return this.tokens;
|
||||
};
|
||||
|
||||
Rewriter.prototype.scanTokens = function(block) {
|
||||
var i, token, tokens;
|
||||
tokens = this.tokens;
|
||||
i = 0;
|
||||
while (token = tokens[i]) {
|
||||
i += block.call(this, token, i, tokens);
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
Rewriter.prototype.detectEnd = function(i, condition, action) {
|
||||
var levels, ref, ref1, token, tokens;
|
||||
tokens = this.tokens;
|
||||
levels = 0;
|
||||
while (token = tokens[i]) {
|
||||
if (levels === 0 && condition.call(this, token, i)) {
|
||||
return action.call(this, token, i);
|
||||
}
|
||||
if (!token || levels < 0) {
|
||||
return action.call(this, token, i - 1);
|
||||
}
|
||||
if (ref = token[0], indexOf.call(EXPRESSION_START, ref) >= 0) {
|
||||
levels += 1;
|
||||
} else if (ref1 = token[0], indexOf.call(EXPRESSION_END, ref1) >= 0) {
|
||||
levels -= 1;
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
return i - 1;
|
||||
};
|
||||
|
||||
Rewriter.prototype.removeLeadingNewlines = function() {
|
||||
var i, k, len, ref, tag;
|
||||
ref = this.tokens;
|
||||
for (i = k = 0, len = ref.length; k < len; i = ++k) {
|
||||
tag = ref[i][0];
|
||||
if (tag !== 'TERMINATOR') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i) {
|
||||
return this.tokens.splice(0, i);
|
||||
}
|
||||
};
|
||||
|
||||
Rewriter.prototype.closeOpenCalls = function() {
|
||||
var action, condition;
|
||||
condition = function(token, i) {
|
||||
var ref;
|
||||
return ((ref = token[0]) === ')' || ref === 'CALL_END') || token[0] === 'OUTDENT' && this.tag(i - 1) === ')';
|
||||
};
|
||||
action = function(token, i) {
|
||||
return this.tokens[token[0] === 'OUTDENT' ? i - 1 : i][0] = 'CALL_END';
|
||||
};
|
||||
return this.scanTokens(function(token, i) {
|
||||
if (token[0] === 'CALL_START') {
|
||||
this.detectEnd(i + 1, condition, action);
|
||||
}
|
||||
return 1;
|
||||
});
|
||||
};
|
||||
|
||||
Rewriter.prototype.closeOpenIndexes = function() {
|
||||
var action, condition;
|
||||
condition = function(token, i) {
|
||||
var ref;
|
||||
return (ref = token[0]) === ']' || ref === 'INDEX_END';
|
||||
};
|
||||
action = function(token, i) {
|
||||
return token[0] = 'INDEX_END';
|
||||
};
|
||||
return this.scanTokens(function(token, i) {
|
||||
if (token[0] === 'INDEX_START') {
|
||||
this.detectEnd(i + 1, condition, action);
|
||||
}
|
||||
return 1;
|
||||
});
|
||||
};
|
||||
|
||||
Rewriter.prototype.indexOfTag = function() {
|
||||
var fuzz, i, j, k, pattern, ref, ref1;
|
||||
i = arguments[0], pattern = 2 <= arguments.length ? slice.call(arguments, 1) : [];
|
||||
fuzz = 0;
|
||||
for (j = k = 0, ref = pattern.length; 0 <= ref ? k < ref : k > ref; j = 0 <= ref ? ++k : --k) {
|
||||
while (this.tag(i + j + fuzz) === 'HERECOMMENT') {
|
||||
fuzz += 2;
|
||||
}
|
||||
if (pattern[j] == null) {
|
||||
continue;
|
||||
}
|
||||
if (typeof pattern[j] === 'string') {
|
||||
pattern[j] = [pattern[j]];
|
||||
}
|
||||
if (ref1 = this.tag(i + j + fuzz), indexOf.call(pattern[j], ref1) < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return i + j + fuzz - 1;
|
||||
};
|
||||
|
||||
Rewriter.prototype.looksObjectish = function(j) {
|
||||
var end, index;
|
||||
if (this.indexOfTag(j, '@', null, ':') > -1 || this.indexOfTag(j, null, ':') > -1) {
|
||||
return true;
|
||||
}
|
||||
index = this.indexOfTag(j, EXPRESSION_START);
|
||||
if (index > -1) {
|
||||
end = null;
|
||||
this.detectEnd(index + 1, (function(token) {
|
||||
var ref;
|
||||
return ref = token[0], indexOf.call(EXPRESSION_END, ref) >= 0;
|
||||
}), (function(token, i) {
|
||||
return end = i;
|
||||
}));
|
||||
if (this.tag(end + 1) === ':') {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
Rewriter.prototype.findTagsBackwards = function(i, tags) {
|
||||
var backStack, ref, ref1, ref2, ref3, ref4, ref5;
|
||||
backStack = [];
|
||||
while (i >= 0 && (backStack.length || (ref2 = this.tag(i), indexOf.call(tags, ref2) < 0) && ((ref3 = this.tag(i), indexOf.call(EXPRESSION_START, ref3) < 0) || this.tokens[i].generated) && (ref4 = this.tag(i), indexOf.call(LINEBREAKS, ref4) < 0))) {
|
||||
if (ref = this.tag(i), indexOf.call(EXPRESSION_END, ref) >= 0) {
|
||||
backStack.push(this.tag(i));
|
||||
}
|
||||
if ((ref1 = this.tag(i), indexOf.call(EXPRESSION_START, ref1) >= 0) && backStack.length) {
|
||||
backStack.pop();
|
||||
}
|
||||
i -= 1;
|
||||
}
|
||||
return ref5 = this.tag(i), indexOf.call(tags, ref5) >= 0;
|
||||
};
|
||||
|
||||
Rewriter.prototype.addImplicitBracesAndParens = function() {
|
||||
var stack, start;
|
||||
stack = [];
|
||||
start = null;
|
||||
return this.scanTokens(function(token, i, tokens) {
|
||||
var endImplicitCall, endImplicitObject, forward, inImplicit, inImplicitCall, inImplicitControl, inImplicitObject, newLine, nextTag, offset, prevTag, prevToken, ref, ref1, ref2, ref3, ref4, ref5, s, sameLine, stackIdx, stackTag, stackTop, startIdx, startImplicitCall, startImplicitObject, startsLine, tag;
|
||||
tag = token[0];
|
||||
prevTag = (prevToken = i > 0 ? tokens[i - 1] : [])[0];
|
||||
nextTag = (i < tokens.length - 1 ? tokens[i + 1] : [])[0];
|
||||
stackTop = function() {
|
||||
return stack[stack.length - 1];
|
||||
};
|
||||
startIdx = i;
|
||||
forward = function(n) {
|
||||
return i - startIdx + n;
|
||||
};
|
||||
inImplicit = function() {
|
||||
var ref, ref1;
|
||||
return (ref = stackTop()) != null ? (ref1 = ref[2]) != null ? ref1.ours : void 0 : void 0;
|
||||
};
|
||||
inImplicitCall = function() {
|
||||
var ref;
|
||||
return inImplicit() && ((ref = stackTop()) != null ? ref[0] : void 0) === '(';
|
||||
};
|
||||
inImplicitObject = function() {
|
||||
var ref;
|
||||
return inImplicit() && ((ref = stackTop()) != null ? ref[0] : void 0) === '{';
|
||||
};
|
||||
inImplicitControl = function() {
|
||||
var ref;
|
||||
return inImplicit && ((ref = stackTop()) != null ? ref[0] : void 0) === 'CONTROL';
|
||||
};
|
||||
startImplicitCall = function(j) {
|
||||
var idx;
|
||||
idx = j != null ? j : i;
|
||||
stack.push([
|
||||
'(', idx, {
|
||||
ours: true
|
||||
}
|
||||
]);
|
||||
tokens.splice(idx, 0, generate('CALL_START', '('));
|
||||
if (j == null) {
|
||||
return i += 1;
|
||||
}
|
||||
};
|
||||
endImplicitCall = function() {
|
||||
stack.pop();
|
||||
tokens.splice(i, 0, generate('CALL_END', ')', ['', 'end of input', token[2]]));
|
||||
return i += 1;
|
||||
};
|
||||
startImplicitObject = function(j, startsLine) {
|
||||
var idx, val;
|
||||
if (startsLine == null) {
|
||||
startsLine = true;
|
||||
}
|
||||
idx = j != null ? j : i;
|
||||
stack.push([
|
||||
'{', idx, {
|
||||
sameLine: true,
|
||||
startsLine: startsLine,
|
||||
ours: true
|
||||
}
|
||||
]);
|
||||
val = new String('{');
|
||||
val.generated = true;
|
||||
tokens.splice(idx, 0, generate('{', val, token));
|
||||
if (j == null) {
|
||||
return i += 1;
|
||||
}
|
||||
};
|
||||
endImplicitObject = function(j) {
|
||||
j = j != null ? j : i;
|
||||
stack.pop();
|
||||
tokens.splice(j, 0, generate('}', '}', token));
|
||||
return i += 1;
|
||||
};
|
||||
if (inImplicitCall() && (tag === 'IF' || tag === 'TRY' || tag === 'FINALLY' || tag === 'CATCH' || tag === 'CLASS' || tag === 'SWITCH')) {
|
||||
stack.push([
|
||||
'CONTROL', i, {
|
||||
ours: true
|
||||
}
|
||||
]);
|
||||
return forward(1);
|
||||
}
|
||||
if (tag === 'INDENT' && inImplicit()) {
|
||||
if (prevTag !== '=>' && prevTag !== '->' && prevTag !== '[' && prevTag !== '(' && prevTag !== ',' && prevTag !== '{' && prevTag !== 'TRY' && prevTag !== 'ELSE' && prevTag !== '=') {
|
||||
while (inImplicitCall()) {
|
||||
endImplicitCall();
|
||||
}
|
||||
}
|
||||
if (inImplicitControl()) {
|
||||
stack.pop();
|
||||
}
|
||||
stack.push([tag, i]);
|
||||
return forward(1);
|
||||
}
|
||||
if (indexOf.call(EXPRESSION_START, tag) >= 0) {
|
||||
stack.push([tag, i]);
|
||||
return forward(1);
|
||||
}
|
||||
if (indexOf.call(EXPRESSION_END, tag) >= 0) {
|
||||
while (inImplicit()) {
|
||||
if (inImplicitCall()) {
|
||||
endImplicitCall();
|
||||
} else if (inImplicitObject()) {
|
||||
endImplicitObject();
|
||||
} else {
|
||||
stack.pop();
|
||||
}
|
||||
}
|
||||
start = stack.pop();
|
||||
}
|
||||
if ((indexOf.call(IMPLICIT_FUNC, tag) >= 0 && token.spaced || tag === '?' && i > 0 && !tokens[i - 1].spaced) && (indexOf.call(IMPLICIT_CALL, nextTag) >= 0 || indexOf.call(IMPLICIT_UNSPACED_CALL, nextTag) >= 0 && !((ref = tokens[i + 1]) != null ? ref.spaced : void 0) && !((ref1 = tokens[i + 1]) != null ? ref1.newLine : void 0))) {
|
||||
if (tag === '?') {
|
||||
tag = token[0] = 'FUNC_EXIST';
|
||||
}
|
||||
startImplicitCall(i + 1);
|
||||
return forward(2);
|
||||
}
|
||||
if (indexOf.call(IMPLICIT_FUNC, tag) >= 0 && this.indexOfTag(i + 1, 'INDENT') > -1 && this.looksObjectish(i + 2) && !this.findTagsBackwards(i, ['CLASS', 'EXTENDS', 'IF', 'CATCH', 'SWITCH', 'LEADING_WHEN', 'FOR', 'WHILE', 'UNTIL'])) {
|
||||
startImplicitCall(i + 1);
|
||||
stack.push(['INDENT', i + 2]);
|
||||
return forward(3);
|
||||
}
|
||||
if (tag === ':') {
|
||||
s = (function() {
|
||||
var ref2;
|
||||
switch (false) {
|
||||
case ref2 = this.tag(i - 1), indexOf.call(EXPRESSION_END, ref2) < 0:
|
||||
return start[1];
|
||||
case this.tag(i - 2) !== '@':
|
||||
return i - 2;
|
||||
default:
|
||||
return i - 1;
|
||||
}
|
||||
}).call(this);
|
||||
while (this.tag(s - 2) === 'HERECOMMENT') {
|
||||
s -= 2;
|
||||
}
|
||||
this.insideForDeclaration = nextTag === 'FOR';
|
||||
startsLine = s === 0 || (ref2 = this.tag(s - 1), indexOf.call(LINEBREAKS, ref2) >= 0) || tokens[s - 1].newLine;
|
||||
if (stackTop()) {
|
||||
ref3 = stackTop(), stackTag = ref3[0], stackIdx = ref3[1];
|
||||
if ((stackTag === '{' || stackTag === 'INDENT' && this.tag(stackIdx - 1) === '{') && (startsLine || this.tag(s - 1) === ',' || this.tag(s - 1) === '{')) {
|
||||
return forward(1);
|
||||
}
|
||||
}
|
||||
startImplicitObject(s, !!startsLine);
|
||||
return forward(2);
|
||||
}
|
||||
if (inImplicitObject() && indexOf.call(LINEBREAKS, tag) >= 0) {
|
||||
stackTop()[2].sameLine = false;
|
||||
}
|
||||
newLine = prevTag === 'OUTDENT' || prevToken.newLine;
|
||||
if (indexOf.call(IMPLICIT_END, tag) >= 0 || indexOf.call(CALL_CLOSERS, tag) >= 0 && newLine) {
|
||||
while (inImplicit()) {
|
||||
ref4 = stackTop(), stackTag = ref4[0], stackIdx = ref4[1], (ref5 = ref4[2], sameLine = ref5.sameLine, startsLine = ref5.startsLine);
|
||||
if (inImplicitCall() && prevTag !== ',') {
|
||||
endImplicitCall();
|
||||
} else if (inImplicitObject() && !this.insideForDeclaration && sameLine && tag !== 'TERMINATOR' && prevTag !== ':') {
|
||||
endImplicitObject();
|
||||
} else if (inImplicitObject() && tag === 'TERMINATOR' && prevTag !== ',' && !(startsLine && this.looksObjectish(i + 1))) {
|
||||
if (nextTag === 'HERECOMMENT') {
|
||||
return forward(1);
|
||||
}
|
||||
endImplicitObject();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (tag === ',' && !this.looksObjectish(i + 1) && inImplicitObject() && !this.insideForDeclaration && (nextTag !== 'TERMINATOR' || !this.looksObjectish(i + 2))) {
|
||||
offset = nextTag === 'OUTDENT' ? 1 : 0;
|
||||
while (inImplicitObject()) {
|
||||
endImplicitObject(i + offset);
|
||||
}
|
||||
}
|
||||
return forward(1);
|
||||
});
|
||||
};
|
||||
|
||||
Rewriter.prototype.addLocationDataToGeneratedTokens = function() {
|
||||
return this.scanTokens(function(token, i, tokens) {
|
||||
var column, line, nextLocation, prevLocation, ref, ref1;
|
||||
if (token[2]) {
|
||||
return 1;
|
||||
}
|
||||
if (!(token.generated || token.explicit)) {
|
||||
return 1;
|
||||
}
|
||||
if (token[0] === '{' && (nextLocation = (ref = tokens[i + 1]) != null ? ref[2] : void 0)) {
|
||||
line = nextLocation.first_line, column = nextLocation.first_column;
|
||||
} else if (prevLocation = (ref1 = tokens[i - 1]) != null ? ref1[2] : void 0) {
|
||||
line = prevLocation.last_line, column = prevLocation.last_column;
|
||||
} else {
|
||||
line = column = 0;
|
||||
}
|
||||
token[2] = {
|
||||
first_line: line,
|
||||
first_column: column,
|
||||
last_line: line,
|
||||
last_column: column
|
||||
};
|
||||
return 1;
|
||||
});
|
||||
};
|
||||
|
||||
Rewriter.prototype.fixOutdentLocationData = function() {
|
||||
return this.scanTokens(function(token, i, tokens) {
|
||||
var prevLocationData;
|
||||
if (!(token[0] === 'OUTDENT' || (token.generated && token[0] === 'CALL_END') || (token.generated && token[0] === '}'))) {
|
||||
return 1;
|
||||
}
|
||||
prevLocationData = tokens[i - 1][2];
|
||||
token[2] = {
|
||||
first_line: prevLocationData.last_line,
|
||||
first_column: prevLocationData.last_column,
|
||||
last_line: prevLocationData.last_line,
|
||||
last_column: prevLocationData.last_column
|
||||
};
|
||||
return 1;
|
||||
});
|
||||
};
|
||||
|
||||
Rewriter.prototype.normalizeLines = function() {
|
||||
var action, condition, indent, outdent, starter;
|
||||
starter = indent = outdent = null;
|
||||
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;
|
||||
};
|
||||
action = function(token, i) {
|
||||
return this.tokens.splice((this.tag(i - 1) === ',' ? i - 1 : i), 0, outdent);
|
||||
};
|
||||
return this.scanTokens(function(token, i, tokens) {
|
||||
var j, k, ref, ref1, ref2, tag;
|
||||
tag = token[0];
|
||||
if (tag === 'TERMINATOR') {
|
||||
if (this.tag(i + 1) === 'ELSE' && this.tag(i - 1) !== 'OUTDENT') {
|
||||
tokens.splice.apply(tokens, [i, 1].concat(slice.call(this.indentation())));
|
||||
return 1;
|
||||
}
|
||||
if (ref = this.tag(i + 1), indexOf.call(EXPRESSION_CLOSE, ref) >= 0) {
|
||||
tokens.splice(i, 1);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (tag === 'CATCH') {
|
||||
for (j = k = 1; k <= 2; j = ++k) {
|
||||
if (!((ref1 = this.tag(i + j)) === 'OUTDENT' || ref1 === 'TERMINATOR' || ref1 === 'FINALLY')) {
|
||||
continue;
|
||||
}
|
||||
tokens.splice.apply(tokens, [i + j, 0].concat(slice.call(this.indentation())));
|
||||
return 2 + j;
|
||||
}
|
||||
}
|
||||
if (indexOf.call(SINGLE_LINERS, tag) >= 0 && this.tag(i + 1) !== 'INDENT' && !(tag === 'ELSE' && this.tag(i + 1) === 'IF')) {
|
||||
starter = tag;
|
||||
ref2 = this.indentation(tokens[i]), indent = ref2[0], outdent = ref2[1];
|
||||
if (starter === 'THEN') {
|
||||
indent.fromThen = true;
|
||||
}
|
||||
tokens.splice(i + 1, 0, indent);
|
||||
this.detectEnd(i + 2, condition, action);
|
||||
if (tag === 'THEN') {
|
||||
tokens.splice(i, 1);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 1;
|
||||
});
|
||||
};
|
||||
|
||||
Rewriter.prototype.tagPostfixConditionals = function() {
|
||||
var action, condition, original;
|
||||
original = null;
|
||||
condition = function(token, i) {
|
||||
var prevTag, tag;
|
||||
tag = token[0];
|
||||
prevTag = this.tokens[i - 1][0];
|
||||
return tag === 'TERMINATOR' || (tag === 'INDENT' && indexOf.call(SINGLE_LINERS, prevTag) < 0);
|
||||
};
|
||||
action = function(token, i) {
|
||||
if (token[0] !== 'INDENT' || (token.generated && !token.fromThen)) {
|
||||
return original[0] = 'POST_' + original[0];
|
||||
}
|
||||
};
|
||||
return this.scanTokens(function(token, i) {
|
||||
if (token[0] !== 'IF') {
|
||||
return 1;
|
||||
}
|
||||
original = token;
|
||||
this.detectEnd(i + 1, condition, action);
|
||||
return 1;
|
||||
});
|
||||
};
|
||||
|
||||
Rewriter.prototype.indentation = function(origin) {
|
||||
var indent, outdent;
|
||||
indent = ['INDENT', 2];
|
||||
outdent = ['OUTDENT', 2];
|
||||
if (origin) {
|
||||
indent.generated = outdent.generated = true;
|
||||
indent.origin = outdent.origin = origin;
|
||||
} else {
|
||||
indent.explicit = outdent.explicit = true;
|
||||
}
|
||||
return [indent, outdent];
|
||||
};
|
||||
|
||||
Rewriter.prototype.generate = generate;
|
||||
|
||||
Rewriter.prototype.tag = function(i) {
|
||||
var ref;
|
||||
return (ref = this.tokens[i]) != null ? ref[0] : void 0;
|
||||
};
|
||||
|
||||
return Rewriter;
|
||||
|
||||
})();
|
||||
|
||||
BALANCED_PAIRS = [['(', ')'], ['[', ']'], ['{', '}'], ['INDENT', 'OUTDENT'], ['CALL_START', 'CALL_END'], ['PARAM_START', 'PARAM_END'], ['INDEX_START', 'INDEX_END'], ['STRING_START', 'STRING_END'], ['REGEX_START', 'REGEX_END']];
|
||||
|
||||
exports.INVERSES = INVERSES = {};
|
||||
|
||||
EXPRESSION_START = [];
|
||||
|
||||
EXPRESSION_END = [];
|
||||
|
||||
for (k = 0, len = BALANCED_PAIRS.length; k < len; k++) {
|
||||
ref = BALANCED_PAIRS[k], left = ref[0], rite = ref[1];
|
||||
EXPRESSION_START.push(INVERSES[rite] = left);
|
||||
EXPRESSION_END.push(INVERSES[left] = rite);
|
||||
}
|
||||
|
||||
EXPRESSION_CLOSE = ['CATCH', 'THEN', 'ELSE', 'FINALLY'].concat(EXPRESSION_END);
|
||||
|
||||
IMPLICIT_FUNC = ['IDENTIFIER', 'PROPERTY', 'SUPER', ')', 'CALL_END', ']', 'INDEX_END', '@', 'THIS'];
|
||||
|
||||
IMPLICIT_CALL = ['IDENTIFIER', 'PROPERTY', 'NUMBER', 'INFINITY', 'NAN', 'STRING', 'STRING_START', 'REGEX', 'REGEX_START', 'JS', 'NEW', 'PARAM_START', 'CLASS', 'IF', 'TRY', 'SWITCH', 'THIS', 'UNDEFINED', 'NULL', 'BOOL', 'UNARY', 'YIELD', 'UNARY_MATH', 'SUPER', 'THROW', '@', '->', '=>', '[', '(', '{', '--', '++'];
|
||||
|
||||
IMPLICIT_UNSPACED_CALL = ['+', '-'];
|
||||
|
||||
IMPLICIT_END = ['POST_IF', 'FOR', 'WHILE', 'UNTIL', 'WHEN', 'BY', 'LOOP', 'TERMINATOR'];
|
||||
|
||||
SINGLE_LINERS = ['ELSE', '->', '=>', 'TRY', 'FINALLY', 'THEN'];
|
||||
|
||||
SINGLE_CLOSERS = ['TERMINATOR', 'CATCH', 'FINALLY', 'ELSE', 'OUTDENT', 'LEADING_WHEN'];
|
||||
|
||||
LINEBREAKS = ['TERMINATOR', 'INDENT', 'OUTDENT'];
|
||||
|
||||
CALL_CLOSERS = ['.', '?.', '::', '?::'];
|
||||
|
||||
}).call(this);
|
||||
@@ -1,161 +0,0 @@
|
||||
// Generated by CoffeeScript 1.12.5
|
||||
(function() {
|
||||
var LineMap, SourceMap;
|
||||
|
||||
LineMap = (function() {
|
||||
function LineMap(line1) {
|
||||
this.line = line1;
|
||||
this.columns = [];
|
||||
}
|
||||
|
||||
LineMap.prototype.add = function(column, arg, options) {
|
||||
var sourceColumn, sourceLine;
|
||||
sourceLine = arg[0], sourceColumn = arg[1];
|
||||
if (options == null) {
|
||||
options = {};
|
||||
}
|
||||
if (this.columns[column] && options.noReplace) {
|
||||
return;
|
||||
}
|
||||
return this.columns[column] = {
|
||||
line: this.line,
|
||||
column: column,
|
||||
sourceLine: sourceLine,
|
||||
sourceColumn: sourceColumn
|
||||
};
|
||||
};
|
||||
|
||||
LineMap.prototype.sourceLocation = function(column) {
|
||||
var mapping;
|
||||
while (!((mapping = this.columns[column]) || (column <= 0))) {
|
||||
column--;
|
||||
}
|
||||
return mapping && [mapping.sourceLine, mapping.sourceColumn];
|
||||
};
|
||||
|
||||
return LineMap;
|
||||
|
||||
})();
|
||||
|
||||
SourceMap = (function() {
|
||||
var BASE64_CHARS, VLQ_CONTINUATION_BIT, VLQ_SHIFT, VLQ_VALUE_MASK;
|
||||
|
||||
function SourceMap() {
|
||||
this.lines = [];
|
||||
}
|
||||
|
||||
SourceMap.prototype.add = function(sourceLocation, generatedLocation, options) {
|
||||
var base, column, line, lineMap;
|
||||
if (options == null) {
|
||||
options = {};
|
||||
}
|
||||
line = generatedLocation[0], column = generatedLocation[1];
|
||||
lineMap = ((base = this.lines)[line] || (base[line] = new LineMap(line)));
|
||||
return lineMap.add(column, sourceLocation, options);
|
||||
};
|
||||
|
||||
SourceMap.prototype.sourceLocation = function(arg) {
|
||||
var column, line, lineMap;
|
||||
line = arg[0], column = arg[1];
|
||||
while (!((lineMap = this.lines[line]) || (line <= 0))) {
|
||||
line--;
|
||||
}
|
||||
return lineMap && lineMap.sourceLocation(column);
|
||||
};
|
||||
|
||||
SourceMap.prototype.generate = function(options, code) {
|
||||
var buffer, i, j, lastColumn, lastSourceColumn, lastSourceLine, len, len1, lineMap, lineNumber, mapping, needComma, ref, ref1, v3, writingline;
|
||||
if (options == null) {
|
||||
options = {};
|
||||
}
|
||||
if (code == null) {
|
||||
code = null;
|
||||
}
|
||||
writingline = 0;
|
||||
lastColumn = 0;
|
||||
lastSourceLine = 0;
|
||||
lastSourceColumn = 0;
|
||||
needComma = false;
|
||||
buffer = "";
|
||||
ref = this.lines;
|
||||
for (lineNumber = i = 0, len = ref.length; i < len; lineNumber = ++i) {
|
||||
lineMap = ref[lineNumber];
|
||||
if (lineMap) {
|
||||
ref1 = lineMap.columns;
|
||||
for (j = 0, len1 = ref1.length; j < len1; j++) {
|
||||
mapping = ref1[j];
|
||||
if (!(mapping)) {
|
||||
continue;
|
||||
}
|
||||
while (writingline < mapping.line) {
|
||||
lastColumn = 0;
|
||||
needComma = false;
|
||||
buffer += ";";
|
||||
writingline++;
|
||||
}
|
||||
if (needComma) {
|
||||
buffer += ",";
|
||||
needComma = false;
|
||||
}
|
||||
buffer += this.encodeVlq(mapping.column - lastColumn);
|
||||
lastColumn = mapping.column;
|
||||
buffer += this.encodeVlq(0);
|
||||
buffer += this.encodeVlq(mapping.sourceLine - lastSourceLine);
|
||||
lastSourceLine = mapping.sourceLine;
|
||||
buffer += this.encodeVlq(mapping.sourceColumn - lastSourceColumn);
|
||||
lastSourceColumn = mapping.sourceColumn;
|
||||
needComma = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
v3 = {
|
||||
version: 3,
|
||||
file: options.generatedFile || '',
|
||||
sourceRoot: options.sourceRoot || '',
|
||||
sources: options.sourceFiles || [''],
|
||||
names: [],
|
||||
mappings: buffer
|
||||
};
|
||||
if (options.inlineMap) {
|
||||
v3.sourcesContent = [code];
|
||||
}
|
||||
return v3;
|
||||
};
|
||||
|
||||
VLQ_SHIFT = 5;
|
||||
|
||||
VLQ_CONTINUATION_BIT = 1 << VLQ_SHIFT;
|
||||
|
||||
VLQ_VALUE_MASK = VLQ_CONTINUATION_BIT - 1;
|
||||
|
||||
SourceMap.prototype.encodeVlq = function(value) {
|
||||
var answer, nextChunk, signBit, valueToEncode;
|
||||
answer = '';
|
||||
signBit = value < 0 ? 1 : 0;
|
||||
valueToEncode = (Math.abs(value) << 1) + signBit;
|
||||
while (valueToEncode || !answer) {
|
||||
nextChunk = valueToEncode & VLQ_VALUE_MASK;
|
||||
valueToEncode = valueToEncode >> VLQ_SHIFT;
|
||||
if (valueToEncode) {
|
||||
nextChunk |= VLQ_CONTINUATION_BIT;
|
||||
}
|
||||
answer += this.encodeBase64(nextChunk);
|
||||
}
|
||||
return answer;
|
||||
};
|
||||
|
||||
BASE64_CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
|
||||
|
||||
SourceMap.prototype.encodeBase64 = function(value) {
|
||||
return BASE64_CHARS[value] || (function() {
|
||||
throw new Error("Cannot Base64 encode value: " + value);
|
||||
})();
|
||||
};
|
||||
|
||||
return SourceMap;
|
||||
|
||||
})();
|
||||
|
||||
module.exports = SourceMap;
|
||||
|
||||
}).call(this);
|
||||
@@ -1,28 +1,22 @@
|
||||
// Generated by CoffeeScript 1.12.5
|
||||
// Generated by CoffeeScript 2.0.0-beta1
|
||||
(function() {
|
||||
var CoffeeScript, compile, runScripts,
|
||||
indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
|
||||
|
||||
CoffeeScript = require('./coffee-script');
|
||||
CoffeeScript = require('./coffeescript');
|
||||
|
||||
CoffeeScript.require = require;
|
||||
|
||||
compile = CoffeeScript.compile;
|
||||
|
||||
CoffeeScript["eval"] = function(code, options) {
|
||||
if (options == null) {
|
||||
options = {};
|
||||
}
|
||||
CoffeeScript["eval"] = function(code, options = {}) {
|
||||
if (options.bare == null) {
|
||||
options.bare = true;
|
||||
}
|
||||
return eval(compile(code, options));
|
||||
};
|
||||
|
||||
CoffeeScript.run = function(code, options) {
|
||||
if (options == null) {
|
||||
options = {};
|
||||
}
|
||||
CoffeeScript.run = function(code, options = {}) {
|
||||
options.bare = true;
|
||||
options.shiftLine = true;
|
||||
return Function(compile(code, options))();
|
||||
@@ -33,23 +27,14 @@
|
||||
}
|
||||
|
||||
if ((typeof btoa !== "undefined" && btoa !== null) && (typeof JSON !== "undefined" && JSON !== null)) {
|
||||
compile = function(code, options) {
|
||||
if (options == null) {
|
||||
options = {};
|
||||
}
|
||||
compile = function(code, options = {}) {
|
||||
options.inlineMap = true;
|
||||
return CoffeeScript.compile(code, options);
|
||||
};
|
||||
}
|
||||
|
||||
CoffeeScript.load = function(url, callback, options, hold) {
|
||||
CoffeeScript.load = function(url, callback, options = {}, hold = false) {
|
||||
var xhr;
|
||||
if (options == null) {
|
||||
options = {};
|
||||
}
|
||||
if (hold == null) {
|
||||
hold = false;
|
||||
}
|
||||
options.sourceFiles = [url];
|
||||
xhr = window.ActiveXObject ? new window.ActiveXObject('Microsoft.XMLHTTP') : new window.XMLHttpRequest();
|
||||
xhr.open('GET', url, true);
|
||||
@@ -62,10 +47,10 @@
|
||||
if ((ref = xhr.status) === 0 || ref === 200) {
|
||||
param = [xhr.responseText, options];
|
||||
if (!hold) {
|
||||
CoffeeScript.run.apply(CoffeeScript, param);
|
||||
CoffeeScript.run(...param);
|
||||
}
|
||||
} else {
|
||||
throw new Error("Could not load " + url);
|
||||
throw new Error(`Could not load ${url}`);
|
||||
}
|
||||
if (callback) {
|
||||
return callback(param);
|
||||
@@ -95,7 +80,7 @@
|
||||
var param;
|
||||
param = coffees[index];
|
||||
if (param instanceof Array) {
|
||||
CoffeeScript.run.apply(CoffeeScript, param);
|
||||
CoffeeScript.run(...param);
|
||||
index++;
|
||||
return execute();
|
||||
}
|
||||
@@ -107,11 +92,13 @@
|
||||
};
|
||||
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 = script.id && script.id !== '' ? script.id : `coffeescript${(i !== 0 ? i : '')}`;
|
||||
options.sourceFiles = ['embedded'];
|
||||
return coffees[i] = [script.innerHTML, options];
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
// Generated by CoffeeScript 1.12.5
|
||||
// Generated by CoffeeScript 2.0.0-beta1
|
||||
(function() {
|
||||
var CoffeeScript, cakefileDirectory, fatalError, fs, helpers, missingTask, oparse, options, optparse, path, printTasks, switches, tasks;
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
optparse = require('./optparse');
|
||||
|
||||
CoffeeScript = require('./coffee-script');
|
||||
CoffeeScript = require('./coffeescript');
|
||||
|
||||
CoffeeScript.register();
|
||||
|
||||
@@ -24,15 +24,10 @@
|
||||
|
||||
helpers.extend(global, {
|
||||
task: function(name, description, action) {
|
||||
var ref;
|
||||
if (!action) {
|
||||
ref = [description, action], action = ref[0], description = ref[1];
|
||||
[action, description] = [description, action];
|
||||
}
|
||||
return tasks[name] = {
|
||||
name: name,
|
||||
description: description,
|
||||
action: action
|
||||
};
|
||||
return tasks[name] = {name, description, action};
|
||||
},
|
||||
option: function(letter, flag, description) {
|
||||
return switches.push([letter, flag, description]);
|
||||
@@ -61,7 +56,7 @@
|
||||
options = oparse.parse(args);
|
||||
} catch (error) {
|
||||
e = error;
|
||||
return fatalError("" + e);
|
||||
return fatalError(`${e}`);
|
||||
}
|
||||
ref = options["arguments"];
|
||||
results = [];
|
||||
@@ -76,13 +71,13 @@
|
||||
var cakefilePath, desc, name, relative, spaces, task;
|
||||
relative = path.relative || path.resolve;
|
||||
cakefilePath = path.join(relative(__originalDirname, process.cwd()), 'Cakefile');
|
||||
console.log(cakefilePath + " defines the following tasks:\n");
|
||||
console.log(`${cakefilePath} defines the following tasks:\n`);
|
||||
for (name in tasks) {
|
||||
task = tasks[name];
|
||||
spaces = 20 - name.length;
|
||||
spaces = spaces > 0 ? Array(spaces + 1).join(' ') : '';
|
||||
desc = task.description ? "# " + task.description : '';
|
||||
console.log("cake " + name + spaces + " " + desc);
|
||||
desc = task.description ? `# ${task.description}` : '';
|
||||
console.log(`cake ${name}${spaces} ${desc}`);
|
||||
}
|
||||
if (switches.length) {
|
||||
return console.log(oparse.help());
|
||||
@@ -96,7 +91,7 @@
|
||||
};
|
||||
|
||||
missingTask = function(task) {
|
||||
return fatalError("No such task: " + task);
|
||||
return fatalError(`No such task: ${task}`);
|
||||
};
|
||||
|
||||
cakefileDirectory = function(dir) {
|
||||
@@ -108,7 +103,7 @@
|
||||
if (parent !== dir) {
|
||||
return cakefileDirectory(parent);
|
||||
}
|
||||
throw new Error("Cakefile not found in " + (process.cwd()));
|
||||
throw new Error(`Cakefile not found in ${process.cwd()}`);
|
||||
};
|
||||
|
||||
}).call(this);
|
||||
@@ -1,4 +1,4 @@
|
||||
// Generated by CoffeeScript 1.12.5
|
||||
// Generated by CoffeeScript 2.0.0-beta1
|
||||
(function() {
|
||||
var Lexer, SourceMap, base64encode, compile, ext, fn1, formatSourcePosition, fs, getSourceMap, helpers, i, len, lexer, packageJson, parser, path, ref, sourceMaps, sources, vm, withPrettyErrors,
|
||||
hasProp = {}.hasOwnProperty;
|
||||
@@ -9,9 +9,9 @@
|
||||
|
||||
path = require('path');
|
||||
|
||||
Lexer = require('./lexer').Lexer;
|
||||
({Lexer} = require('./lexer'));
|
||||
|
||||
parser = require('./parser').parser;
|
||||
({parser} = require('./parser'));
|
||||
|
||||
helpers = require('./helpers');
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
base64encode = function(src) {
|
||||
switch (false) {
|
||||
case typeof Buffer !== 'function':
|
||||
return new Buffer(src).toString('base64');
|
||||
return Buffer.from(src).toString('base64');
|
||||
case typeof btoa !== 'function':
|
||||
return btoa(encodeURIComponent(src).replace(/%([0-9A-F]{2})/g, function(match, p1) {
|
||||
return String.fromCharCode('0x' + p1);
|
||||
@@ -39,11 +39,8 @@
|
||||
};
|
||||
|
||||
withPrettyErrors = function(fn) {
|
||||
return function(code, options) {
|
||||
return function(code, options = {}) {
|
||||
var err;
|
||||
if (options == null) {
|
||||
options = {};
|
||||
}
|
||||
try {
|
||||
return fn.call(this, code, options);
|
||||
} catch (error) {
|
||||
@@ -62,7 +59,7 @@
|
||||
|
||||
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 = helpers.merge, extend = helpers.extend;
|
||||
({merge, extend} = helpers);
|
||||
options = extend({}, options);
|
||||
generateSourceMap = options.sourceMap || options.inlineMap || (options.filename == null);
|
||||
filename = options.filename || '<anonymous>';
|
||||
@@ -120,8 +117,8 @@
|
||||
js += fragment.code;
|
||||
}
|
||||
if (options.header) {
|
||||
header = "Generated by CoffeeScript " + this.VERSION;
|
||||
js = "// " + header + "\n" + js;
|
||||
header = `Generated by CoffeeScript ${this.VERSION}`;
|
||||
js = `// ${header}\n${js}`;
|
||||
}
|
||||
if (generateSourceMap) {
|
||||
v3SourceMap = map.generate(options, code);
|
||||
@@ -129,13 +126,13 @@
|
||||
}
|
||||
if (options.inlineMap) {
|
||||
encoded = base64encode(JSON.stringify(v3SourceMap));
|
||||
sourceMapDataURI = "//# sourceMappingURL=data:application/json;base64," + encoded;
|
||||
sourceURL = "//# sourceURL=" + ((ref1 = options.filename) != null ? ref1 : 'coffeescript');
|
||||
js = js + "\n" + sourceMapDataURI + "\n" + sourceURL;
|
||||
sourceMapDataURI = `//# sourceMappingURL=data:application/json;base64,${encoded}`;
|
||||
sourceURL = `//# sourceURL=${(ref1 = options.filename) != null ? ref1 : 'coffeescript'}`;
|
||||
js = `${js}\n${sourceMapDataURI}\n${sourceURL}`;
|
||||
}
|
||||
if (options.sourceMap) {
|
||||
return {
|
||||
js: js,
|
||||
js,
|
||||
sourceMap: map,
|
||||
v3SourceMap: JSON.stringify(v3SourceMap, null, 2)
|
||||
};
|
||||
@@ -156,11 +153,8 @@
|
||||
}
|
||||
});
|
||||
|
||||
exports.run = function(code, options) {
|
||||
exports.run = function(code, options = {}) {
|
||||
var answer, dir, mainModule, ref;
|
||||
if (options == null) {
|
||||
options = {};
|
||||
}
|
||||
mainModule = require.main;
|
||||
mainModule.filename = process.argv[1] = options.filename ? fs.realpathSync(options.filename) : '<anonymous>';
|
||||
mainModule.moduleCache && (mainModule.moduleCache = {});
|
||||
@@ -173,11 +167,8 @@
|
||||
return mainModule._compile(code, mainModule.filename);
|
||||
};
|
||||
|
||||
exports["eval"] = function(code, options) {
|
||||
exports["eval"] = function(code, options = {}) {
|
||||
var Module, _module, _require, createContext, i, isContext, js, k, len, o, r, ref, ref1, ref2, ref3, sandbox, v;
|
||||
if (options == null) {
|
||||
options = {};
|
||||
}
|
||||
if (!(code = code.trim())) {
|
||||
return;
|
||||
}
|
||||
@@ -248,7 +239,7 @@
|
||||
fn1 = function(ext) {
|
||||
var base;
|
||||
return (base = require.extensions)[ext] != null ? base[ext] : base[ext] = function() {
|
||||
throw new Error("Use CoffeeScript.register() or require the coffee-script/register module to require " + ext + " files.");
|
||||
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++) {
|
||||
@@ -257,21 +248,15 @@
|
||||
}
|
||||
}
|
||||
|
||||
exports._compileFile = function(filename, sourceMap, inlineMap) {
|
||||
exports._compileFile = function(filename, sourceMap = false, inlineMap = false) {
|
||||
var answer, err, raw, stripped;
|
||||
if (sourceMap == null) {
|
||||
sourceMap = false;
|
||||
}
|
||||
if (inlineMap == null) {
|
||||
inlineMap = false;
|
||||
}
|
||||
raw = fs.readFileSync(filename, 'utf8');
|
||||
stripped = raw.charCodeAt(0) === 0xFEFF ? raw.substring(1) : raw;
|
||||
try {
|
||||
answer = compile(stripped, {
|
||||
filename: filename,
|
||||
sourceMap: sourceMap,
|
||||
inlineMap: inlineMap,
|
||||
filename,
|
||||
sourceMap,
|
||||
inlineMap,
|
||||
sourceFiles: [filename],
|
||||
literate: helpers.isLiterate(filename)
|
||||
});
|
||||
@@ -289,7 +274,7 @@
|
||||
var tag, token;
|
||||
token = parser.tokens[this.pos++];
|
||||
if (token) {
|
||||
tag = token[0], this.yytext = token[1], this.yylloc = token[2];
|
||||
[tag, this.yytext, this.yylloc] = token;
|
||||
parser.errorToken = token.origin || token;
|
||||
this.yylineno = this.yylloc.first_line;
|
||||
} else {
|
||||
@@ -308,11 +293,10 @@
|
||||
|
||||
parser.yy = require('./nodes');
|
||||
|
||||
parser.yy.parseError = function(message, arg) {
|
||||
var errorLoc, errorTag, errorText, errorToken, token, tokens;
|
||||
token = arg.token;
|
||||
errorToken = parser.errorToken, tokens = parser.tokens;
|
||||
errorTag = errorToken[0], errorText = errorToken[1], errorLoc = errorToken[2];
|
||||
parser.yy.parseError = function(message, {token}) {
|
||||
var errorLoc, errorTag, errorText, errorToken, tokens;
|
||||
({errorToken, tokens} = parser);
|
||||
[errorTag, errorText, errorLoc] = errorToken;
|
||||
errorText = (function() {
|
||||
switch (false) {
|
||||
case errorToken !== tokens[tokens.length - 1]:
|
||||
@@ -325,7 +309,7 @@
|
||||
return helpers.nameWhitespaceCharacter(errorText);
|
||||
}
|
||||
})();
|
||||
return helpers.throwSyntaxError("unexpected " + errorText, errorLoc);
|
||||
return helpers.throwSyntaxError(`unexpected ${errorText}`, errorLoc);
|
||||
};
|
||||
|
||||
formatSourcePosition = function(frame, getSourceMapping) {
|
||||
@@ -338,7 +322,7 @@
|
||||
if (frame.isEval()) {
|
||||
filename = frame.getScriptNameOrSourceURL();
|
||||
if (!filename) {
|
||||
fileLocation = (frame.getEvalOrigin()) + ", ";
|
||||
fileLocation = `${frame.getEvalOrigin()}, `;
|
||||
}
|
||||
} else {
|
||||
filename = frame.getFileName();
|
||||
@@ -347,7 +331,7 @@
|
||||
line = frame.getLineNumber();
|
||||
column = frame.getColumnNumber();
|
||||
source = getSourceMapping(filename, line, column);
|
||||
fileLocation = source ? filename + ":" + source[0] + ":" + source[1] : filename + ":" + line + ":" + column;
|
||||
fileLocation = source ? `${filename}:${source[0]}:${source[1]}` : `${filename}:${line}:${column}`;
|
||||
}
|
||||
functionName = frame.getFunctionName();
|
||||
isConstructor = frame.isConstructor();
|
||||
@@ -358,19 +342,19 @@
|
||||
if (functionName) {
|
||||
tp = as = '';
|
||||
if (typeName && functionName.indexOf(typeName)) {
|
||||
tp = typeName + ".";
|
||||
tp = `${typeName}.`;
|
||||
}
|
||||
if (methodName && functionName.indexOf("." + methodName) !== functionName.length - methodName.length - 1) {
|
||||
as = " [as " + methodName + "]";
|
||||
if (methodName && functionName.indexOf(`.${methodName}`) !== functionName.length - methodName.length - 1) {
|
||||
as = ` [as ${methodName}]`;
|
||||
}
|
||||
return "" + tp + functionName + as + " (" + fileLocation + ")";
|
||||
return `${tp}${functionName}${as} (${fileLocation})`;
|
||||
} else {
|
||||
return typeName + "." + (methodName || '<anonymous>') + " (" + fileLocation + ")";
|
||||
return `${typeName}.${methodName || '<anonymous>'} (${fileLocation})`;
|
||||
}
|
||||
} else if (isConstructor) {
|
||||
return "new " + (functionName || '<anonymous>') + " (" + fileLocation + ")";
|
||||
return `new ${functionName || '<anonymous>'} (${fileLocation})`;
|
||||
} else if (functionName) {
|
||||
return functionName + " (" + fileLocation + ")";
|
||||
return `${functionName} (${fileLocation})`;
|
||||
} else {
|
||||
return fileLocation;
|
||||
}
|
||||
@@ -416,11 +400,11 @@
|
||||
if (frame.getFunction() === exports.run) {
|
||||
break;
|
||||
}
|
||||
results.push(" at " + (formatSourcePosition(frame, getSourceMapping)));
|
||||
results.push(` at ${formatSourcePosition(frame, getSourceMapping)}`);
|
||||
}
|
||||
return results;
|
||||
})();
|
||||
return (err.toString()) + "\n" + (frames.join('\n')) + "\n";
|
||||
return `${err.toString()}\n${frames.join('\n')}\n`;
|
||||
};
|
||||
|
||||
}).call(this);
|
||||
@@ -1,6 +1,6 @@
|
||||
// Generated by CoffeeScript 1.12.5
|
||||
// Generated by CoffeeScript 2.0.0-beta1
|
||||
(function() {
|
||||
var BANNER, CoffeeScript, EventEmitter, SWITCHES, compileJoin, compileOptions, compilePath, compileScript, compileStdio, exec, findDirectoryIndex, forkNode, fs, helpers, hidden, joinTimeout, makePrelude, mkdirp, notSources, optionParser, optparse, opts, outputPath, parseOptions, path, printLine, printTokens, printWarn, ref, removeSource, removeSourceDir, silentUnlink, sourceCode, sources, spawn, timeLog, usage, useWinPathSep, version, wait, watch, watchDir, watchedDirs, writeJs,
|
||||
var BANNER, CoffeeScript, EventEmitter, SWITCHES, compileJoin, compileOptions, compilePath, compileScript, compileStdio, exec, findDirectoryIndex, forkNode, fs, helpers, hidden, joinTimeout, makePrelude, mkdirp, notSources, optionParser, optparse, opts, outputPath, parseOptions, path, printLine, printTokens, printWarn, removeSource, removeSourceDir, silentUnlink, sourceCode, sources, spawn, timeLog, usage, useWinPathSep, version, wait, watch, watchDir, watchedDirs, writeJs,
|
||||
indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
|
||||
|
||||
fs = require('fs');
|
||||
@@ -11,11 +11,11 @@
|
||||
|
||||
optparse = require('./optparse');
|
||||
|
||||
CoffeeScript = require('./coffee-script');
|
||||
CoffeeScript = require('./coffeescript');
|
||||
|
||||
ref = require('child_process'), spawn = ref.spawn, exec = ref.exec;
|
||||
({spawn, exec} = require('child_process'));
|
||||
|
||||
EventEmitter = require('events').EventEmitter;
|
||||
({EventEmitter} = require('events'));
|
||||
|
||||
useWinPathSep = path.sep === '\\';
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
|
||||
BANNER = 'Usage: coffee [options] path/to/script.coffee -- [args]\n\nIf called without options, `coffee` will run your script.';
|
||||
|
||||
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 coffee-script'], ['-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 [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']];
|
||||
|
||||
opts = {};
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
optionParser = null;
|
||||
|
||||
exports.run = function() {
|
||||
var i, len, literals, ref1, replCliOpts, results, source;
|
||||
var i, len, literals, ref, replCliOpts, results, source;
|
||||
parseOptions();
|
||||
replCliOpts = {
|
||||
useGlobal: true
|
||||
@@ -90,10 +90,10 @@
|
||||
opts.join = path.resolve(opts.join);
|
||||
console.error('\nThe --join option is deprecated and will be removed in a future version.\n\nIf for some reason it\'s necessary to share local variables between files,\nreplace...\n\n $ coffee --compile --join bundle.js -- a.coffee b.coffee c.coffee\n\nwith...\n\n $ cat a.coffee b.coffee c.coffee | coffee --compile --stdio > bundle.js\n');
|
||||
}
|
||||
ref1 = opts["arguments"];
|
||||
ref = opts["arguments"];
|
||||
results = [];
|
||||
for (i = 0, len = ref1.length; i < len; i++) {
|
||||
source = ref1[i];
|
||||
for (i = 0, len = ref.length; i < len; i++) {
|
||||
source = ref[i];
|
||||
source = path.resolve(source);
|
||||
results.push(compilePath(source, true, source));
|
||||
}
|
||||
@@ -104,10 +104,10 @@
|
||||
return requires.map(function(module) {
|
||||
var _, match, name;
|
||||
if (match = module.match(/^(.*)=(.*)$/)) {
|
||||
_ = match[0], name = match[1], module = match[2];
|
||||
[_, name, module] = match;
|
||||
}
|
||||
name || (name = helpers.baseFileName(module, true, useWinPathSep));
|
||||
return name + " = require('" + module + "')";
|
||||
return `${name} = require('${module}')`;
|
||||
}).join(';');
|
||||
};
|
||||
|
||||
@@ -121,7 +121,7 @@
|
||||
} catch (error) {
|
||||
err = error;
|
||||
if (err.code === 'ENOENT') {
|
||||
console.error("File not found: " + source);
|
||||
console.error(`File not found: ${source}`);
|
||||
process.exit(1);
|
||||
}
|
||||
throw err;
|
||||
@@ -178,11 +178,11 @@
|
||||
};
|
||||
|
||||
findDirectoryIndex = function(source) {
|
||||
var err, ext, i, index, len, ref1;
|
||||
ref1 = CoffeeScript.FILE_EXTENSIONS;
|
||||
for (i = 0, len = ref1.length; i < len; i++) {
|
||||
ext = ref1[i];
|
||||
index = path.join(source, "index" + ext);
|
||||
var err, ext, i, index, len, ref;
|
||||
ref = CoffeeScript.FILE_EXTENSIONS;
|
||||
for (i = 0, len = ref.length; i < len; i++) {
|
||||
ext = ref[i];
|
||||
index = path.join(source, `index${ext}`);
|
||||
try {
|
||||
if ((fs.statSync(index)).isFile()) {
|
||||
return index;
|
||||
@@ -194,23 +194,16 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
console.error("Missing index.coffee or index.litcoffee in " + source);
|
||||
console.error(`Missing index.coffee or index.litcoffee in ${source}`);
|
||||
return process.exit(1);
|
||||
};
|
||||
|
||||
compileScript = function(file, input, base) {
|
||||
compileScript = function(file, input, base = null) {
|
||||
var compiled, err, message, o, options, t, task;
|
||||
if (base == null) {
|
||||
base = null;
|
||||
}
|
||||
o = opts;
|
||||
options = compileOptions(file, base);
|
||||
try {
|
||||
t = task = {
|
||||
file: file,
|
||||
input: input,
|
||||
options: options
|
||||
};
|
||||
t = task = {file, input, options};
|
||||
CoffeeScript.emit('compile', task);
|
||||
if (o.tokens) {
|
||||
return printTokens(CoffeeScript.tokens(t.input, t.options));
|
||||
@@ -248,7 +241,7 @@
|
||||
if (CoffeeScript.listeners('failure').length) {
|
||||
return;
|
||||
}
|
||||
message = (err != null ? err.stack : void 0) || ("" + err);
|
||||
message = (err != null ? err.stack : void 0) || `${err}`;
|
||||
if (o.watch) {
|
||||
return printLine(message + '\x07');
|
||||
} else {
|
||||
@@ -423,27 +416,24 @@
|
||||
if (!opts.join) {
|
||||
silentUnlink(outputPath(source, base));
|
||||
silentUnlink(outputPath(source, base, '.js.map'));
|
||||
return timeLog("removed " + source);
|
||||
return timeLog(`removed ${source}`);
|
||||
}
|
||||
};
|
||||
|
||||
silentUnlink = function(path) {
|
||||
var err, ref1;
|
||||
var err, ref;
|
||||
try {
|
||||
return fs.unlinkSync(path);
|
||||
} catch (error) {
|
||||
err = error;
|
||||
if ((ref1 = err.code) !== 'ENOENT' && ref1 !== 'EPERM') {
|
||||
if ((ref = err.code) !== 'ENOENT' && ref !== 'EPERM') {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
outputPath = function(source, base, extension) {
|
||||
outputPath = function(source, base, extension = ".js") {
|
||||
var basename, dir, srcDir;
|
||||
if (extension == null) {
|
||||
extension = ".js";
|
||||
}
|
||||
basename = helpers.baseFileName(source, true, useWinPathSep);
|
||||
srcDir = path.dirname(source);
|
||||
if (!opts.output) {
|
||||
@@ -458,7 +448,7 @@
|
||||
|
||||
mkdirp = function(dir, fn) {
|
||||
var mkdirs, mode;
|
||||
mode = 0x1ff & ~process.umask();
|
||||
mode = 0o777 & ~process.umask();
|
||||
return (mkdirs = function(p, fn) {
|
||||
return fs.exists(p, function(exists) {
|
||||
if (exists) {
|
||||
@@ -477,11 +467,8 @@
|
||||
})(dir, fn);
|
||||
};
|
||||
|
||||
writeJs = function(base, sourcePath, js, jsPath, generatedSourceMap) {
|
||||
writeJs = function(base, sourcePath, js, jsPath, generatedSourceMap = null) {
|
||||
var compile, jsDir, sourceMapPath;
|
||||
if (generatedSourceMap == null) {
|
||||
generatedSourceMap = null;
|
||||
}
|
||||
sourceMapPath = outputPath(sourcePath, base, ".js.map");
|
||||
jsDir = path.dirname(jsPath);
|
||||
compile = function() {
|
||||
@@ -490,21 +477,21 @@
|
||||
js = ' ';
|
||||
}
|
||||
if (generatedSourceMap) {
|
||||
js = js + "\n//# sourceMappingURL=" + (helpers.baseFileName(sourceMapPath, false, useWinPathSep)) + "\n";
|
||||
js = `${js}\n//# sourceMappingURL=${helpers.baseFileName(sourceMapPath, false, useWinPathSep)}\n`;
|
||||
}
|
||||
fs.writeFile(jsPath, js, function(err) {
|
||||
if (err) {
|
||||
printLine(err.message);
|
||||
return process.exit(1);
|
||||
} else if (opts.compile && opts.watch) {
|
||||
return timeLog("compiled " + sourcePath);
|
||||
return timeLog(`compiled ${sourcePath}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (generatedSourceMap) {
|
||||
return fs.writeFile(sourceMapPath, generatedSourceMap, function(err) {
|
||||
if (err) {
|
||||
printLine("Could not write source map: " + err.message);
|
||||
printLine(`Could not write source map: ${err.message}`);
|
||||
return process.exit(1);
|
||||
}
|
||||
});
|
||||
@@ -524,7 +511,7 @@
|
||||
};
|
||||
|
||||
timeLog = function(message) {
|
||||
return console.log(((new Date).toLocaleTimeString()) + " - " + message);
|
||||
return console.log(`${(new Date).toLocaleTimeString()} - ${message}`);
|
||||
};
|
||||
|
||||
printTokens = function(tokens) {
|
||||
@@ -536,7 +523,7 @@
|
||||
token = tokens[i];
|
||||
tag = token[0];
|
||||
value = token[1].toString().replace(/\n/, '\\n');
|
||||
results.push("[" + tag + " " + value + "]");
|
||||
results.push(`[${tag} ${value}]`);
|
||||
}
|
||||
return results;
|
||||
})();
|
||||
@@ -555,7 +542,7 @@
|
||||
compileOptions = function(filename, base) {
|
||||
var answer, cwd, jsDir, jsPath;
|
||||
answer = {
|
||||
filename: filename,
|
||||
filename,
|
||||
literate: opts.literate || helpers.isLiterate(filename),
|
||||
bare: opts.bare,
|
||||
header: opts.compile && !opts['no-header'],
|
||||
@@ -568,7 +555,7 @@
|
||||
jsPath = outputPath(filename, base);
|
||||
jsDir = path.dirname(jsPath);
|
||||
answer = helpers.merge(answer, {
|
||||
jsPath: jsPath,
|
||||
jsPath,
|
||||
sourceRoot: path.relative(jsDir, cwd),
|
||||
sourceFiles: [path.relative(cwd, filename)],
|
||||
generatedFile: helpers.baseFileName(jsPath, false, useWinPathSep)
|
||||
@@ -604,7 +591,7 @@
|
||||
};
|
||||
|
||||
version = function() {
|
||||
return printLine("CoffeeScript version " + CoffeeScript.VERSION);
|
||||
return printLine(`CoffeeScript version ${CoffeeScript.VERSION}`);
|
||||
};
|
||||
|
||||
}).call(this);
|
||||
@@ -1,8 +1,8 @@
|
||||
// Generated by CoffeeScript 1.12.5
|
||||
// Generated by CoffeeScript 2.0.0-beta1
|
||||
(function() {
|
||||
var Parser, alt, alternatives, grammar, name, o, operators, token, tokens, unwrap;
|
||||
|
||||
Parser = require('jison').Parser;
|
||||
({Parser} = require('jison'));
|
||||
|
||||
unwrap = /^function\s*\(\)\s*\{\s*return\s*([\s\S]*);\s*\}/;
|
||||
|
||||
@@ -13,19 +13,19 @@
|
||||
if (!action) {
|
||||
return [patternString, '$$ = $1;', options];
|
||||
}
|
||||
action = (match = unwrap.exec(action)) ? match[1] : "(" + action + "())";
|
||||
action = (match = unwrap.exec(action)) ? match[1] : `(${action}())`;
|
||||
action = action.replace(/\bnew /g, '$&yy.');
|
||||
action = action.replace(/\b(?:Block\.wrap|extend)\b/g, 'yy.$&');
|
||||
addLocationDataFn = function(first, last) {
|
||||
if (!last) {
|
||||
return "yy.addLocationDataFn(@" + first + ")";
|
||||
return `yy.addLocationDataFn(@${first})`;
|
||||
} else {
|
||||
return "yy.addLocationDataFn(@" + first + ", @" + last + ")";
|
||||
return `yy.addLocationDataFn(@${first}, @${last})`;
|
||||
}
|
||||
};
|
||||
action = action.replace(/LOC\(([0-9]*)\)/g, addLocationDataFn('$1'));
|
||||
action = action.replace(/LOC\(([0-9]*),\s*([0-9]*)\)/g, addLocationDataFn('$1', '$2'));
|
||||
return [patternString, "$$ = " + (addLocationDataFn(1, patternCount)) + "(" + action + ");", options];
|
||||
return [patternString, `$$ = ${addLocationDataFn(1, patternCount)}(${action});`, options];
|
||||
};
|
||||
|
||||
grammar = {
|
||||
@@ -41,7 +41,8 @@
|
||||
return $1.push($3);
|
||||
}), o('Body TERMINATOR')
|
||||
],
|
||||
Line: [o('Expression'), o('Statement'), o('YieldReturn')],
|
||||
Line: [o('Expression'), o('Statement'), o('FuncDirective')],
|
||||
FuncDirective: [o('YieldReturn'), o('AwaitReturn')],
|
||||
Statement: [
|
||||
o('Return'), o('Comment'), o('STATEMENT', function() {
|
||||
return new StatementLiteral($1);
|
||||
@@ -154,6 +155,13 @@
|
||||
return new YieldReturn;
|
||||
})
|
||||
],
|
||||
AwaitReturn: [
|
||||
o('AWAIT RETURN Expression', function() {
|
||||
return new AwaitReturn($3);
|
||||
}), o('AWAIT RETURN', function() {
|
||||
return new AwaitReturn;
|
||||
})
|
||||
],
|
||||
Comment: [
|
||||
o('HERECOMMENT', function() {
|
||||
return new Comment($1);
|
||||
@@ -227,7 +235,14 @@
|
||||
return new Value($1);
|
||||
}), o('Range', function() {
|
||||
return new Value($1);
|
||||
}), o('This')
|
||||
}), o('This'), o('Super')
|
||||
],
|
||||
Super: [
|
||||
o('SUPER . Property', function() {
|
||||
return new Super(LOC(3)(new Access($3)));
|
||||
}), o('SUPER INDEX_START Expression INDEX_END', function() {
|
||||
return new Super(LOC(3)(new Index($3)));
|
||||
})
|
||||
],
|
||||
Accessor: [
|
||||
o('. Property', function() {
|
||||
@@ -406,13 +421,8 @@
|
||||
return new Call($1, $3, $2);
|
||||
}), o('Invocation OptFuncExist Arguments', function() {
|
||||
return new Call($1, $3, $2);
|
||||
}), o('Super')
|
||||
],
|
||||
Super: [
|
||||
o('SUPER', function() {
|
||||
return new SuperCall;
|
||||
}), o('SUPER Arguments', function() {
|
||||
return new SuperCall($2);
|
||||
}), o('SUPER OptFuncExist Arguments', function() {
|
||||
return new SuperCall(LOC(1)(new Super), $3, $2);
|
||||
})
|
||||
],
|
||||
OptFuncExist: [
|
||||
@@ -725,6 +735,8 @@
|
||||
return new Op('+', $2);
|
||||
}), {
|
||||
prec: 'UNARY_MATH'
|
||||
}), o('AWAIT Expression', function() {
|
||||
return new Op($1, $2);
|
||||
}), o('-- SimpleAssignable', function() {
|
||||
return new Op('--', $2);
|
||||
}), o('++ SimpleAssignable', function() {
|
||||
@@ -777,7 +789,7 @@
|
||||
]
|
||||
};
|
||||
|
||||
operators = [['left', '.', '?.', '::', '?::'], ['left', 'CALL_START', 'CALL_END'], ['nonassoc', '++', '--'], ['left', '?'], ['right', 'UNARY'], ['right', '**'], ['right', 'UNARY_MATH'], ['left', 'MATH'], ['left', '+', '-'], ['left', 'SHIFT'], ['left', 'RELATION'], ['left', 'COMPARE'], ['left', '&'], ['left', '^'], ['left', '|'], ['left', '&&'], ['left', '||'], ['left', 'BIN?'], ['nonassoc', 'INDENT', 'OUTDENT'], ['right', 'YIELD'], ['right', '=', ':', 'COMPOUND_ASSIGN', 'RETURN', 'THROW', 'EXTENDS'], ['right', 'FORIN', 'FOROF', 'FORFROM', 'BY', 'WHEN'], ['right', 'IF', 'ELSE', 'FOR', 'WHILE', 'UNTIL', 'LOOP', 'SUPER', 'CLASS', 'IMPORT', 'EXPORT'], ['left', 'POST_IF']];
|
||||
operators = [['left', '.', '?.', '::', '?::'], ['left', 'CALL_START', 'CALL_END'], ['nonassoc', '++', '--'], ['left', '?'], ['right', 'UNARY'], ['right', 'AWAIT'], ['right', '**'], ['right', 'UNARY_MATH'], ['left', 'MATH'], ['left', '+', '-'], ['left', 'SHIFT'], ['left', 'RELATION'], ['left', 'COMPARE'], ['left', '&'], ['left', '^'], ['left', '|'], ['left', '&&'], ['left', '||'], ['left', 'BIN?'], ['nonassoc', 'INDENT', 'OUTDENT'], ['right', 'YIELD'], ['right', '=', ':', 'COMPOUND_ASSIGN', 'RETURN', 'THROW', 'EXTENDS'], ['right', 'FORIN', 'FOROF', 'FORFROM', 'BY', 'WHEN'], ['right', 'IF', 'ELSE', 'FOR', 'WHILE', 'UNTIL', 'LOOP', 'SUPER', 'CLASS', 'IMPORT', 'EXPORT'], ['left', 'POST_IF']];
|
||||
|
||||
tokens = [];
|
||||
|
||||
@@ -796,7 +808,7 @@
|
||||
}
|
||||
}
|
||||
if (name === 'Root') {
|
||||
alt[1] = "return " + alt[1];
|
||||
alt[1] = `return ${alt[1]}`;
|
||||
}
|
||||
results.push(alt);
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
// Generated by CoffeeScript 1.12.5
|
||||
// Generated by CoffeeScript 2.0.0-beta1
|
||||
(function() {
|
||||
var buildLocationData, extend, flatten, ref, repeat, syntaxErrorToString;
|
||||
var buildLocationData, extend, flatten, md, ref, repeat, syntaxErrorToString;
|
||||
|
||||
md = require('markdown-it')();
|
||||
|
||||
exports.starts = function(string, literal, start) {
|
||||
return literal === string.substr(start, literal.length);
|
||||
@@ -26,10 +28,10 @@
|
||||
};
|
||||
|
||||
exports.compact = function(array) {
|
||||
var i, item, len1, results;
|
||||
var item, j, len1, results;
|
||||
results = [];
|
||||
for (i = 0, len1 = array.length; i < len1; i++) {
|
||||
item = array[i];
|
||||
for (j = 0, len1 = array.length; j < len1; j++) {
|
||||
item = array[j];
|
||||
if (item) {
|
||||
results.push(item);
|
||||
}
|
||||
@@ -63,10 +65,10 @@
|
||||
};
|
||||
|
||||
exports.flatten = flatten = function(array) {
|
||||
var element, flattened, i, len1;
|
||||
var element, flattened, j, len1;
|
||||
flattened = [];
|
||||
for (i = 0, len1 = array.length; i < len1; i++) {
|
||||
element = array[i];
|
||||
for (j = 0, len1 = array.length; j < len1; j++) {
|
||||
element = array[j];
|
||||
if ('[object Array]' === Object.prototype.toString.call(element)) {
|
||||
flattened = flattened.concat(flatten(element));
|
||||
} else {
|
||||
@@ -84,10 +86,10 @@
|
||||
};
|
||||
|
||||
exports.some = (ref = Array.prototype.some) != null ? ref : function(fn) {
|
||||
var e, i, len1, ref1;
|
||||
var e, j, len1, ref1;
|
||||
ref1 = this;
|
||||
for (i = 0, len1 = ref1.length; i < len1; i++) {
|
||||
e = ref1[i];
|
||||
for (j = 0, len1 = ref1.length; j < len1; j++) {
|
||||
e = ref1[j];
|
||||
if (fn(e)) {
|
||||
return true;
|
||||
}
|
||||
@@ -96,25 +98,23 @@
|
||||
};
|
||||
|
||||
exports.invertLiterate = function(code) {
|
||||
var line, lines, maybe_code;
|
||||
maybe_code = true;
|
||||
lines = (function() {
|
||||
var i, len1, ref1, results;
|
||||
ref1 = code.split('\n');
|
||||
results = [];
|
||||
for (i = 0, len1 = ref1.length; i < len1; i++) {
|
||||
line = ref1[i];
|
||||
if (maybe_code && /^([ ]{4}|[ ]{0,3}\t)/.test(line)) {
|
||||
results.push(line);
|
||||
} else if (maybe_code = /^\s*$/.test(line)) {
|
||||
results.push(line);
|
||||
} else {
|
||||
results.push('# ' + line);
|
||||
var out;
|
||||
out = [];
|
||||
md.renderer.rules = {
|
||||
code_block: function(tokens, idx, options, env, slf) {
|
||||
var i, j, len1, line, lines, results, startLine;
|
||||
startLine = tokens[idx].map[0];
|
||||
lines = tokens[idx].content.split('\n');
|
||||
results = [];
|
||||
for (i = j = 0, len1 = lines.length; j < len1; i = ++j) {
|
||||
line = lines[i];
|
||||
results.push(out[startLine + i] = line);
|
||||
}
|
||||
return results;
|
||||
}
|
||||
return results;
|
||||
})();
|
||||
return lines.join('\n');
|
||||
};
|
||||
md.render(code);
|
||||
return out.join('\n');
|
||||
};
|
||||
|
||||
buildLocationData = function(first, last) {
|
||||
@@ -147,20 +147,14 @@
|
||||
locationData = obj;
|
||||
}
|
||||
if (locationData) {
|
||||
return ((locationData.first_line + 1) + ":" + (locationData.first_column + 1) + "-") + ((locationData.last_line + 1) + ":" + (locationData.last_column + 1));
|
||||
return `${locationData.first_line + 1}:${locationData.first_column + 1}-` + `${locationData.last_line + 1}:${locationData.last_column + 1}`;
|
||||
} else {
|
||||
return "No location data";
|
||||
}
|
||||
};
|
||||
|
||||
exports.baseFileName = function(file, stripExt, useWinPathSep) {
|
||||
exports.baseFileName = function(file, stripExt = false, useWinPathSep = false) {
|
||||
var parts, pathSep;
|
||||
if (stripExt == null) {
|
||||
stripExt = false;
|
||||
}
|
||||
if (useWinPathSep == null) {
|
||||
useWinPathSep = false;
|
||||
}
|
||||
pathSep = useWinPathSep ? /\\|\// : /\//;
|
||||
parts = file.split(pathSep);
|
||||
file = parts[parts.length - 1];
|
||||
@@ -202,11 +196,11 @@
|
||||
};
|
||||
|
||||
syntaxErrorToString = function() {
|
||||
var codeLine, colorize, colorsEnabled, end, filename, first_column, first_line, last_column, last_line, marker, ref1, ref2, ref3, ref4, start;
|
||||
var codeLine, colorize, colorsEnabled, end, filename, first_column, first_line, last_column, last_line, marker, ref1, ref2, ref3, start;
|
||||
if (!(this.code && this.location)) {
|
||||
return Error.prototype.toString.call(this);
|
||||
}
|
||||
ref1 = this.location, first_line = ref1.first_line, first_column = ref1.first_column, last_line = ref1.last_line, last_column = ref1.last_column;
|
||||
({first_line, first_column, last_line, last_column} = this.location);
|
||||
if (last_line == null) {
|
||||
last_line = first_line;
|
||||
}
|
||||
@@ -219,16 +213,16 @@
|
||||
end = first_line === last_line ? last_column + 1 : codeLine.length;
|
||||
marker = codeLine.slice(0, start).replace(/[^\s]/g, ' ') + repeat('^', end - start);
|
||||
if (typeof process !== "undefined" && process !== null) {
|
||||
colorsEnabled = ((ref2 = process.stdout) != null ? ref2.isTTY : void 0) && !((ref3 = process.env) != null ? ref3.NODE_DISABLE_COLORS : void 0);
|
||||
colorsEnabled = ((ref1 = process.stdout) != null ? ref1.isTTY : void 0) && !((ref2 = process.env) != null ? ref2.NODE_DISABLE_COLORS : void 0);
|
||||
}
|
||||
if ((ref4 = this.colorful) != null ? ref4 : colorsEnabled) {
|
||||
if ((ref3 = this.colorful) != null ? ref3 : colorsEnabled) {
|
||||
colorize = function(str) {
|
||||
return "\x1B[1;31m" + str + "\x1B[0m";
|
||||
return `\x1B[1;31m${str}\x1B[0m`;
|
||||
};
|
||||
codeLine = codeLine.slice(0, start) + colorize(codeLine.slice(start, end)) + codeLine.slice(end);
|
||||
marker = colorize(marker);
|
||||
}
|
||||
return filename + ":" + (first_line + 1) + ":" + (first_column + 1) + ": error: " + this.message + "\n" + codeLine + "\n" + marker;
|
||||
return `${filename}:${first_line + 1}:${first_column + 1}: error: ${this.message}\n${codeLine}\n${marker}`;
|
||||
};
|
||||
|
||||
exports.nameWhitespaceCharacter = function(string) {
|
||||
@@ -1,8 +1,8 @@
|
||||
// Generated by CoffeeScript 1.12.5
|
||||
// Generated by CoffeeScript 2.0.0-beta1
|
||||
(function() {
|
||||
var key, ref, val;
|
||||
|
||||
ref = require('./coffee-script');
|
||||
ref = require('./coffeescript');
|
||||
for (key in ref) {
|
||||
val = ref[key];
|
||||
exports[key] = val;
|
||||
@@ -1,27 +1,22 @@
|
||||
// Generated by CoffeeScript 1.12.5
|
||||
// Generated by CoffeeScript 2.0.0-beta1
|
||||
(function() {
|
||||
var BOM, BOOL, CALLABLE, CODE, COFFEE_ALIASES, COFFEE_ALIAS_MAP, COFFEE_KEYWORDS, COMMENT, COMPARE, COMPOUND_ASSIGN, HERECOMMENT_ILLEGAL, HEREDOC_DOUBLE, HEREDOC_INDENT, HEREDOC_SINGLE, HEREGEX, HEREGEX_OMIT, HERE_JSTOKEN, IDENTIFIER, INDENTABLE_CLOSERS, INDEXABLE, 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, VALID_FLAGS, WHITESPACE, compact, count, invertLiterate, isForFrom, isUnassignable, key, locationDataToString, ref, ref1, repeat, starts, throwSyntaxError,
|
||||
indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; },
|
||||
slice = [].slice;
|
||||
var BOM, BOOL, CALLABLE, CODE, COFFEE_ALIASES, COFFEE_ALIAS_MAP, COFFEE_KEYWORDS, COMMENT, COMPARE, COMPOUND_ASSIGN, HERECOMMENT_ILLEGAL, HEREDOC_DOUBLE, HEREDOC_INDENT, HEREDOC_SINGLE, HEREGEX, HEREGEX_OMIT, HERE_JSTOKEN, IDENTIFIER, INDENTABLE_CLOSERS, INDEXABLE, 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, VALID_FLAGS, WHITESPACE, compact, count, invertLiterate, isForFrom, isUnassignable, key, locationDataToString, repeat, starts, throwSyntaxError,
|
||||
indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
|
||||
|
||||
ref = require('./rewriter'), Rewriter = ref.Rewriter, INVERSES = ref.INVERSES;
|
||||
({Rewriter, INVERSES} = require('./rewriter'));
|
||||
|
||||
ref1 = require('./helpers'), count = ref1.count, starts = ref1.starts, compact = ref1.compact, repeat = ref1.repeat, invertLiterate = ref1.invertLiterate, locationDataToString = ref1.locationDataToString, throwSyntaxError = ref1.throwSyntaxError;
|
||||
({count, starts, compact, repeat, invertLiterate, locationDataToString, throwSyntaxError} = require('./helpers'));
|
||||
|
||||
exports.Lexer = Lexer = (function() {
|
||||
function Lexer() {}
|
||||
|
||||
Lexer.prototype.tokenize = function(code, opts) {
|
||||
var consumed, end, i, ref2;
|
||||
if (opts == null) {
|
||||
opts = {};
|
||||
}
|
||||
exports.Lexer = Lexer = class Lexer {
|
||||
tokenize(code, opts = {}) {
|
||||
var consumed, end, i;
|
||||
this.literate = opts.literate;
|
||||
this.indent = 0;
|
||||
this.baseIndent = 0;
|
||||
this.indebt = 0;
|
||||
this.outdebt = 0;
|
||||
this.indents = [];
|
||||
this.indentLiteral = '';
|
||||
this.ends = [];
|
||||
this.tokens = [];
|
||||
this.seenFor = false;
|
||||
@@ -35,7 +30,7 @@
|
||||
i = 0;
|
||||
while (this.chunk = code.slice(i)) {
|
||||
consumed = this.identifierToken() || this.commentToken() || this.whitespaceToken() || this.lineToken() || this.stringToken() || this.numberToken() || this.regexToken() || this.jsToken() || this.literalToken();
|
||||
ref2 = this.getLineAndColumnFromChunk(consumed), this.chunkLine = ref2[0], this.chunkColumn = ref2[1];
|
||||
[this.chunkLine, this.chunkColumn] = this.getLineAndColumnFromChunk(consumed);
|
||||
i += consumed;
|
||||
if (opts.untilBalanced && this.ends.length === 0) {
|
||||
return {
|
||||
@@ -46,35 +41,35 @@
|
||||
}
|
||||
this.closeIndentation();
|
||||
if (end = this.ends.pop()) {
|
||||
this.error("missing " + end.tag, end.origin[2]);
|
||||
this.error(`missing ${end.tag}`, end.origin[2]);
|
||||
}
|
||||
if (opts.rewrite === false) {
|
||||
return this.tokens;
|
||||
}
|
||||
return (new Rewriter).rewrite(this.tokens);
|
||||
};
|
||||
}
|
||||
|
||||
Lexer.prototype.clean = function(code) {
|
||||
clean(code) {
|
||||
if (code.charCodeAt(0) === BOM) {
|
||||
code = code.slice(1);
|
||||
}
|
||||
code = code.replace(/\r/g, '').replace(TRAILING_SPACES, '');
|
||||
if (WHITESPACE.test(code)) {
|
||||
code = "\n" + code;
|
||||
code = `\n${code}`;
|
||||
this.chunkLine--;
|
||||
}
|
||||
if (this.literate) {
|
||||
code = invertLiterate(code);
|
||||
}
|
||||
return code;
|
||||
};
|
||||
}
|
||||
|
||||
Lexer.prototype.identifierToken = function() {
|
||||
var alias, colon, colonOffset, id, idLength, input, match, poppedToken, prev, ref2, ref3, ref4, ref5, ref6, ref7, ref8, ref9, tag, tagToken;
|
||||
identifierToken() {
|
||||
var alias, colon, colonOffset, id, idLength, input, match, poppedToken, prev, prevprev, ref, ref1, ref2, ref3, ref4, ref5, ref6, ref7, tag, tagToken;
|
||||
if (!(match = IDENTIFIER.exec(this.chunk))) {
|
||||
return 0;
|
||||
}
|
||||
input = match[0], id = match[1], colon = match[2];
|
||||
[input, id, colon] = match;
|
||||
idLength = id.length;
|
||||
poppedToken = void 0;
|
||||
if (id === 'own' && this.tag() === 'FOR') {
|
||||
@@ -88,27 +83,27 @@
|
||||
if (id === 'as' && this.seenImport) {
|
||||
if (this.value() === '*') {
|
||||
this.tokens[this.tokens.length - 1][0] = 'IMPORT_ALL';
|
||||
} else if (ref2 = this.value(), indexOf.call(COFFEE_KEYWORDS, ref2) >= 0) {
|
||||
} else if (ref = this.value(), indexOf.call(COFFEE_KEYWORDS, ref) >= 0) {
|
||||
this.tokens[this.tokens.length - 1][0] = 'IDENTIFIER';
|
||||
}
|
||||
if ((ref3 = this.tag()) === 'DEFAULT' || ref3 === 'IMPORT_ALL' || ref3 === 'IDENTIFIER') {
|
||||
if ((ref1 = this.tag()) === 'DEFAULT' || ref1 === 'IMPORT_ALL' || ref1 === 'IDENTIFIER') {
|
||||
this.token('AS', id);
|
||||
return id.length;
|
||||
}
|
||||
}
|
||||
if (id === 'as' && this.seenExport && ((ref4 = this.tag()) === 'IDENTIFIER' || ref4 === 'DEFAULT')) {
|
||||
if (id === 'as' && this.seenExport && ((ref2 = this.tag()) === 'IDENTIFIER' || ref2 === 'DEFAULT')) {
|
||||
this.token('AS', id);
|
||||
return id.length;
|
||||
}
|
||||
if (id === 'default' && this.seenExport && ((ref5 = this.tag()) === 'EXPORT' || ref5 === 'AS')) {
|
||||
if (id === 'default' && this.seenExport && ((ref3 = this.tag()) === 'EXPORT' || ref3 === 'AS')) {
|
||||
this.token('DEFAULT', id);
|
||||
return id.length;
|
||||
}
|
||||
ref6 = this.tokens, prev = ref6[ref6.length - 1];
|
||||
tag = colon || (prev != null) && (((ref7 = prev[0]) === '.' || ref7 === '?.' || ref7 === '::' || ref7 === '?::') || !prev.spaced && prev[0] === '@') ? 'PROPERTY' : 'IDENTIFIER';
|
||||
prev = this.prev();
|
||||
tag = colon || (prev != null) && (((ref4 = prev[0]) === '.' || ref4 === '?.' || ref4 === '::' || ref4 === '?::') || !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' && (ref8 = this.tag(), indexOf.call(LINE_BREAK, ref8) >= 0)) {
|
||||
if (tag === 'WHEN' && (ref5 = this.tag(), indexOf.call(LINE_BREAK, ref5) >= 0)) {
|
||||
tag = 'LEADING_WHEN';
|
||||
} else if (tag === 'FOR') {
|
||||
this.seenFor = true;
|
||||
@@ -135,9 +130,18 @@
|
||||
} else if (tag === 'IDENTIFIER' && this.seenFor && id === 'from' && isForFrom(prev)) {
|
||||
tag = 'FORFROM';
|
||||
this.seenFor = false;
|
||||
} else if (tag === 'PROPERTY' && prev) {
|
||||
if (prev.spaced && (ref6 = prev[0], indexOf.call(CALLABLE, ref6) >= 0) && /^[gs]et$/.test(prev[1])) {
|
||||
this.error(`'${prev[1]}' cannot be used as a keyword, or as a function call without parentheses`, prev[2]);
|
||||
} else {
|
||||
prevprev = this.tokens[this.tokens.length - 2];
|
||||
if (((ref7 = prev[0]) === '@' || ref7 === 'THIS') && prevprev && prevprev.spaced && /^[gs]et$/.test(prevprev[1])) {
|
||||
this.error(`'${prevprev[1]}' cannot be used as a keyword, or as a function call without parentheses`, prevprev[2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (tag === 'IDENTIFIER' && indexOf.call(RESERVED, id) >= 0) {
|
||||
this.error("reserved word '" + id + "'", {
|
||||
this.error(`reserved word '${id}'`, {
|
||||
length: id.length
|
||||
});
|
||||
}
|
||||
@@ -173,17 +177,17 @@
|
||||
tagToken.origin = [tag, alias, tagToken[2]];
|
||||
}
|
||||
if (poppedToken) {
|
||||
ref9 = [poppedToken[2].first_line, poppedToken[2].first_column], tagToken[2].first_line = ref9[0], tagToken[2].first_column = ref9[1];
|
||||
[tagToken[2].first_line, tagToken[2].first_column] = [poppedToken[2].first_line, poppedToken[2].first_column];
|
||||
}
|
||||
if (colon) {
|
||||
colonOffset = input.lastIndexOf(':');
|
||||
this.token(':', ':', colonOffset, colon.length);
|
||||
}
|
||||
return input.length;
|
||||
};
|
||||
}
|
||||
|
||||
Lexer.prototype.numberToken = function() {
|
||||
var base, lexedLength, match, number, numberValue, ref2, tag;
|
||||
numberToken() {
|
||||
var base, lexedLength, match, number, numberValue, tag;
|
||||
if (!(match = NUMBER.exec(this.chunk))) {
|
||||
return 0;
|
||||
}
|
||||
@@ -191,22 +195,22 @@
|
||||
lexedLength = number.length;
|
||||
switch (false) {
|
||||
case !/^0[BOX]/.test(number):
|
||||
this.error("radix prefix in '" + number + "' must be lowercase", {
|
||||
this.error(`radix prefix in '${number}' must be lowercase`, {
|
||||
offset: 1
|
||||
});
|
||||
break;
|
||||
case !/^(?!0x).*E/.test(number):
|
||||
this.error("exponential notation in '" + number + "' must be indicated with a lowercase 'e'", {
|
||||
this.error(`exponential notation in '${number}' must be indicated with a lowercase 'e'`, {
|
||||
offset: number.indexOf('E')
|
||||
});
|
||||
break;
|
||||
case !/^0\d*[89]/.test(number):
|
||||
this.error("decimal literal '" + number + "' must not be prefixed with '0'", {
|
||||
this.error(`decimal literal '${number}' must not be prefixed with '0'`, {
|
||||
length: lexedLength
|
||||
});
|
||||
break;
|
||||
case !/^0\d+/.test(number):
|
||||
this.error("octal literal '" + number + "' must be prefixed with '0o'", {
|
||||
this.error(`octal literal '${number}' must be prefixed with '0o'`, {
|
||||
length: lexedLength
|
||||
});
|
||||
}
|
||||
@@ -223,22 +227,20 @@
|
||||
}
|
||||
})();
|
||||
numberValue = base != null ? parseInt(number.slice(2), base) : parseFloat(number);
|
||||
if ((ref2 = number.charAt(1)) === 'b' || ref2 === 'o') {
|
||||
number = "0x" + (numberValue.toString(16));
|
||||
}
|
||||
tag = numberValue === 2e308 ? 'INFINITY' : 'NUMBER';
|
||||
this.token(tag, number, 0, lexedLength);
|
||||
return lexedLength;
|
||||
};
|
||||
}
|
||||
|
||||
Lexer.prototype.stringToken = function() {
|
||||
var $, attempt, delimiter, doc, end, heredoc, i, indent, indentRegex, match, quote, ref2, ref3, regex, token, tokens;
|
||||
quote = (STRING_START.exec(this.chunk) || [])[0];
|
||||
stringToken() {
|
||||
var $, attempt, delimiter, doc, end, heredoc, i, indent, indentRegex, match, prev, quote, ref, regex, token, tokens;
|
||||
[quote] = STRING_START.exec(this.chunk) || [];
|
||||
if (!quote) {
|
||||
return 0;
|
||||
}
|
||||
if (this.tokens.length && this.value() === 'from' && (this.seenImport || this.seenExport)) {
|
||||
this.tokens[this.tokens.length - 1][0] = 'FROM';
|
||||
prev = this.prev();
|
||||
if (prev && this.value() === 'from' && (this.seenImport || this.seenExport)) {
|
||||
prev[0] = 'FROM';
|
||||
}
|
||||
regex = (function() {
|
||||
switch (quote) {
|
||||
@@ -253,7 +255,10 @@
|
||||
}
|
||||
})();
|
||||
heredoc = quote.length === 3;
|
||||
ref2 = this.matchWithInterpolations(regex, quote), tokens = ref2.tokens, end = ref2.index;
|
||||
({
|
||||
tokens,
|
||||
index: end
|
||||
} = this.matchWithInterpolations(regex, quote));
|
||||
$ = tokens.length - 1;
|
||||
delimiter = quote.charAt(0);
|
||||
if (heredoc) {
|
||||
@@ -271,72 +276,64 @@
|
||||
})()).join('#{}');
|
||||
while (match = HEREDOC_INDENT.exec(doc)) {
|
||||
attempt = match[1];
|
||||
if (indent === null || (0 < (ref3 = attempt.length) && ref3 < indent.length)) {
|
||||
if (indent === null || (0 < (ref = attempt.length) && ref < indent.length)) {
|
||||
indent = attempt;
|
||||
}
|
||||
}
|
||||
if (indent) {
|
||||
indentRegex = RegExp("\\n" + indent, "g");
|
||||
indentRegex = RegExp(`\\n${indent}`, "g");
|
||||
}
|
||||
this.mergeInterpolationTokens(tokens, {
|
||||
delimiter: delimiter
|
||||
}, (function(_this) {
|
||||
return function(value, i) {
|
||||
value = _this.formatString(value);
|
||||
if (indentRegex) {
|
||||
value = value.replace(indentRegex, '\n');
|
||||
}
|
||||
if (i === 0) {
|
||||
value = value.replace(LEADING_BLANK_LINE, '');
|
||||
}
|
||||
if (i === $) {
|
||||
value = value.replace(TRAILING_BLANK_LINE, '');
|
||||
}
|
||||
return value;
|
||||
};
|
||||
})(this));
|
||||
this.mergeInterpolationTokens(tokens, {delimiter}, (value, i) => {
|
||||
value = this.formatString(value);
|
||||
if (indentRegex) {
|
||||
value = value.replace(indentRegex, '\n');
|
||||
}
|
||||
if (i === 0) {
|
||||
value = value.replace(LEADING_BLANK_LINE, '');
|
||||
}
|
||||
if (i === $) {
|
||||
value = value.replace(TRAILING_BLANK_LINE, '');
|
||||
}
|
||||
return value;
|
||||
});
|
||||
} else {
|
||||
this.mergeInterpolationTokens(tokens, {
|
||||
delimiter: delimiter
|
||||
}, (function(_this) {
|
||||
return function(value, i) {
|
||||
value = _this.formatString(value);
|
||||
value = value.replace(SIMPLE_STRING_OMIT, function(match, offset) {
|
||||
if ((i === 0 && offset === 0) || (i === $ && offset + match.length === value.length)) {
|
||||
return '';
|
||||
} else {
|
||||
return ' ';
|
||||
}
|
||||
});
|
||||
return value;
|
||||
};
|
||||
})(this));
|
||||
this.mergeInterpolationTokens(tokens, {delimiter}, (value, i) => {
|
||||
value = this.formatString(value);
|
||||
value = value.replace(SIMPLE_STRING_OMIT, function(match, offset) {
|
||||
if ((i === 0 && offset === 0) || (i === $ && offset + match.length === value.length)) {
|
||||
return '';
|
||||
} else {
|
||||
return ' ';
|
||||
}
|
||||
});
|
||||
return value;
|
||||
});
|
||||
}
|
||||
return end;
|
||||
};
|
||||
}
|
||||
|
||||
Lexer.prototype.commentToken = function() {
|
||||
commentToken() {
|
||||
var comment, here, match;
|
||||
if (!(match = this.chunk.match(COMMENT))) {
|
||||
return 0;
|
||||
}
|
||||
comment = match[0], here = match[1];
|
||||
[comment, here] = match;
|
||||
if (here) {
|
||||
if (match = HERECOMMENT_ILLEGAL.exec(comment)) {
|
||||
this.error("block comments cannot contain " + match[0], {
|
||||
this.error(`block comments cannot contain ${match[0]}`, {
|
||||
offset: match.index,
|
||||
length: match[0].length
|
||||
});
|
||||
}
|
||||
if (here.indexOf('\n') >= 0) {
|
||||
here = here.replace(RegExp("\\n" + (repeat(' ', this.indent)), "g"), '\n');
|
||||
here = here.replace(RegExp(`\\n${repeat(' ', this.indent)}`, "g"), '\n');
|
||||
}
|
||||
this.token('HERECOMMENT', here, 0, comment.length);
|
||||
}
|
||||
return comment.length;
|
||||
};
|
||||
}
|
||||
|
||||
Lexer.prototype.jsToken = function() {
|
||||
jsToken() {
|
||||
var match, script;
|
||||
if (!(this.chunk.charAt(0) === '`' && (match = HERE_JSTOKEN.exec(this.chunk) || JSTOKEN.exec(this.chunk)))) {
|
||||
return 0;
|
||||
@@ -346,33 +343,33 @@
|
||||
});
|
||||
this.token('JS', script, 0, match[0].length);
|
||||
return match[0].length;
|
||||
};
|
||||
}
|
||||
|
||||
Lexer.prototype.regexToken = function() {
|
||||
var body, closed, end, flags, index, match, origin, prev, ref2, ref3, ref4, regex, tokens;
|
||||
regexToken() {
|
||||
var body, closed, end, flags, index, match, origin, prev, ref, ref1, regex, tokens;
|
||||
switch (false) {
|
||||
case !(match = REGEX_ILLEGAL.exec(this.chunk)):
|
||||
this.error("regular expressions cannot begin with " + match[2], {
|
||||
this.error(`regular expressions cannot begin with ${match[2]}`, {
|
||||
offset: match.index + match[1].length
|
||||
});
|
||||
break;
|
||||
case !(match = this.matchWithInterpolations(HEREGEX, '///')):
|
||||
tokens = match.tokens, index = match.index;
|
||||
({tokens, index} = match);
|
||||
break;
|
||||
case !(match = REGEX.exec(this.chunk)):
|
||||
regex = match[0], body = match[1], closed = match[2];
|
||||
[regex, body, closed] = match;
|
||||
this.validateEscapes(body, {
|
||||
isRegex: true,
|
||||
offsetInChunk: 1
|
||||
});
|
||||
index = regex.length;
|
||||
ref2 = this.tokens, prev = ref2[ref2.length - 1];
|
||||
prev = this.prev();
|
||||
if (prev) {
|
||||
if (prev.spaced && (ref3 = prev[0], indexOf.call(CALLABLE, ref3) >= 0)) {
|
||||
if (prev.spaced && (ref = prev[0], indexOf.call(CALLABLE, ref) >= 0)) {
|
||||
if (!closed || POSSIBLY_DIVISION.test(regex)) {
|
||||
return 0;
|
||||
}
|
||||
} else if (ref4 = prev[0], indexOf.call(NOT_REGEX, ref4) >= 0) {
|
||||
} else if (ref1 = prev[0], indexOf.call(NOT_REGEX, ref1) >= 0) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -383,12 +380,12 @@
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
flags = REGEX_FLAGS.exec(this.chunk.slice(index))[0];
|
||||
[flags] = REGEX_FLAGS.exec(this.chunk.slice(index));
|
||||
end = index + flags.length;
|
||||
origin = this.makeToken('REGEX', null, 0, end);
|
||||
switch (false) {
|
||||
case !!VALID_FLAGS.test(flags):
|
||||
this.error("invalid regular expression flags " + flags, {
|
||||
this.error(`invalid regular expression flags ${flags}`, {
|
||||
offset: index,
|
||||
length: flags.length
|
||||
});
|
||||
@@ -397,9 +394,9 @@
|
||||
if (body == null) {
|
||||
body = this.formatHeregex(tokens[0][1]);
|
||||
}
|
||||
this.token('REGEX', "" + (this.makeDelimitedLiteral(body, {
|
||||
this.token('REGEX', `${this.makeDelimitedLiteral(body, {
|
||||
delimiter: '/'
|
||||
})) + flags, 0, end, origin);
|
||||
})}${flags}`, 0, end, origin);
|
||||
break;
|
||||
default:
|
||||
this.token('REGEX_START', '(', 0, 0, origin);
|
||||
@@ -417,10 +414,10 @@
|
||||
this.token('REGEX_END', ')', end - 1, 0);
|
||||
}
|
||||
return end;
|
||||
};
|
||||
}
|
||||
|
||||
Lexer.prototype.lineToken = function() {
|
||||
var diff, indent, match, noNewlines, size;
|
||||
lineToken() {
|
||||
var diff, indent, match, minLiteralLength, newIndentLiteral, noNewlines, size;
|
||||
if (!(match = MULTI_DENT.exec(this.chunk))) {
|
||||
return 0;
|
||||
}
|
||||
@@ -434,6 +431,20 @@
|
||||
}
|
||||
size = indent.length - 1 - indent.lastIndexOf('\n');
|
||||
noNewlines = this.unfinished();
|
||||
newIndentLiteral = size > 0 ? indent.slice(-size) : '';
|
||||
if (!/^(.?)\1*$/.exec(newIndentLiteral)) {
|
||||
this.error('mixed indentation', {
|
||||
offset: indent.length
|
||||
});
|
||||
return indent.length;
|
||||
}
|
||||
minLiteralLength = Math.min(newIndentLiteral.length, this.indentLiteral.length);
|
||||
if (newIndentLiteral.slice(0, minLiteralLength) !== this.indentLiteral.slice(0, minLiteralLength)) {
|
||||
this.error('indentation mismatch', {
|
||||
offset: indent.length
|
||||
});
|
||||
return indent.length;
|
||||
}
|
||||
if (size - this.indebt === this.indent) {
|
||||
if (noNewlines) {
|
||||
this.suppressNewlines();
|
||||
@@ -450,6 +461,7 @@
|
||||
}
|
||||
if (!this.tokens.length) {
|
||||
this.baseIndent = this.indent = size;
|
||||
this.indentLiteral = newIndentLiteral;
|
||||
return indent.length;
|
||||
}
|
||||
diff = size - this.indent + this.outdebt;
|
||||
@@ -460,6 +472,7 @@
|
||||
});
|
||||
this.outdebt = this.indebt = 0;
|
||||
this.indent = size;
|
||||
this.indentLiteral = newIndentLiteral;
|
||||
} else if (size < this.baseIndent) {
|
||||
this.error('missing indentation', {
|
||||
offset: indent.length
|
||||
@@ -469,24 +482,21 @@
|
||||
this.outdentToken(this.indent - size, noNewlines, indent.length);
|
||||
}
|
||||
return indent.length;
|
||||
};
|
||||
}
|
||||
|
||||
Lexer.prototype.outdentToken = function(moveOut, noNewlines, outdentLength) {
|
||||
var decreasedIndent, dent, lastIndent, ref2;
|
||||
outdentToken(moveOut, noNewlines, outdentLength) {
|
||||
var decreasedIndent, dent, lastIndent, ref;
|
||||
decreasedIndent = this.indent - moveOut;
|
||||
while (moveOut > 0) {
|
||||
lastIndent = this.indents[this.indents.length - 1];
|
||||
if (!lastIndent) {
|
||||
moveOut = 0;
|
||||
} else if (lastIndent === this.outdebt) {
|
||||
moveOut -= this.outdebt;
|
||||
this.outdebt = 0;
|
||||
} else if (lastIndent < this.outdebt) {
|
||||
this.outdebt -= lastIndent;
|
||||
moveOut -= lastIndent;
|
||||
} else if (this.outdebt && moveOut <= this.outdebt) {
|
||||
this.outdebt -= moveOut;
|
||||
moveOut = 0;
|
||||
} else {
|
||||
dent = this.indents.pop() + this.outdebt;
|
||||
if (outdentLength && (ref2 = this.chunk[outdentLength], indexOf.call(INDENTABLE_CLOSERS, ref2) >= 0)) {
|
||||
if (outdentLength && (ref = this.chunk[outdentLength], indexOf.call(INDENTABLE_CLOSERS, ref) >= 0)) {
|
||||
decreasedIndent -= dent - moveOut;
|
||||
moveOut = dent;
|
||||
}
|
||||
@@ -506,15 +516,16 @@
|
||||
this.token('TERMINATOR', '\n', outdentLength, 0);
|
||||
}
|
||||
this.indent = decreasedIndent;
|
||||
this.indentLiteral = this.indentLiteral.slice(0, decreasedIndent);
|
||||
return this;
|
||||
};
|
||||
}
|
||||
|
||||
Lexer.prototype.whitespaceToken = function() {
|
||||
var match, nline, prev, ref2;
|
||||
whitespaceToken() {
|
||||
var match, nline, prev;
|
||||
if (!((match = WHITESPACE.exec(this.chunk)) || (nline = this.chunk.charAt(0) === '\n'))) {
|
||||
return 0;
|
||||
}
|
||||
ref2 = this.tokens, prev = ref2[ref2.length - 1];
|
||||
prev = this.prev();
|
||||
if (prev) {
|
||||
prev[match ? 'spaced' : 'newLine'] = true;
|
||||
}
|
||||
@@ -523,9 +534,9 @@
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Lexer.prototype.newlineToken = function(offset) {
|
||||
newlineToken(offset) {
|
||||
while (this.value() === ';') {
|
||||
this.tokens.pop();
|
||||
}
|
||||
@@ -533,19 +544,19 @@
|
||||
this.token('TERMINATOR', '\n', offset, 0);
|
||||
}
|
||||
return this;
|
||||
};
|
||||
}
|
||||
|
||||
Lexer.prototype.suppressNewlines = function() {
|
||||
suppressNewlines() {
|
||||
if (this.value() === '\\') {
|
||||
this.tokens.pop();
|
||||
}
|
||||
return this;
|
||||
};
|
||||
}
|
||||
|
||||
Lexer.prototype.literalToken = function() {
|
||||
var match, message, origin, prev, ref2, ref3, ref4, ref5, ref6, skipToken, tag, token, value;
|
||||
literalToken() {
|
||||
var match, message, origin, prev, ref, ref1, ref2, ref3, skipToken, tag, token, value;
|
||||
if (match = OPERATOR.exec(this.chunk)) {
|
||||
value = match[0];
|
||||
[value] = match;
|
||||
if (CODE.test(value)) {
|
||||
this.tagParameters();
|
||||
}
|
||||
@@ -553,17 +564,17 @@
|
||||
value = this.chunk.charAt(0);
|
||||
}
|
||||
tag = value;
|
||||
ref2 = this.tokens, prev = ref2[ref2.length - 1];
|
||||
if (prev && indexOf.call(['='].concat(slice.call(COMPOUND_ASSIGN)), value) >= 0) {
|
||||
prev = this.prev();
|
||||
if (prev && indexOf.call(['=', ...COMPOUND_ASSIGN], value) >= 0) {
|
||||
skipToken = false;
|
||||
if (value === '=' && ((ref3 = prev[1]) === '||' || ref3 === '&&') && !prev.spaced) {
|
||||
if (value === '=' && ((ref = prev[1]) === '||' || ref === '&&') && !prev.spaced) {
|
||||
prev[0] = 'COMPOUND_ASSIGN';
|
||||
prev[1] += '=';
|
||||
prev = this.tokens[this.tokens.length - 2];
|
||||
skipToken = true;
|
||||
}
|
||||
if (prev && prev[0] !== 'PROPERTY') {
|
||||
origin = (ref4 = prev.origin) != null ? ref4 : prev;
|
||||
origin = (ref1 = prev.origin) != null ? ref1 : prev;
|
||||
message = isUnassignable(prev[1], origin[1]);
|
||||
if (message) {
|
||||
this.error(message, origin[2]);
|
||||
@@ -602,12 +613,12 @@
|
||||
} else if (value === '?' && (prev != null ? prev.spaced : void 0)) {
|
||||
tag = 'BIN?';
|
||||
} else if (prev && !prev.spaced) {
|
||||
if (value === '(' && (ref5 = prev[0], indexOf.call(CALLABLE, ref5) >= 0)) {
|
||||
if (value === '(' && (ref2 = prev[0], indexOf.call(CALLABLE, ref2) >= 0)) {
|
||||
if (prev[0] === '?') {
|
||||
prev[0] = 'FUNC_EXIST';
|
||||
}
|
||||
tag = 'CALL_START';
|
||||
} else if (value === '[' && (ref6 = prev[0], indexOf.call(INDEXABLE, ref6) >= 0)) {
|
||||
} else if (value === '[' && (ref3 = prev[0], indexOf.call(INDEXABLE, ref3) >= 0)) {
|
||||
tag = 'INDEX_START';
|
||||
switch (prev[0]) {
|
||||
case '?':
|
||||
@@ -632,15 +643,15 @@
|
||||
}
|
||||
this.tokens.push(token);
|
||||
return value.length;
|
||||
};
|
||||
}
|
||||
|
||||
Lexer.prototype.tagParameters = function() {
|
||||
tagParameters() {
|
||||
var i, stack, tok, tokens;
|
||||
if (this.tag() !== ')') {
|
||||
return this;
|
||||
}
|
||||
stack = [];
|
||||
tokens = this.tokens;
|
||||
({tokens} = this);
|
||||
i = tokens.length;
|
||||
tokens[--i][0] = 'PARAM_END';
|
||||
while (tok = tokens[--i]) {
|
||||
@@ -661,14 +672,14 @@
|
||||
}
|
||||
}
|
||||
return this;
|
||||
};
|
||||
}
|
||||
|
||||
Lexer.prototype.closeIndentation = function() {
|
||||
closeIndentation() {
|
||||
return this.outdentToken(this.indent);
|
||||
};
|
||||
}
|
||||
|
||||
Lexer.prototype.matchWithInterpolations = function(regex, delimiter) {
|
||||
var close, column, firstToken, index, lastToken, line, nested, offsetInChunk, open, ref2, ref3, ref4, str, strPart, tokens;
|
||||
matchWithInterpolations(regex, delimiter) {
|
||||
var close, column, firstToken, index, lastToken, line, nested, offsetInChunk, open, ref, str, strPart, tokens;
|
||||
tokens = [];
|
||||
offsetInChunk = delimiter.length;
|
||||
if (this.chunk.slice(0, offsetInChunk) !== delimiter) {
|
||||
@@ -676,10 +687,10 @@
|
||||
}
|
||||
str = this.chunk.slice(offsetInChunk);
|
||||
while (true) {
|
||||
strPart = regex.exec(str)[0];
|
||||
[strPart] = regex.exec(str);
|
||||
this.validateEscapes(strPart, {
|
||||
isRegex: delimiter.charAt(0) === '/',
|
||||
offsetInChunk: offsetInChunk
|
||||
offsetInChunk
|
||||
});
|
||||
tokens.push(this.makeToken('NEOSTRING', strPart, offsetInChunk));
|
||||
str = str.slice(strPart.length);
|
||||
@@ -687,18 +698,21 @@
|
||||
if (str.slice(0, 2) !== '#{') {
|
||||
break;
|
||||
}
|
||||
ref2 = this.getLineAndColumnFromChunk(offsetInChunk + 1), line = ref2[0], column = ref2[1];
|
||||
ref3 = new Lexer().tokenize(str.slice(1), {
|
||||
[line, column] = this.getLineAndColumnFromChunk(offsetInChunk + 1);
|
||||
({
|
||||
tokens: nested,
|
||||
index
|
||||
} = new Lexer().tokenize(str.slice(1), {
|
||||
line: line,
|
||||
column: column,
|
||||
untilBalanced: true
|
||||
}), nested = ref3.tokens, index = ref3.index;
|
||||
}));
|
||||
index += 1;
|
||||
open = nested[0], close = nested[nested.length - 1];
|
||||
open[0] = open[1] = '(';
|
||||
close[0] = close[1] = ')';
|
||||
close.origin = ['', 'end of interpolation', close[2]];
|
||||
if (((ref4 = nested[1]) != null ? ref4[0] : void 0) === 'TERMINATOR') {
|
||||
if (((ref = nested[1]) != null ? ref[0] : void 0) === 'TERMINATOR') {
|
||||
nested.splice(1, 1);
|
||||
}
|
||||
tokens.push(['TOKENS', nested]);
|
||||
@@ -706,7 +720,7 @@
|
||||
offsetInChunk += index;
|
||||
}
|
||||
if (str.slice(0, delimiter.length) !== delimiter) {
|
||||
this.error("missing " + delimiter, {
|
||||
this.error(`missing ${delimiter}`, {
|
||||
length: delimiter.length
|
||||
});
|
||||
}
|
||||
@@ -722,20 +736,20 @@
|
||||
lastToken[2].last_column -= 1;
|
||||
}
|
||||
return {
|
||||
tokens: tokens,
|
||||
tokens,
|
||||
index: offsetInChunk + delimiter.length
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
Lexer.prototype.mergeInterpolationTokens = function(tokens, options, fn) {
|
||||
var converted, firstEmptyStringIndex, firstIndex, i, j, lastToken, len, locationToken, lparen, plusToken, ref2, rparen, tag, token, tokensToPush, value;
|
||||
mergeInterpolationTokens(tokens, options, fn) {
|
||||
var converted, firstEmptyStringIndex, firstIndex, i, j, lastToken, len, locationToken, lparen, plusToken, rparen, tag, token, tokensToPush, value;
|
||||
if (tokens.length > 1) {
|
||||
lparen = this.token('STRING_START', '(', 0, 0);
|
||||
}
|
||||
firstIndex = this.tokens.length;
|
||||
for (i = j = 0, len = tokens.length; j < len; i = ++j) {
|
||||
token = tokens[i];
|
||||
tag = token[0], value = token[1];
|
||||
[tag, value] = token;
|
||||
switch (tag) {
|
||||
case 'TOKENS':
|
||||
if (value.length === 2) {
|
||||
@@ -770,7 +784,7 @@
|
||||
last_column: locationToken[2].first_column
|
||||
};
|
||||
}
|
||||
(ref2 = this.tokens).push.apply(ref2, tokensToPush);
|
||||
this.tokens.push(...tokensToPush);
|
||||
}
|
||||
if (lparen) {
|
||||
lastToken = tokens[tokens.length - 1];
|
||||
@@ -790,24 +804,24 @@
|
||||
last_column: lastToken[2].last_column
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Lexer.prototype.pair = function(tag) {
|
||||
var lastIndent, prev, ref2, ref3, wanted;
|
||||
ref2 = this.ends, prev = ref2[ref2.length - 1];
|
||||
pair(tag) {
|
||||
var lastIndent, prev, ref, ref1, wanted;
|
||||
ref = this.ends, prev = ref[ref.length - 1];
|
||||
if (tag !== (wanted = prev != null ? prev.tag : void 0)) {
|
||||
if ('OUTDENT' !== wanted) {
|
||||
this.error("unmatched " + tag);
|
||||
this.error(`unmatched ${tag}`);
|
||||
}
|
||||
ref3 = this.indents, lastIndent = ref3[ref3.length - 1];
|
||||
ref1 = this.indents, lastIndent = ref1[ref1.length - 1];
|
||||
this.outdentToken(lastIndent, true);
|
||||
return this.pair(tag);
|
||||
}
|
||||
return this.ends.pop();
|
||||
};
|
||||
}
|
||||
|
||||
Lexer.prototype.getLineAndColumnFromChunk = function(offset) {
|
||||
var column, lastLine, lineCount, ref2, string;
|
||||
getLineAndColumnFromChunk(offset) {
|
||||
var column, lastLine, lineCount, ref, string;
|
||||
if (offset === 0) {
|
||||
return [this.chunkLine, this.chunkColumn];
|
||||
}
|
||||
@@ -819,31 +833,25 @@
|
||||
lineCount = count(string, '\n');
|
||||
column = this.chunkColumn;
|
||||
if (lineCount > 0) {
|
||||
ref2 = string.split('\n'), lastLine = ref2[ref2.length - 1];
|
||||
ref = string.split('\n'), lastLine = ref[ref.length - 1];
|
||||
column = lastLine.length;
|
||||
} else {
|
||||
column += string.length;
|
||||
}
|
||||
return [this.chunkLine + lineCount, column];
|
||||
};
|
||||
}
|
||||
|
||||
Lexer.prototype.makeToken = function(tag, value, offsetInChunk, length) {
|
||||
var lastCharacter, locationData, ref2, ref3, token;
|
||||
if (offsetInChunk == null) {
|
||||
offsetInChunk = 0;
|
||||
}
|
||||
if (length == null) {
|
||||
length = value.length;
|
||||
}
|
||||
makeToken(tag, value, offsetInChunk = 0, length = value.length) {
|
||||
var lastCharacter, locationData, token;
|
||||
locationData = {};
|
||||
ref2 = this.getLineAndColumnFromChunk(offsetInChunk), locationData.first_line = ref2[0], locationData.first_column = ref2[1];
|
||||
[locationData.first_line, locationData.first_column] = this.getLineAndColumnFromChunk(offsetInChunk);
|
||||
lastCharacter = length > 0 ? length - 1 : 0;
|
||||
ref3 = this.getLineAndColumnFromChunk(offsetInChunk + lastCharacter), locationData.last_line = ref3[0], locationData.last_column = ref3[1];
|
||||
[locationData.last_line, locationData.last_column] = this.getLineAndColumnFromChunk(offsetInChunk + lastCharacter);
|
||||
token = [tag, value, locationData];
|
||||
return token;
|
||||
};
|
||||
}
|
||||
|
||||
Lexer.prototype.token = function(tag, value, offsetInChunk, length, origin) {
|
||||
token(tag, value, offsetInChunk, length, origin) {
|
||||
var token;
|
||||
token = this.makeToken(tag, value, offsetInChunk, length);
|
||||
if (origin) {
|
||||
@@ -851,38 +859,39 @@
|
||||
}
|
||||
this.tokens.push(token);
|
||||
return token;
|
||||
};
|
||||
}
|
||||
|
||||
Lexer.prototype.tag = function() {
|
||||
var ref2, token;
|
||||
ref2 = this.tokens, token = ref2[ref2.length - 1];
|
||||
tag() {
|
||||
var ref, token;
|
||||
ref = this.tokens, token = ref[ref.length - 1];
|
||||
return token != null ? token[0] : void 0;
|
||||
};
|
||||
}
|
||||
|
||||
Lexer.prototype.value = function() {
|
||||
var ref2, token;
|
||||
ref2 = this.tokens, token = ref2[ref2.length - 1];
|
||||
value() {
|
||||
var ref, token;
|
||||
ref = this.tokens, token = ref[ref.length - 1];
|
||||
return token != null ? token[1] : void 0;
|
||||
};
|
||||
}
|
||||
|
||||
Lexer.prototype.unfinished = function() {
|
||||
var ref2;
|
||||
return LINE_CONTINUER.test(this.chunk) || ((ref2 = this.tag()) === '\\' || ref2 === '.' || ref2 === '?.' || ref2 === '?::' || ref2 === 'UNARY' || ref2 === 'MATH' || ref2 === 'UNARY_MATH' || ref2 === '+' || ref2 === '-' || ref2 === '**' || ref2 === 'SHIFT' || ref2 === 'RELATION' || ref2 === 'COMPARE' || ref2 === '&' || ref2 === '^' || ref2 === '|' || ref2 === '&&' || ref2 === '||' || ref2 === 'BIN?' || ref2 === 'THROW' || ref2 === 'EXTENDS');
|
||||
};
|
||||
prev() {
|
||||
return this.tokens[this.tokens.length - 1];
|
||||
}
|
||||
|
||||
Lexer.prototype.formatString = function(str) {
|
||||
unfinished() {
|
||||
var ref;
|
||||
return LINE_CONTINUER.test(this.chunk) || ((ref = this.tag()) === '\\' || ref === '.' || ref === '?.' || ref === '?::' || ref === 'UNARY' || ref === 'MATH' || ref === 'UNARY_MATH' || ref === '+' || ref === '-' || ref === '**' || ref === 'SHIFT' || ref === 'RELATION' || ref === 'COMPARE' || ref === '&' || ref === '^' || ref === '|' || ref === '&&' || ref === '||' || ref === 'BIN?' || ref === 'THROW' || ref === 'EXTENDS');
|
||||
}
|
||||
|
||||
formatString(str) {
|
||||
return str.replace(STRING_OMIT, '$1');
|
||||
};
|
||||
}
|
||||
|
||||
Lexer.prototype.formatHeregex = function(str) {
|
||||
formatHeregex(str) {
|
||||
return str.replace(HEREGEX_OMIT, '$1$2');
|
||||
};
|
||||
}
|
||||
|
||||
Lexer.prototype.validateEscapes = function(str, options) {
|
||||
var before, hex, invalidEscape, invalidEscapeRegex, match, message, octal, ref2, unicode;
|
||||
if (options == null) {
|
||||
options = {};
|
||||
}
|
||||
validateEscapes(str, options = {}) {
|
||||
var before, hex, invalidEscape, invalidEscapeRegex, match, message, octal, ref, unicode;
|
||||
invalidEscapeRegex = options.isRegex ? REGEX_INVALID_ESCAPE : STRING_INVALID_ESCAPE;
|
||||
match = invalidEscapeRegex.exec(str);
|
||||
if (!match) {
|
||||
@@ -890,22 +899,19 @@
|
||||
}
|
||||
match[0], before = match[1], octal = match[2], hex = match[3], unicode = match[4];
|
||||
message = octal ? "octal escape sequences are not allowed" : "invalid escape sequence";
|
||||
invalidEscape = "\\" + (octal || hex || unicode);
|
||||
return this.error(message + " " + invalidEscape, {
|
||||
offset: ((ref2 = options.offsetInChunk) != null ? ref2 : 0) + match.index + before.length,
|
||||
invalidEscape = `\\${octal || hex || unicode}`;
|
||||
return this.error(`${message} ${invalidEscape}`, {
|
||||
offset: ((ref = options.offsetInChunk) != null ? ref : 0) + match.index + before.length,
|
||||
length: invalidEscape.length
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
Lexer.prototype.makeDelimitedLiteral = function(body, options) {
|
||||
makeDelimitedLiteral(body, options = {}) {
|
||||
var regex;
|
||||
if (options == null) {
|
||||
options = {};
|
||||
}
|
||||
if (body === '' && options.delimiter === '/') {
|
||||
body = '(?:)';
|
||||
}
|
||||
regex = RegExp("(\\\\\\\\)|(\\\\0(?=[1-7]))|\\\\?(" + options.delimiter + ")|\\\\?(?:(\\n)|(\\r)|(\\u2028)|(\\u2029))|(\\\\.)", "g");
|
||||
regex = RegExp(`(\\\\\\\\)|(\\\\0(?=[1-7]))|\\\\?(${options.delimiter})|\\\\?(?:(\\n)|(\\r)|(\\u2028)|(\\u2029))|(\\\\.)`, "g");
|
||||
body = body.replace(regex, function(match, backslash, nul, delimiter, lf, cr, ls, ps, other) {
|
||||
switch (false) {
|
||||
case !backslash:
|
||||
@@ -917,7 +923,7 @@
|
||||
case !nul:
|
||||
return '\\x00';
|
||||
case !delimiter:
|
||||
return "\\" + delimiter;
|
||||
return `\\${delimiter}`;
|
||||
case !lf:
|
||||
return '\\n';
|
||||
case !cr:
|
||||
@@ -928,43 +934,35 @@
|
||||
return '\\u2029';
|
||||
case !other:
|
||||
if (options.double) {
|
||||
return "\\" + other;
|
||||
return `\\${other}`;
|
||||
} else {
|
||||
return other;
|
||||
}
|
||||
}
|
||||
});
|
||||
return "" + options.delimiter + body + options.delimiter;
|
||||
};
|
||||
return `${options.delimiter}${body}${options.delimiter}`;
|
||||
}
|
||||
|
||||
Lexer.prototype.error = function(message, options) {
|
||||
var first_column, first_line, location, ref2, ref3, ref4;
|
||||
if (options == null) {
|
||||
options = {};
|
||||
}
|
||||
location = 'first_line' in options ? options : ((ref3 = this.getLineAndColumnFromChunk((ref2 = options.offset) != null ? ref2 : 0), first_line = ref3[0], first_column = ref3[1], ref3), {
|
||||
first_line: first_line,
|
||||
first_column: first_column,
|
||||
last_column: first_column + ((ref4 = options.length) != null ? ref4 : 1) - 1
|
||||
error(message, options = {}) {
|
||||
var first_column, first_line, location, ref, ref1;
|
||||
location = 'first_line' in options ? options : ([first_line, first_column] = this.getLineAndColumnFromChunk((ref = options.offset) != null ? ref : 0), {
|
||||
first_line,
|
||||
first_column,
|
||||
last_column: first_column + ((ref1 = options.length) != null ? ref1 : 1) - 1
|
||||
});
|
||||
return throwSyntaxError(message, location);
|
||||
};
|
||||
|
||||
return Lexer;
|
||||
|
||||
})();
|
||||
|
||||
isUnassignable = function(name, displayName) {
|
||||
if (displayName == null) {
|
||||
displayName = name;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
isUnassignable = function(name, displayName = name) {
|
||||
switch (false) {
|
||||
case indexOf.call(slice.call(JS_KEYWORDS).concat(slice.call(COFFEE_KEYWORDS)), name) < 0:
|
||||
return "keyword '" + displayName + "' can't be assigned";
|
||||
case indexOf.call([...JS_KEYWORDS, ...COFFEE_KEYWORDS], name) < 0:
|
||||
return `keyword '${displayName}' can't be assigned`;
|
||||
case indexOf.call(STRICT_PROSCRIBED, name) < 0:
|
||||
return "'" + displayName + "' can't be assigned";
|
||||
return `'${displayName}' can't be assigned`;
|
||||
case indexOf.call(RESERVED, name) < 0:
|
||||
return "reserved word '" + displayName + "' can't be assigned";
|
||||
return `reserved word '${displayName}' can't be assigned`;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@@ -973,7 +971,7 @@
|
||||
exports.isUnassignable = isUnassignable;
|
||||
|
||||
isForFrom = function(prev) {
|
||||
var ref2;
|
||||
var ref;
|
||||
if (prev[0] === 'IDENTIFIER') {
|
||||
if (prev[1] === 'from') {
|
||||
prev[1][0] = 'IDENTIFIER';
|
||||
@@ -982,14 +980,14 @@
|
||||
return true;
|
||||
} else if (prev[0] === 'FOR') {
|
||||
return false;
|
||||
} else if ((ref2 = prev[1]) === '{' || ref2 === '[' || ref2 === ',' || ref2 === ':') {
|
||||
} else if ((ref = prev[1]) === '{' || ref === '[' || ref === ',' || ref === ':') {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
JS_KEYWORDS = ['true', 'false', 'null', 'this', 'new', 'delete', 'typeof', 'in', 'instanceof', 'return', 'throw', 'break', 'continue', 'debugger', 'yield', 'if', 'else', 'switch', 'for', 'while', 'do', 'try', 'catch', 'finally', 'class', 'extends', 'super', 'import', 'export', 'default'];
|
||||
JS_KEYWORDS = ['true', 'false', 'null', 'this', 'new', 'delete', 'typeof', 'in', 'instanceof', 'return', 'throw', 'break', 'continue', 'debugger', 'yield', 'await', 'if', 'else', 'switch', 'for', 'while', 'do', 'try', 'catch', 'finally', 'class', 'extends', 'super', 'import', 'export', 'default'];
|
||||
|
||||
COFFEE_KEYWORDS = ['undefined', 'Infinity', 'NaN', 'then', 'unless', 'until', 'loop', 'of', 'by', 'when'];
|
||||
|
||||
4265
lib/coffeescript/nodes.js
Normal file
4265
lib/coffeescript/nodes.js
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,16 +1,16 @@
|
||||
// Generated by CoffeeScript 1.12.5
|
||||
// Generated by CoffeeScript 2.0.0-beta1
|
||||
(function() {
|
||||
var LONG_FLAG, MULTI_FLAG, OPTIONAL, OptionParser, SHORT_FLAG, buildRule, buildRules, normalizeArguments, repeat;
|
||||
|
||||
repeat = require('./helpers').repeat;
|
||||
({repeat} = require('./helpers'));
|
||||
|
||||
exports.OptionParser = OptionParser = (function() {
|
||||
function OptionParser(rules, banner) {
|
||||
exports.OptionParser = OptionParser = class OptionParser {
|
||||
constructor(rules, banner) {
|
||||
this.banner = banner;
|
||||
this.rules = buildRules(rules);
|
||||
}
|
||||
|
||||
OptionParser.prototype.parse = function(args) {
|
||||
parse(args) {
|
||||
var arg, i, isOption, j, k, len, len1, matchedRule, options, originalArgs, pos, ref, rule, seenNonOptionArg, skippingArgument, value;
|
||||
options = {
|
||||
"arguments": []
|
||||
@@ -48,7 +48,7 @@
|
||||
}
|
||||
}
|
||||
if (isOption && !matchedRule) {
|
||||
throw new Error("unrecognized option: " + arg);
|
||||
throw new Error(`unrecognized option: ${arg}`);
|
||||
}
|
||||
}
|
||||
if (seenNonOptionArg || !isOption) {
|
||||
@@ -56,13 +56,13 @@
|
||||
}
|
||||
}
|
||||
return options;
|
||||
};
|
||||
}
|
||||
|
||||
OptionParser.prototype.help = function() {
|
||||
help() {
|
||||
var j, len, letPart, lines, ref, rule, spaces;
|
||||
lines = [];
|
||||
if (this.banner) {
|
||||
lines.unshift(this.banner + "\n");
|
||||
lines.unshift(`${this.banner}\n`);
|
||||
}
|
||||
ref = this.rules;
|
||||
for (j = 0, len = ref.length; j < len; j++) {
|
||||
@@ -72,12 +72,10 @@
|
||||
letPart = rule.shortFlag ? rule.shortFlag + ', ' : ' ';
|
||||
lines.push(' ' + letPart + rule.longFlag + spaces + rule.description);
|
||||
}
|
||||
return "\n" + (lines.join('\n')) + "\n";
|
||||
};
|
||||
return `\n${lines.join('\n')}\n`;
|
||||
}
|
||||
|
||||
return OptionParser;
|
||||
|
||||
})();
|
||||
};
|
||||
|
||||
LONG_FLAG = /^(--\w[\w\-]*)/;
|
||||
|
||||
@@ -95,16 +93,13 @@
|
||||
if (tuple.length < 3) {
|
||||
tuple.unshift(null);
|
||||
}
|
||||
results.push(buildRule.apply(null, tuple));
|
||||
results.push(buildRule(...tuple));
|
||||
}
|
||||
return results;
|
||||
};
|
||||
|
||||
buildRule = function(shortFlag, longFlag, description, options) {
|
||||
buildRule = function(shortFlag, longFlag, description, options = {}) {
|
||||
var match;
|
||||
if (options == null) {
|
||||
options = {};
|
||||
}
|
||||
match = longFlag.match(OPTIONAL);
|
||||
longFlag = longFlag.match(LONG_FLAG)[1];
|
||||
return {
|
||||
897
lib/coffeescript/parser.js
Executable file
897
lib/coffeescript/parser.js
Executable file
File diff suppressed because one or more lines are too long
@@ -1,8 +1,8 @@
|
||||
// Generated by CoffeeScript 1.12.5
|
||||
// Generated by CoffeeScript 2.0.0-beta1
|
||||
(function() {
|
||||
var CoffeeScript, Module, binary, child_process, ext, findExtension, fork, helpers, i, len, loadFile, path, ref;
|
||||
|
||||
CoffeeScript = require('./coffee-script');
|
||||
CoffeeScript = require('./coffeescript');
|
||||
|
||||
child_process = require('child_process');
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
}
|
||||
|
||||
if (child_process) {
|
||||
fork = child_process.fork;
|
||||
({fork} = child_process);
|
||||
binary = require.resolve('../../bin/coffee');
|
||||
child_process.fork = function(path, args, options) {
|
||||
if (helpers.isCoffee(path)) {
|
||||
@@ -1,6 +1,6 @@
|
||||
// Generated by CoffeeScript 1.12.5
|
||||
// Generated by CoffeeScript 2.0.0-beta1
|
||||
(function() {
|
||||
var CoffeeScript, addHistory, addMultilineHandler, fs, getCommandId, merge, nodeREPL, path, ref, replDefaults, runInContext, updateSyntaxError, vm;
|
||||
var CoffeeScript, addHistory, addMultilineHandler, fs, getCommandId, merge, nodeREPL, path, replDefaults, runInContext, updateSyntaxError, vm;
|
||||
|
||||
fs = require('fs');
|
||||
|
||||
@@ -10,20 +10,20 @@
|
||||
|
||||
nodeREPL = require('repl');
|
||||
|
||||
CoffeeScript = require('./coffee-script');
|
||||
CoffeeScript = require('./coffeescript');
|
||||
|
||||
ref = require('./helpers'), merge = ref.merge, updateSyntaxError = ref.updateSyntaxError;
|
||||
({merge, updateSyntaxError} = require('./helpers'));
|
||||
|
||||
replDefaults = {
|
||||
prompt: 'coffee> ',
|
||||
historyFile: process.env.HOME ? path.join(process.env.HOME, '.coffee_history') : void 0,
|
||||
historyMaxInputSize: 10240,
|
||||
"eval": function(input, context, filename, cb) {
|
||||
var Assign, Block, Literal, Value, ast, err, js, ref1, referencedVars, token, tokens;
|
||||
var Assign, Block, Literal, Value, ast, err, js, referencedVars, token, tokens;
|
||||
input = input.replace(/\uFF00/g, '\n');
|
||||
input = input.replace(/^\(([\s\S]*)\n\)$/m, '$1');
|
||||
input = input.replace(/^\s*try\s*{([\s\S]*)}\s*catch.*$/m, '$1');
|
||||
ref1 = require('./nodes'), Block = ref1.Block, Assign = ref1.Assign, Value = ref1.Value, Literal = ref1.Literal;
|
||||
({Block, Assign, Value, Literal} = require('./nodes'));
|
||||
try {
|
||||
tokens = CoffeeScript.tokens(input);
|
||||
referencedVars = (function() {
|
||||
@@ -42,7 +42,7 @@
|
||||
js = ast.compile({
|
||||
bare: true,
|
||||
locals: Object.keys(context),
|
||||
referencedVars: referencedVars
|
||||
referencedVars
|
||||
});
|
||||
return cb(null, runInContext(js, context, filename));
|
||||
} catch (error) {
|
||||
@@ -62,9 +62,9 @@
|
||||
};
|
||||
|
||||
addMultilineHandler = function(repl) {
|
||||
var inputStream, multiline, nodeLineListener, origPrompt, outputStream, ref1, rli;
|
||||
rli = repl.rli, inputStream = repl.inputStream, outputStream = repl.outputStream;
|
||||
origPrompt = (ref1 = repl._prompt) != null ? ref1 : repl.prompt;
|
||||
var inputStream, multiline, nodeLineListener, origPrompt, outputStream, ref, rli;
|
||||
({rli, inputStream, outputStream} = repl);
|
||||
origPrompt = (ref = repl._prompt) != null ? ref : repl.prompt;
|
||||
multiline = {
|
||||
enabled: false,
|
||||
initialPrompt: origPrompt.replace(/^[^> ]*/, function(x) {
|
||||
@@ -79,7 +79,7 @@
|
||||
rli.removeListener('line', nodeLineListener);
|
||||
rli.on('line', function(cmd) {
|
||||
if (multiline.enabled) {
|
||||
multiline.buffer += cmd + "\n";
|
||||
multiline.buffer += `${cmd}\n`;
|
||||
rli.setPrompt(multiline.prompt);
|
||||
rli.prompt(true);
|
||||
} else {
|
||||
@@ -124,7 +124,7 @@
|
||||
stat = fs.statSync(filename);
|
||||
size = Math.min(maxSize, stat.size);
|
||||
readFd = fs.openSync(filename, 'r');
|
||||
buffer = new Buffer(size);
|
||||
buffer = Buffer.alloc(size);
|
||||
fs.readSync(readFd, buffer, 0, size, stat.size - size);
|
||||
fs.closeSync(readFd);
|
||||
repl.rli.history = buffer.toString().split('\n').reverse();
|
||||
@@ -140,7 +140,7 @@
|
||||
fd = fs.openSync(filename, 'a');
|
||||
repl.rli.addListener('line', function(code) {
|
||||
if (code && code.length && code !== '.history' && code !== '.exit' && lastLine !== code) {
|
||||
fs.writeSync(fd, code + "\n");
|
||||
fs.writeSync(fd, `${code}\n`);
|
||||
return lastLine = code;
|
||||
}
|
||||
});
|
||||
@@ -150,7 +150,7 @@
|
||||
return repl.commands[getCommandId(repl, 'history')] = {
|
||||
help: 'Show command history',
|
||||
action: function() {
|
||||
repl.outputStream.write((repl.rli.history.slice(0).reverse().join('\n')) + "\n");
|
||||
repl.outputStream.write(`${repl.rli.history.slice(0).reverse().join('\n')}\n`);
|
||||
return repl.displayPrompt();
|
||||
}
|
||||
};
|
||||
@@ -160,23 +160,20 @@
|
||||
var commandsHaveLeadingDot;
|
||||
commandsHaveLeadingDot = repl.commands['.help'] != null;
|
||||
if (commandsHaveLeadingDot) {
|
||||
return "." + commandName;
|
||||
return `.${commandName}`;
|
||||
} else {
|
||||
return commandName;
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
start: function(opts) {
|
||||
var build, major, minor, ref1, repl;
|
||||
if (opts == null) {
|
||||
opts = {};
|
||||
}
|
||||
ref1 = process.versions.node.split('.').map(function(n) {
|
||||
start: function(opts = {}) {
|
||||
var build, major, minor, repl;
|
||||
[major, minor, build] = process.versions.node.split('.').map(function(n) {
|
||||
return parseInt(n);
|
||||
}), major = ref1[0], minor = ref1[1], build = ref1[2];
|
||||
if (major === 0 && minor < 8) {
|
||||
console.warn("Node 0.8.0+ required for CoffeeScript REPL");
|
||||
});
|
||||
if (major < 6) {
|
||||
console.warn("Node 6+ required for CoffeeScript REPL");
|
||||
process.exit(1);
|
||||
}
|
||||
CoffeeScript.register();
|
||||
524
lib/coffeescript/rewriter.js
Normal file
524
lib/coffeescript/rewriter.js
Normal file
@@ -0,0 +1,524 @@
|
||||
// Generated by CoffeeScript 2.0.0-beta1
|
||||
(function() {
|
||||
var BALANCED_PAIRS, CALL_CLOSERS, EXPRESSION_CLOSE, EXPRESSION_END, EXPRESSION_START, IMPLICIT_CALL, IMPLICIT_END, IMPLICIT_FUNC, IMPLICIT_UNSPACED_CALL, INVERSES, LINEBREAKS, SINGLE_CLOSERS, SINGLE_LINERS, generate, k, left, len, rite,
|
||||
indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
|
||||
|
||||
generate = function(tag, value, origin) {
|
||||
var tok;
|
||||
tok = [tag, value];
|
||||
tok.generated = true;
|
||||
if (origin) {
|
||||
tok.origin = origin;
|
||||
}
|
||||
return tok;
|
||||
};
|
||||
|
||||
exports.Rewriter = (function() {
|
||||
class Rewriter {
|
||||
rewrite(tokens1) {
|
||||
this.tokens = tokens1;
|
||||
this.removeLeadingNewlines();
|
||||
this.closeOpenCalls();
|
||||
this.closeOpenIndexes();
|
||||
this.normalizeLines();
|
||||
this.tagPostfixConditionals();
|
||||
this.addImplicitBracesAndParens();
|
||||
this.addLocationDataToGeneratedTokens();
|
||||
this.fixOutdentLocationData();
|
||||
return this.tokens;
|
||||
}
|
||||
|
||||
scanTokens(block) {
|
||||
var i, token, tokens;
|
||||
({tokens} = this);
|
||||
i = 0;
|
||||
while (token = tokens[i]) {
|
||||
i += block.call(this, token, i, tokens);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
detectEnd(i, condition, action) {
|
||||
var levels, ref, ref1, token, tokens;
|
||||
({tokens} = this);
|
||||
levels = 0;
|
||||
while (token = tokens[i]) {
|
||||
if (levels === 0 && condition.call(this, token, i)) {
|
||||
return action.call(this, token, i);
|
||||
}
|
||||
if (!token || levels < 0) {
|
||||
return action.call(this, token, i - 1);
|
||||
}
|
||||
if (ref = token[0], indexOf.call(EXPRESSION_START, ref) >= 0) {
|
||||
levels += 1;
|
||||
} else if (ref1 = token[0], indexOf.call(EXPRESSION_END, ref1) >= 0) {
|
||||
levels -= 1;
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
return i - 1;
|
||||
}
|
||||
|
||||
removeLeadingNewlines() {
|
||||
var i, k, len, ref, tag;
|
||||
ref = this.tokens;
|
||||
for (i = k = 0, len = ref.length; k < len; i = ++k) {
|
||||
[tag] = ref[i];
|
||||
if (tag !== 'TERMINATOR') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i) {
|
||||
return this.tokens.splice(0, i);
|
||||
}
|
||||
}
|
||||
|
||||
closeOpenCalls() {
|
||||
var action, condition;
|
||||
condition = function(token, i) {
|
||||
var ref;
|
||||
return ((ref = token[0]) === ')' || ref === 'CALL_END') || token[0] === 'OUTDENT' && this.tag(i - 1) === ')';
|
||||
};
|
||||
action = function(token, i) {
|
||||
return this.tokens[token[0] === 'OUTDENT' ? i - 1 : i][0] = 'CALL_END';
|
||||
};
|
||||
return this.scanTokens(function(token, i) {
|
||||
if (token[0] === 'CALL_START') {
|
||||
this.detectEnd(i + 1, condition, action);
|
||||
}
|
||||
return 1;
|
||||
});
|
||||
}
|
||||
|
||||
closeOpenIndexes() {
|
||||
var action, condition;
|
||||
condition = function(token, i) {
|
||||
var ref;
|
||||
return (ref = token[0]) === ']' || ref === 'INDEX_END';
|
||||
};
|
||||
action = function(token, i) {
|
||||
return token[0] = 'INDEX_END';
|
||||
};
|
||||
return this.scanTokens(function(token, i) {
|
||||
if (token[0] === 'INDEX_START') {
|
||||
this.detectEnd(i + 1, condition, action);
|
||||
}
|
||||
return 1;
|
||||
});
|
||||
}
|
||||
|
||||
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) {
|
||||
while (this.tag(i + j + fuzz) === 'HERECOMMENT') {
|
||||
fuzz += 2;
|
||||
}
|
||||
if (pattern[j] == null) {
|
||||
continue;
|
||||
}
|
||||
if (typeof pattern[j] === 'string') {
|
||||
pattern[j] = [pattern[j]];
|
||||
}
|
||||
if (ref1 = this.tag(i + j + fuzz), indexOf.call(pattern[j], ref1) < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return i + j + fuzz - 1;
|
||||
}
|
||||
|
||||
looksObjectish(j) {
|
||||
var end, index;
|
||||
if (this.indexOfTag(j, '@', null, ':') > -1 || this.indexOfTag(j, null, ':') > -1) {
|
||||
return true;
|
||||
}
|
||||
index = this.indexOfTag(j, EXPRESSION_START);
|
||||
if (index > -1) {
|
||||
end = null;
|
||||
this.detectEnd(index + 1, (function(token) {
|
||||
var ref;
|
||||
return ref = token[0], indexOf.call(EXPRESSION_END, ref) >= 0;
|
||||
}), (function(token, i) {
|
||||
return end = i;
|
||||
}));
|
||||
if (this.tag(end + 1) === ':') {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
findTagsBackwards(i, tags) {
|
||||
var backStack, ref, ref1, ref2, ref3, ref4, ref5;
|
||||
backStack = [];
|
||||
while (i >= 0 && (backStack.length || (ref2 = this.tag(i), indexOf.call(tags, ref2) < 0) && ((ref3 = this.tag(i), indexOf.call(EXPRESSION_START, ref3) < 0) || this.tokens[i].generated) && (ref4 = this.tag(i), indexOf.call(LINEBREAKS, ref4) < 0))) {
|
||||
if (ref = this.tag(i), indexOf.call(EXPRESSION_END, ref) >= 0) {
|
||||
backStack.push(this.tag(i));
|
||||
}
|
||||
if ((ref1 = this.tag(i), indexOf.call(EXPRESSION_START, ref1) >= 0) && backStack.length) {
|
||||
backStack.pop();
|
||||
}
|
||||
i -= 1;
|
||||
}
|
||||
return ref5 = this.tag(i), indexOf.call(tags, ref5) >= 0;
|
||||
}
|
||||
|
||||
addImplicitBracesAndParens() {
|
||||
var stack, start;
|
||||
stack = [];
|
||||
start = null;
|
||||
return this.scanTokens(function(token, i, tokens) {
|
||||
var endImplicitCall, endImplicitObject, forward, inImplicit, inImplicitCall, inImplicitControl, inImplicitObject, newLine, nextTag, offset, prevTag, prevToken, ref, ref1, ref2, s, sameLine, stackIdx, stackTag, stackTop, startIdx, startImplicitCall, startImplicitObject, startsLine, tag;
|
||||
[tag] = token;
|
||||
[prevTag] = prevToken = i > 0 ? tokens[i - 1] : [];
|
||||
[nextTag] = i < tokens.length - 1 ? tokens[i + 1] : [];
|
||||
stackTop = function() {
|
||||
return stack[stack.length - 1];
|
||||
};
|
||||
startIdx = i;
|
||||
forward = function(n) {
|
||||
return i - startIdx + n;
|
||||
};
|
||||
inImplicit = function() {
|
||||
var ref, ref1;
|
||||
return (ref = stackTop()) != null ? (ref1 = ref[2]) != null ? ref1.ours : void 0 : void 0;
|
||||
};
|
||||
inImplicitCall = function() {
|
||||
var ref;
|
||||
return inImplicit() && ((ref = stackTop()) != null ? ref[0] : void 0) === '(';
|
||||
};
|
||||
inImplicitObject = function() {
|
||||
var ref;
|
||||
return inImplicit() && ((ref = stackTop()) != null ? ref[0] : void 0) === '{';
|
||||
};
|
||||
inImplicitControl = function() {
|
||||
var ref;
|
||||
return inImplicit && ((ref = stackTop()) != null ? ref[0] : void 0) === 'CONTROL';
|
||||
};
|
||||
startImplicitCall = function(j) {
|
||||
var idx;
|
||||
idx = j != null ? j : i;
|
||||
stack.push([
|
||||
'(', idx, {
|
||||
ours: true
|
||||
}
|
||||
]);
|
||||
tokens.splice(idx, 0, generate('CALL_START', '('));
|
||||
if (j == null) {
|
||||
return i += 1;
|
||||
}
|
||||
};
|
||||
endImplicitCall = function() {
|
||||
stack.pop();
|
||||
tokens.splice(i, 0, generate('CALL_END', ')', ['', 'end of input', token[2]]));
|
||||
return i += 1;
|
||||
};
|
||||
startImplicitObject = function(j, startsLine = true) {
|
||||
var idx, val;
|
||||
idx = j != null ? j : i;
|
||||
stack.push([
|
||||
'{', idx, {
|
||||
sameLine: true,
|
||||
startsLine: startsLine,
|
||||
ours: true
|
||||
}
|
||||
]);
|
||||
val = new String('{');
|
||||
val.generated = true;
|
||||
tokens.splice(idx, 0, generate('{', val, token));
|
||||
if (j == null) {
|
||||
return i += 1;
|
||||
}
|
||||
};
|
||||
endImplicitObject = function(j) {
|
||||
j = j != null ? j : i;
|
||||
stack.pop();
|
||||
tokens.splice(j, 0, generate('}', '}', token));
|
||||
return i += 1;
|
||||
};
|
||||
if (inImplicitCall() && (tag === 'IF' || tag === 'TRY' || tag === 'FINALLY' || tag === 'CATCH' || tag === 'CLASS' || tag === 'SWITCH')) {
|
||||
stack.push([
|
||||
'CONTROL', i, {
|
||||
ours: true
|
||||
}
|
||||
]);
|
||||
return forward(1);
|
||||
}
|
||||
if (tag === 'INDENT' && inImplicit()) {
|
||||
if (prevTag !== '=>' && prevTag !== '->' && prevTag !== '[' && prevTag !== '(' && prevTag !== ',' && prevTag !== '{' && prevTag !== 'TRY' && prevTag !== 'ELSE' && prevTag !== '=') {
|
||||
while (inImplicitCall()) {
|
||||
endImplicitCall();
|
||||
}
|
||||
}
|
||||
if (inImplicitControl()) {
|
||||
stack.pop();
|
||||
}
|
||||
stack.push([tag, i]);
|
||||
return forward(1);
|
||||
}
|
||||
if (indexOf.call(EXPRESSION_START, tag) >= 0) {
|
||||
stack.push([tag, i]);
|
||||
return forward(1);
|
||||
}
|
||||
if (indexOf.call(EXPRESSION_END, tag) >= 0) {
|
||||
while (inImplicit()) {
|
||||
if (inImplicitCall()) {
|
||||
endImplicitCall();
|
||||
} else if (inImplicitObject()) {
|
||||
endImplicitObject();
|
||||
} else {
|
||||
stack.pop();
|
||||
}
|
||||
}
|
||||
start = stack.pop();
|
||||
}
|
||||
if ((indexOf.call(IMPLICIT_FUNC, tag) >= 0 && token.spaced || tag === '?' && i > 0 && !tokens[i - 1].spaced) && (indexOf.call(IMPLICIT_CALL, nextTag) >= 0 || indexOf.call(IMPLICIT_UNSPACED_CALL, nextTag) >= 0 && !((ref = tokens[i + 1]) != null ? ref.spaced : void 0) && !((ref1 = tokens[i + 1]) != null ? ref1.newLine : void 0))) {
|
||||
if (tag === '?') {
|
||||
tag = token[0] = 'FUNC_EXIST';
|
||||
}
|
||||
startImplicitCall(i + 1);
|
||||
return forward(2);
|
||||
}
|
||||
if (indexOf.call(IMPLICIT_FUNC, tag) >= 0 && this.indexOfTag(i + 1, 'INDENT') > -1 && this.looksObjectish(i + 2) && !this.findTagsBackwards(i, ['CLASS', 'EXTENDS', 'IF', 'CATCH', 'SWITCH', 'LEADING_WHEN', 'FOR', 'WHILE', 'UNTIL'])) {
|
||||
startImplicitCall(i + 1);
|
||||
stack.push(['INDENT', i + 2]);
|
||||
return forward(3);
|
||||
}
|
||||
if (tag === ':') {
|
||||
s = (function() {
|
||||
var ref2;
|
||||
switch (false) {
|
||||
case ref2 = this.tag(i - 1), indexOf.call(EXPRESSION_END, ref2) < 0:
|
||||
return start[1];
|
||||
case this.tag(i - 2) !== '@':
|
||||
return i - 2;
|
||||
default:
|
||||
return i - 1;
|
||||
}
|
||||
}).call(this);
|
||||
while (this.tag(s - 2) === 'HERECOMMENT') {
|
||||
s -= 2;
|
||||
}
|
||||
this.insideForDeclaration = nextTag === 'FOR';
|
||||
startsLine = s === 0 || (ref2 = this.tag(s - 1), indexOf.call(LINEBREAKS, ref2) >= 0) || tokens[s - 1].newLine;
|
||||
if (stackTop()) {
|
||||
[stackTag, stackIdx] = stackTop();
|
||||
if ((stackTag === '{' || stackTag === 'INDENT' && this.tag(stackIdx - 1) === '{') && (startsLine || this.tag(s - 1) === ',' || this.tag(s - 1) === '{')) {
|
||||
return forward(1);
|
||||
}
|
||||
}
|
||||
startImplicitObject(s, !!startsLine);
|
||||
return forward(2);
|
||||
}
|
||||
if (inImplicitObject() && indexOf.call(LINEBREAKS, tag) >= 0) {
|
||||
stackTop()[2].sameLine = false;
|
||||
}
|
||||
newLine = prevTag === 'OUTDENT' || prevToken.newLine;
|
||||
if (indexOf.call(IMPLICIT_END, tag) >= 0 || indexOf.call(CALL_CLOSERS, tag) >= 0 && newLine) {
|
||||
while (inImplicit()) {
|
||||
[stackTag, stackIdx, {sameLine, startsLine}] = stackTop();
|
||||
if (inImplicitCall() && prevTag !== ',') {
|
||||
endImplicitCall();
|
||||
} else if (inImplicitObject() && !this.insideForDeclaration && sameLine && tag !== 'TERMINATOR' && prevTag !== ':') {
|
||||
endImplicitObject();
|
||||
} else if (inImplicitObject() && tag === 'TERMINATOR' && prevTag !== ',' && !(startsLine && this.looksObjectish(i + 1))) {
|
||||
if (nextTag === 'HERECOMMENT') {
|
||||
return forward(1);
|
||||
}
|
||||
endImplicitObject();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (tag === ',' && !this.looksObjectish(i + 1) && inImplicitObject() && !this.insideForDeclaration && (nextTag !== 'TERMINATOR' || !this.looksObjectish(i + 2))) {
|
||||
offset = nextTag === 'OUTDENT' ? 1 : 0;
|
||||
while (inImplicitObject()) {
|
||||
endImplicitObject(i + offset);
|
||||
}
|
||||
}
|
||||
return forward(1);
|
||||
});
|
||||
}
|
||||
|
||||
addLocationDataToGeneratedTokens() {
|
||||
return this.scanTokens(function(token, i, tokens) {
|
||||
var column, line, nextLocation, prevLocation, ref, ref1;
|
||||
if (token[2]) {
|
||||
return 1;
|
||||
}
|
||||
if (!(token.generated || token.explicit)) {
|
||||
return 1;
|
||||
}
|
||||
if (token[0] === '{' && (nextLocation = (ref = tokens[i + 1]) != null ? ref[2] : void 0)) {
|
||||
({
|
||||
first_line: line,
|
||||
first_column: column
|
||||
} = nextLocation);
|
||||
} else if (prevLocation = (ref1 = tokens[i - 1]) != null ? ref1[2] : void 0) {
|
||||
({
|
||||
last_line: line,
|
||||
last_column: column
|
||||
} = prevLocation);
|
||||
} else {
|
||||
line = column = 0;
|
||||
}
|
||||
token[2] = {
|
||||
first_line: line,
|
||||
first_column: column,
|
||||
last_line: line,
|
||||
last_column: column
|
||||
};
|
||||
return 1;
|
||||
});
|
||||
}
|
||||
|
||||
fixOutdentLocationData() {
|
||||
return this.scanTokens(function(token, i, tokens) {
|
||||
var prevLocationData;
|
||||
if (!(token[0] === 'OUTDENT' || (token.generated && token[0] === 'CALL_END') || (token.generated && token[0] === '}'))) {
|
||||
return 1;
|
||||
}
|
||||
prevLocationData = tokens[i - 1][2];
|
||||
token[2] = {
|
||||
first_line: prevLocationData.last_line,
|
||||
first_column: prevLocationData.last_column,
|
||||
last_line: prevLocationData.last_line,
|
||||
last_column: prevLocationData.last_column
|
||||
};
|
||||
return 1;
|
||||
});
|
||||
}
|
||||
|
||||
normalizeLines() {
|
||||
var action, condition, indent, outdent, starter;
|
||||
starter = indent = outdent = null;
|
||||
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;
|
||||
};
|
||||
action = function(token, i) {
|
||||
return this.tokens.splice((this.tag(i - 1) === ',' ? i - 1 : i), 0, outdent);
|
||||
};
|
||||
return this.scanTokens(function(token, i, tokens) {
|
||||
var j, k, ref, ref1, tag;
|
||||
[tag] = token;
|
||||
if (tag === 'TERMINATOR') {
|
||||
if (this.tag(i + 1) === 'ELSE' && this.tag(i - 1) !== 'OUTDENT') {
|
||||
tokens.splice(i, 1, ...this.indentation());
|
||||
return 1;
|
||||
}
|
||||
if (ref = this.tag(i + 1), indexOf.call(EXPRESSION_CLOSE, ref) >= 0) {
|
||||
tokens.splice(i, 1);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (tag === 'CATCH') {
|
||||
for (j = k = 1; k <= 2; j = ++k) {
|
||||
if (!((ref1 = this.tag(i + j)) === 'OUTDENT' || ref1 === 'TERMINATOR' || ref1 === 'FINALLY')) {
|
||||
continue;
|
||||
}
|
||||
tokens.splice(i + j, 0, ...this.indentation());
|
||||
return 2 + j;
|
||||
}
|
||||
}
|
||||
if (indexOf.call(SINGLE_LINERS, tag) >= 0 && this.tag(i + 1) !== 'INDENT' && !(tag === 'ELSE' && this.tag(i + 1) === 'IF')) {
|
||||
starter = tag;
|
||||
[indent, outdent] = this.indentation(tokens[i]);
|
||||
if (starter === 'THEN') {
|
||||
indent.fromThen = true;
|
||||
}
|
||||
tokens.splice(i + 1, 0, indent);
|
||||
this.detectEnd(i + 2, condition, action);
|
||||
if (tag === 'THEN') {
|
||||
tokens.splice(i, 1);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 1;
|
||||
});
|
||||
}
|
||||
|
||||
tagPostfixConditionals() {
|
||||
var action, condition, original;
|
||||
original = null;
|
||||
condition = function(token, i) {
|
||||
var prevTag, tag;
|
||||
[tag] = token;
|
||||
[prevTag] = this.tokens[i - 1];
|
||||
return tag === 'TERMINATOR' || (tag === 'INDENT' && indexOf.call(SINGLE_LINERS, prevTag) < 0);
|
||||
};
|
||||
action = function(token, i) {
|
||||
if (token[0] !== 'INDENT' || (token.generated && !token.fromThen)) {
|
||||
return original[0] = 'POST_' + original[0];
|
||||
}
|
||||
};
|
||||
return this.scanTokens(function(token, i) {
|
||||
if (token[0] !== 'IF') {
|
||||
return 1;
|
||||
}
|
||||
original = token;
|
||||
this.detectEnd(i + 1, condition, action);
|
||||
return 1;
|
||||
});
|
||||
}
|
||||
|
||||
indentation(origin) {
|
||||
var indent, outdent;
|
||||
indent = ['INDENT', 2];
|
||||
outdent = ['OUTDENT', 2];
|
||||
if (origin) {
|
||||
indent.generated = outdent.generated = true;
|
||||
indent.origin = outdent.origin = origin;
|
||||
} else {
|
||||
indent.explicit = outdent.explicit = true;
|
||||
}
|
||||
return [indent, outdent];
|
||||
}
|
||||
|
||||
tag(i) {
|
||||
var ref;
|
||||
return (ref = this.tokens[i]) != null ? ref[0] : void 0;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
Rewriter.prototype.generate = generate;
|
||||
|
||||
return Rewriter;
|
||||
|
||||
})();
|
||||
|
||||
BALANCED_PAIRS = [['(', ')'], ['[', ']'], ['{', '}'], ['INDENT', 'OUTDENT'], ['CALL_START', 'CALL_END'], ['PARAM_START', 'PARAM_END'], ['INDEX_START', 'INDEX_END'], ['STRING_START', 'STRING_END'], ['REGEX_START', 'REGEX_END']];
|
||||
|
||||
exports.INVERSES = INVERSES = {};
|
||||
|
||||
EXPRESSION_START = [];
|
||||
|
||||
EXPRESSION_END = [];
|
||||
|
||||
for (k = 0, len = BALANCED_PAIRS.length; k < len; k++) {
|
||||
[left, rite] = BALANCED_PAIRS[k];
|
||||
EXPRESSION_START.push(INVERSES[rite] = left);
|
||||
EXPRESSION_END.push(INVERSES[left] = rite);
|
||||
}
|
||||
|
||||
EXPRESSION_CLOSE = ['CATCH', 'THEN', 'ELSE', 'FINALLY'].concat(EXPRESSION_END);
|
||||
|
||||
IMPLICIT_FUNC = ['IDENTIFIER', 'PROPERTY', 'SUPER', ')', 'CALL_END', ']', 'INDEX_END', '@', 'THIS'];
|
||||
|
||||
IMPLICIT_CALL = ['IDENTIFIER', 'PROPERTY', 'NUMBER', 'INFINITY', 'NAN', 'STRING', 'STRING_START', 'REGEX', 'REGEX_START', 'JS', 'NEW', 'PARAM_START', 'CLASS', 'IF', 'TRY', 'SWITCH', 'THIS', 'UNDEFINED', 'NULL', 'BOOL', 'UNARY', 'YIELD', 'AWAIT', 'UNARY_MATH', 'SUPER', 'THROW', '@', '->', '=>', '[', '(', '{', '--', '++'];
|
||||
|
||||
IMPLICIT_UNSPACED_CALL = ['+', '-'];
|
||||
|
||||
IMPLICIT_END = ['POST_IF', 'FOR', 'WHILE', 'UNTIL', 'WHEN', 'BY', 'LOOP', 'TERMINATOR'];
|
||||
|
||||
SINGLE_LINERS = ['ELSE', '->', '=>', 'TRY', 'FINALLY', 'THEN'];
|
||||
|
||||
SINGLE_CLOSERS = ['TERMINATOR', 'CATCH', 'FINALLY', 'ELSE', 'OUTDENT', 'LEADING_WHEN'];
|
||||
|
||||
LINEBREAKS = ['TERMINATOR', 'INDENT', 'OUTDENT'];
|
||||
|
||||
CALL_CLOSERS = ['.', '?.', '::', '?::'];
|
||||
|
||||
}).call(this);
|
||||
@@ -1,10 +1,10 @@
|
||||
// Generated by CoffeeScript 1.12.5
|
||||
// Generated by CoffeeScript 2.0.0-beta1
|
||||
(function() {
|
||||
var Scope,
|
||||
indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
|
||||
|
||||
exports.Scope = Scope = (function() {
|
||||
function Scope(parent, expressions, method, referencedVars) {
|
||||
exports.Scope = Scope = class Scope {
|
||||
constructor(parent, expressions, method, referencedVars) {
|
||||
var ref, ref1;
|
||||
this.parent = parent;
|
||||
this.expressions = expressions;
|
||||
@@ -23,56 +23,47 @@
|
||||
this.root = (ref = (ref1 = this.parent) != null ? ref1.root : void 0) != null ? ref : this;
|
||||
}
|
||||
|
||||
Scope.prototype.add = function(name, type, immediate) {
|
||||
add(name, type, immediate) {
|
||||
if (this.shared && !immediate) {
|
||||
return this.parent.add(name, type, immediate);
|
||||
}
|
||||
if (Object.prototype.hasOwnProperty.call(this.positions, name)) {
|
||||
return this.variables[this.positions[name]].type = type;
|
||||
} else {
|
||||
return this.positions[name] = this.variables.push({
|
||||
name: name,
|
||||
type: type
|
||||
}) - 1;
|
||||
return this.positions[name] = this.variables.push({name, type}) - 1;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Scope.prototype.namedMethod = function() {
|
||||
namedMethod() {
|
||||
var ref;
|
||||
if (((ref = this.method) != null ? ref.name : void 0) || !this.parent) {
|
||||
return this.method;
|
||||
}
|
||||
return this.parent.namedMethod();
|
||||
};
|
||||
}
|
||||
|
||||
Scope.prototype.find = function(name, type) {
|
||||
if (type == null) {
|
||||
type = 'var';
|
||||
}
|
||||
find(name, type = 'var') {
|
||||
if (this.check(name)) {
|
||||
return true;
|
||||
}
|
||||
this.add(name, type);
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
Scope.prototype.parameter = function(name) {
|
||||
parameter(name) {
|
||||
if (this.shared && this.parent.check(name, true)) {
|
||||
return;
|
||||
}
|
||||
return this.add(name, 'param');
|
||||
};
|
||||
}
|
||||
|
||||
Scope.prototype.check = function(name) {
|
||||
check(name) {
|
||||
var ref;
|
||||
return !!(this.type(name) || ((ref = this.parent) != null ? ref.check(name) : void 0));
|
||||
};
|
||||
}
|
||||
|
||||
Scope.prototype.temporary = function(name, index, single) {
|
||||
temporary(name, index, single = false) {
|
||||
var diff, endCode, letter, newCode, num, startCode;
|
||||
if (single == null) {
|
||||
single = false;
|
||||
}
|
||||
if (single) {
|
||||
startCode = name.charCodeAt(0);
|
||||
endCode = 'z'.charCodeAt(0);
|
||||
@@ -80,13 +71,13 @@
|
||||
newCode = startCode + index % (diff + 1);
|
||||
letter = String.fromCharCode(newCode);
|
||||
num = Math.floor(index / (diff + 1));
|
||||
return "" + letter + (num || '');
|
||||
return `${letter}${num || ''}`;
|
||||
} else {
|
||||
return "" + name + (index || '');
|
||||
return `${name}${index || ''}`;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Scope.prototype.type = function(name) {
|
||||
type(name) {
|
||||
var i, len, ref, v;
|
||||
ref = this.variables;
|
||||
for (i = 0, len = ref.length; i < len; i++) {
|
||||
@@ -96,13 +87,10 @@
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
}
|
||||
|
||||
Scope.prototype.freeVariable = function(name, options) {
|
||||
freeVariable(name, options = {}) {
|
||||
var index, ref, temp;
|
||||
if (options == null) {
|
||||
options = {};
|
||||
}
|
||||
index = 0;
|
||||
while (true) {
|
||||
temp = this.temporary(name, index, options.single);
|
||||
@@ -115,21 +103,21 @@
|
||||
this.add(temp, 'var', true);
|
||||
}
|
||||
return temp;
|
||||
};
|
||||
}
|
||||
|
||||
Scope.prototype.assign = function(name, value) {
|
||||
assign(name, value) {
|
||||
this.add(name, {
|
||||
value: value,
|
||||
value,
|
||||
assigned: true
|
||||
}, true);
|
||||
return this.hasAssignments = true;
|
||||
};
|
||||
}
|
||||
|
||||
Scope.prototype.hasDeclarations = function() {
|
||||
hasDeclarations() {
|
||||
return !!this.declaredVariables().length;
|
||||
};
|
||||
}
|
||||
|
||||
Scope.prototype.declaredVariables = function() {
|
||||
declaredVariables() {
|
||||
var v;
|
||||
return ((function() {
|
||||
var i, len, ref, results;
|
||||
@@ -143,23 +131,21 @@
|
||||
}
|
||||
return results;
|
||||
}).call(this)).sort();
|
||||
};
|
||||
}
|
||||
|
||||
Scope.prototype.assignedVariables = function() {
|
||||
assignedVariables() {
|
||||
var i, len, ref, results, v;
|
||||
ref = this.variables;
|
||||
results = [];
|
||||
for (i = 0, len = ref.length; i < len; i++) {
|
||||
v = ref[i];
|
||||
if (v.type.assigned) {
|
||||
results.push(v.name + " = " + v.type.value);
|
||||
results.push(`${v.name} = ${v.type.value}`);
|
||||
}
|
||||
}
|
||||
return results;
|
||||
};
|
||||
}
|
||||
|
||||
return Scope;
|
||||
|
||||
})();
|
||||
};
|
||||
|
||||
}).call(this);
|
||||
147
lib/coffeescript/sourcemap.js
Normal file
147
lib/coffeescript/sourcemap.js
Normal file
@@ -0,0 +1,147 @@
|
||||
// Generated by CoffeeScript 2.0.0-beta1
|
||||
(function() {
|
||||
var LineMap, SourceMap;
|
||||
|
||||
LineMap = class LineMap {
|
||||
constructor(line1) {
|
||||
this.line = line1;
|
||||
this.columns = [];
|
||||
}
|
||||
|
||||
add(column, [sourceLine, sourceColumn], options = {}) {
|
||||
if (this.columns[column] && options.noReplace) {
|
||||
return;
|
||||
}
|
||||
return this.columns[column] = {
|
||||
line: this.line,
|
||||
column,
|
||||
sourceLine,
|
||||
sourceColumn
|
||||
};
|
||||
}
|
||||
|
||||
sourceLocation(column) {
|
||||
var mapping;
|
||||
while (!((mapping = this.columns[column]) || (column <= 0))) {
|
||||
column--;
|
||||
}
|
||||
return mapping && [mapping.sourceLine, mapping.sourceColumn];
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
SourceMap = (function() {
|
||||
var BASE64_CHARS, VLQ_CONTINUATION_BIT, VLQ_SHIFT, VLQ_VALUE_MASK;
|
||||
|
||||
class SourceMap {
|
||||
constructor() {
|
||||
this.lines = [];
|
||||
}
|
||||
|
||||
add(sourceLocation, generatedLocation, options = {}) {
|
||||
var base, column, line, lineMap;
|
||||
[line, column] = generatedLocation;
|
||||
lineMap = ((base = this.lines)[line] || (base[line] = new LineMap(line)));
|
||||
return lineMap.add(column, sourceLocation, options);
|
||||
}
|
||||
|
||||
sourceLocation([line, column]) {
|
||||
var lineMap;
|
||||
while (!((lineMap = this.lines[line]) || (line <= 0))) {
|
||||
line--;
|
||||
}
|
||||
return lineMap && lineMap.sourceLocation(column);
|
||||
}
|
||||
|
||||
generate(options = {}, code = null) {
|
||||
var buffer, i, j, lastColumn, lastSourceColumn, lastSourceLine, len, len1, lineMap, lineNumber, mapping, needComma, ref, ref1, v3, writingline;
|
||||
writingline = 0;
|
||||
lastColumn = 0;
|
||||
lastSourceLine = 0;
|
||||
lastSourceColumn = 0;
|
||||
needComma = false;
|
||||
buffer = "";
|
||||
ref = this.lines;
|
||||
for (lineNumber = i = 0, len = ref.length; i < len; lineNumber = ++i) {
|
||||
lineMap = ref[lineNumber];
|
||||
if (lineMap) {
|
||||
ref1 = lineMap.columns;
|
||||
for (j = 0, len1 = ref1.length; j < len1; j++) {
|
||||
mapping = ref1[j];
|
||||
if (!(mapping)) {
|
||||
continue;
|
||||
}
|
||||
while (writingline < mapping.line) {
|
||||
lastColumn = 0;
|
||||
needComma = false;
|
||||
buffer += ";";
|
||||
writingline++;
|
||||
}
|
||||
if (needComma) {
|
||||
buffer += ",";
|
||||
needComma = false;
|
||||
}
|
||||
buffer += this.encodeVlq(mapping.column - lastColumn);
|
||||
lastColumn = mapping.column;
|
||||
buffer += this.encodeVlq(0);
|
||||
buffer += this.encodeVlq(mapping.sourceLine - lastSourceLine);
|
||||
lastSourceLine = mapping.sourceLine;
|
||||
buffer += this.encodeVlq(mapping.sourceColumn - lastSourceColumn);
|
||||
lastSourceColumn = mapping.sourceColumn;
|
||||
needComma = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
v3 = {
|
||||
version: 3,
|
||||
file: options.generatedFile || '',
|
||||
sourceRoot: options.sourceRoot || '',
|
||||
sources: options.sourceFiles || [''],
|
||||
names: [],
|
||||
mappings: buffer
|
||||
};
|
||||
if (options.inlineMap) {
|
||||
v3.sourcesContent = [code];
|
||||
}
|
||||
return v3;
|
||||
}
|
||||
|
||||
encodeVlq(value) {
|
||||
var answer, nextChunk, signBit, valueToEncode;
|
||||
answer = '';
|
||||
signBit = value < 0 ? 1 : 0;
|
||||
valueToEncode = (Math.abs(value) << 1) + signBit;
|
||||
while (valueToEncode || !answer) {
|
||||
nextChunk = valueToEncode & VLQ_VALUE_MASK;
|
||||
valueToEncode = valueToEncode >> VLQ_SHIFT;
|
||||
if (valueToEncode) {
|
||||
nextChunk |= VLQ_CONTINUATION_BIT;
|
||||
}
|
||||
answer += this.encodeBase64(nextChunk);
|
||||
}
|
||||
return answer;
|
||||
}
|
||||
|
||||
encodeBase64(value) {
|
||||
return BASE64_CHARS[value] || (function() {
|
||||
throw new Error(`Cannot Base64 encode value: ${value}`);
|
||||
})();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
VLQ_SHIFT = 5;
|
||||
|
||||
VLQ_CONTINUATION_BIT = 1 << VLQ_SHIFT;
|
||||
|
||||
VLQ_VALUE_MASK = VLQ_CONTINUATION_BIT - 1;
|
||||
|
||||
BASE64_CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
|
||||
|
||||
return SourceMap;
|
||||
|
||||
})();
|
||||
|
||||
module.exports = SourceMap;
|
||||
|
||||
}).call(this);
|
||||
16
package.json
16
package.json
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "coffee-script",
|
||||
"name": "coffeescript",
|
||||
"description": "Unfancy JavaScript",
|
||||
"keywords": [
|
||||
"javascript",
|
||||
@@ -8,15 +8,15 @@
|
||||
"compiler"
|
||||
],
|
||||
"author": "Jeremy Ashkenas",
|
||||
"version": "1.12.5",
|
||||
"version": "2.0.0-beta1",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.8.0"
|
||||
"node": ">=7.6.0"
|
||||
},
|
||||
"directories": {
|
||||
"lib": "./lib/coffee-script"
|
||||
"lib": "./lib/coffeescript"
|
||||
},
|
||||
"main": "./lib/coffee-script/coffee-script",
|
||||
"main": "./lib/coffeescript/coffeescript",
|
||||
"bin": {
|
||||
"coffee": "./bin/coffee",
|
||||
"cake": "./bin/cake"
|
||||
@@ -40,10 +40,12 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"docco": "~0.7.0",
|
||||
"google-closure-compiler-js": "^20170218.0.0",
|
||||
"google-closure-compiler-js": "^20170409.0.0",
|
||||
"highlight.js": "~9.10.0",
|
||||
"jison": ">=0.4.17",
|
||||
"markdown-it": "^8.3.1",
|
||||
"underscore": "~1.8.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"markdown-it": "^8.3.1"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
require('./lib/coffee-script/register');
|
||||
require('./lib/coffeescript/register');
|
||||
|
||||
2
repl.js
2
repl.js
@@ -1 +1 @@
|
||||
module.exports = require('./lib/coffee-script/repl');
|
||||
module.exports = require('./lib/coffeescript/repl');
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
# We add support for loading remote Coffee scripts via **XHR**, and
|
||||
# `text/coffeescript` script tags, source maps via data-URLs, and so on.
|
||||
|
||||
CoffeeScript = require './coffee-script'
|
||||
CoffeeScript = require './coffeescript'
|
||||
CoffeeScript.require = require
|
||||
compile = CoffeeScript.compile
|
||||
|
||||
@@ -69,6 +69,7 @@ runScripts = ->
|
||||
options = literate: script.type is coffeetypes[1]
|
||||
source = script.src or script.getAttribute('data-src')
|
||||
if source
|
||||
options.filename = source
|
||||
CoffeeScript.load source,
|
||||
(param) ->
|
||||
coffees[i] = param
|
||||
@@ -76,6 +77,12 @@ runScripts = ->
|
||||
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 = if script.id and script.id isnt '' then script.id else "coffeescript#{if i isnt 0 then i else ''}"
|
||||
options.sourceFiles = ['embedded']
|
||||
coffees[i] = [script.innerHTML, options]
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ fs = require 'fs'
|
||||
path = require 'path'
|
||||
helpers = require './helpers'
|
||||
optparse = require './optparse'
|
||||
CoffeeScript = require './coffee-script'
|
||||
CoffeeScript = require './coffeescript'
|
||||
|
||||
# Register .coffee extension
|
||||
CoffeeScript.register()
|
||||
|
||||
@@ -11,7 +11,7 @@ path = require 'path'
|
||||
helpers = require './helpers'
|
||||
SourceMap = require './sourcemap'
|
||||
# Require `package.json`, which is two levels above this file, as this file is
|
||||
# evaluated from `lib/coffee-script`.
|
||||
# evaluated from `lib/coffeescript`.
|
||||
packageJson = require '../../package.json'
|
||||
|
||||
# The current CoffeeScript version number.
|
||||
@@ -25,7 +25,7 @@ exports.helpers = helpers
|
||||
# Function that allows for btoa in both nodejs and the browser.
|
||||
base64encode = (src) -> switch
|
||||
when typeof Buffer is 'function'
|
||||
new Buffer(src).toString('base64')
|
||||
Buffer.from(src).toString('base64')
|
||||
when typeof btoa is 'function'
|
||||
# The contents of a `<script>` block are encoded via UTF-16, so if any extended
|
||||
# characters are used in the block, btoa will fail as it maxes out at UTF-8.
|
||||
@@ -230,7 +230,7 @@ if require.extensions
|
||||
for ext in @FILE_EXTENSIONS then do (ext) ->
|
||||
require.extensions[ext] ?= ->
|
||||
throw new Error """
|
||||
Use CoffeeScript.register() or require the coffee-script/register module to require #{ext} files.
|
||||
Use CoffeeScript.register() or require the coffeescript/register module to require #{ext} files.
|
||||
"""
|
||||
|
||||
exports._compileFile = (filename, sourceMap = no, inlineMap = no) ->
|
||||
@@ -9,7 +9,7 @@ fs = require 'fs'
|
||||
path = require 'path'
|
||||
helpers = require './helpers'
|
||||
optparse = require './optparse'
|
||||
CoffeeScript = require './coffee-script'
|
||||
CoffeeScript = require './coffeescript'
|
||||
{spawn, exec} = require 'child_process'
|
||||
{EventEmitter} = require 'events'
|
||||
|
||||
@@ -47,7 +47,7 @@ SWITCHES = [
|
||||
['-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 coffee-script']
|
||||
['-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']
|
||||
|
||||
@@ -89,7 +89,12 @@ grammar =
|
||||
Line: [
|
||||
o 'Expression'
|
||||
o 'Statement'
|
||||
o 'FuncDirective'
|
||||
]
|
||||
|
||||
FuncDirective: [
|
||||
o 'YieldReturn'
|
||||
o 'AwaitReturn'
|
||||
]
|
||||
|
||||
# Pure statements which cannot be expressions.
|
||||
@@ -219,17 +224,22 @@ grammar =
|
||||
o 'YIELD RETURN', -> new YieldReturn
|
||||
]
|
||||
|
||||
AwaitReturn: [
|
||||
o 'AWAIT RETURN Expression', -> new AwaitReturn $3
|
||||
o 'AWAIT RETURN', -> new AwaitReturn
|
||||
]
|
||||
|
||||
|
||||
# A block comment.
|
||||
Comment: [
|
||||
o 'HERECOMMENT', -> new Comment $1
|
||||
]
|
||||
|
||||
# The **Code** node is the function literal. It's defined by an indented block
|
||||
# of **Block** preceded by a function arrow, with an optional parameter
|
||||
# list.
|
||||
# of **Block** preceded by a function arrow, with an optional parameter list.
|
||||
Code: [
|
||||
o 'PARAM_START ParamList PARAM_END FuncGlyph Block', -> new Code $2, $5, $4
|
||||
o 'FuncGlyph Block', -> new Code [], $2, $1
|
||||
o 'FuncGlyph Block', -> new Code [], $2, $1
|
||||
]
|
||||
|
||||
# CoffeeScript has two different symbols for functions. `->` is for ordinary
|
||||
@@ -299,6 +309,13 @@ grammar =
|
||||
o 'Parenthetical', -> new Value $1
|
||||
o 'Range', -> new Value $1
|
||||
o 'This'
|
||||
o 'Super'
|
||||
]
|
||||
|
||||
# A `super`-based expression that can be used as a value.
|
||||
Super: [
|
||||
o 'SUPER . Property', -> new Super LOC(3) new Access $3
|
||||
o 'SUPER INDEX_START Expression INDEX_END', -> new Super LOC(3) new Index $3
|
||||
]
|
||||
|
||||
# The general group of accessors into an object, by property, by prototype
|
||||
@@ -420,12 +437,7 @@ grammar =
|
||||
o 'Value OptFuncExist String', -> new TaggedTemplateCall $1, $3, $2
|
||||
o 'Value OptFuncExist Arguments', -> new Call $1, $3, $2
|
||||
o 'Invocation OptFuncExist Arguments', -> new Call $1, $3, $2
|
||||
o 'Super'
|
||||
]
|
||||
|
||||
Super: [
|
||||
o 'SUPER', -> new SuperCall
|
||||
o 'SUPER Arguments', -> new SuperCall $2
|
||||
o 'SUPER OptFuncExist Arguments', -> new SuperCall LOC(1)(new Super), $3, $2
|
||||
]
|
||||
|
||||
# An optional existence check on a function.
|
||||
@@ -652,6 +664,8 @@ grammar =
|
||||
o '- Expression', (-> new Op '-', $2), prec: 'UNARY_MATH'
|
||||
o '+ Expression', (-> new Op '+', $2), prec: 'UNARY_MATH'
|
||||
|
||||
o 'AWAIT Expression', -> new Op $1 , $2
|
||||
|
||||
o '-- SimpleAssignable', -> new Op '--', $2
|
||||
o '++ SimpleAssignable', -> new Op '++', $2
|
||||
o 'SimpleAssignable --', -> new Op '--', $1, null, true
|
||||
@@ -706,6 +720,7 @@ operators = [
|
||||
['nonassoc', '++', '--']
|
||||
['left', '?']
|
||||
['right', 'UNARY']
|
||||
['right', 'AWAIT']
|
||||
['right', '**']
|
||||
['right', 'UNARY_MATH']
|
||||
['left', 'MATH']
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
# the **Lexer**, **Rewriter**, and the **Nodes**. Merge objects, flatten
|
||||
# arrays, count characters, that sort of thing.
|
||||
|
||||
md = require('markdown-it')()
|
||||
|
||||
# Peek at the beginning of a given string to see if it matches a sequence.
|
||||
exports.starts = (string, literal, start) ->
|
||||
literal is string.substr start, literal.length
|
||||
@@ -67,19 +69,21 @@ exports.some = Array::some ? (fn) ->
|
||||
return true for e in this when fn e
|
||||
false
|
||||
|
||||
# Simple function for inverting Literate CoffeeScript code by putting the
|
||||
# documentation in comments, producing a string of CoffeeScript code that
|
||||
# can be compiled "normally".
|
||||
# Simple function for extracting code from Literate CoffeeScript by stripping
|
||||
# out all non-code blocks, producing a string of CoffeeScript code that can
|
||||
# be compiled “normally.” Uses [MarkdownIt](https://markdown-it.github.io/)
|
||||
# to tell the difference between Markdown and code blocks.
|
||||
exports.invertLiterate = (code) ->
|
||||
maybe_code = true
|
||||
lines = for line in code.split('\n')
|
||||
if maybe_code and /^([ ]{4}|[ ]{0,3}\t)/.test line
|
||||
line
|
||||
else if maybe_code = /^\s*$/.test line
|
||||
line
|
||||
else
|
||||
'# ' + line
|
||||
lines.join '\n'
|
||||
out = []
|
||||
md.renderer.rules =
|
||||
# Delete all other rules, since all we want are the code blocks.
|
||||
code_block: (tokens, idx, options, env, slf) ->
|
||||
startLine = tokens[idx].map[0]
|
||||
lines = tokens[idx].content.split '\n'
|
||||
for line, i in lines
|
||||
out[startLine + i] = line
|
||||
md.render code
|
||||
out.join '\n'
|
||||
|
||||
# Merge two jison-style location data objects together.
|
||||
# If `last` is not provided, this will simply return `first`.
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
# Loader for CoffeeScript as a Node.js library.
|
||||
exports[key] = val for key, val of require './coffee-script'
|
||||
exports[key] = val for key, val of require './coffeescript'
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#
|
||||
# where locationData is {first_line, first_column, last_line, last_column}, which is a
|
||||
# format that can be fed directly into [Jison](http://github.com/zaach/jison). These
|
||||
# are read by jison in the `parser.lexer` function defined in coffee-script.coffee.
|
||||
# are read by jison in the `parser.lexer` function defined in coffeescript.coffee.
|
||||
|
||||
{Rewriter, INVERSES} = require './rewriter'
|
||||
|
||||
@@ -40,6 +40,7 @@ exports.Lexer = class Lexer
|
||||
@indebt = 0 # The over-indentation at the current level.
|
||||
@outdebt = 0 # The under-outdentation at the current level.
|
||||
@indents = [] # The stack of all current indentation levels.
|
||||
@indentLiteral = '' # The indentation
|
||||
@ends = [] # The stack for pairing up tokens.
|
||||
@tokens = [] # Stream of parsed tokens in the form `['TYPE', value, location data]`.
|
||||
@seenFor = no # Used to recognize FORIN, FOROF and FORFROM tokens.
|
||||
@@ -132,7 +133,7 @@ exports.Lexer = class Lexer
|
||||
@token 'DEFAULT', id
|
||||
return id.length
|
||||
|
||||
[..., prev] = @tokens
|
||||
prev = @prev()
|
||||
|
||||
tag =
|
||||
if colon or prev? and
|
||||
@@ -170,6 +171,16 @@ exports.Lexer = class Lexer
|
||||
isForFrom(prev)
|
||||
tag = 'FORFROM'
|
||||
@seenFor = no
|
||||
# Throw an error on attempts to use `get` or `set` as keywords, or
|
||||
# what CoffeeScript would normally interpret as calls to functions named
|
||||
# `get` or `set`, i.e. `get({foo: function () {}})`
|
||||
else if tag is 'PROPERTY' and prev
|
||||
if prev.spaced and prev[0] in CALLABLE and /^[gs]et$/.test(prev[1])
|
||||
@error "'#{prev[1]}' cannot be used as a keyword, or as a function call without parentheses", prev[2]
|
||||
else
|
||||
prevprev = @tokens[@tokens.length - 2]
|
||||
if prev[0] in ['@', 'THIS'] and prevprev and prevprev.spaced and /^[gs]et$/.test(prevprev[1])
|
||||
@error "'#{prevprev[1]}' cannot be used as a keyword, or as a function call without parentheses", prevprev[2]
|
||||
|
||||
if tag is 'IDENTIFIER' and id in RESERVED
|
||||
@error "reserved word '#{id}'", length: id.length
|
||||
@@ -222,9 +233,8 @@ exports.Lexer = class Lexer
|
||||
when 'o' then 8
|
||||
when 'x' then 16
|
||||
else null
|
||||
|
||||
numberValue = if base? then parseInt(number[2..], base) else parseFloat(number)
|
||||
if number.charAt(1) in ['b', 'o']
|
||||
number = "0x#{numberValue.toString 16}"
|
||||
|
||||
tag = if numberValue is Infinity then 'INFINITY' else 'NUMBER'
|
||||
@token tag, number, 0, lexedLength
|
||||
@@ -238,8 +248,9 @@ exports.Lexer = class Lexer
|
||||
|
||||
# If the preceding token is `from` and this is an import or export statement,
|
||||
# properly tag the `from`.
|
||||
if @tokens.length and @value() is 'from' and (@seenImport or @seenExport)
|
||||
@tokens[@tokens.length - 1][0] = 'FROM'
|
||||
prev = @prev()
|
||||
if prev and @value() is 'from' and (@seenImport or @seenExport)
|
||||
prev[0] = 'FROM'
|
||||
|
||||
regex = switch quote
|
||||
when "'" then STRING_SINGLE
|
||||
@@ -319,7 +330,7 @@ exports.Lexer = class Lexer
|
||||
[regex, body, closed] = match
|
||||
@validateEscapes body, isRegex: yes, offsetInChunk: 1
|
||||
index = regex.length
|
||||
[..., prev] = @tokens
|
||||
prev = @prev()
|
||||
if prev
|
||||
if prev.spaced and prev[0] in CALLABLE
|
||||
return 0 if not closed or POSSIBLY_DIVISION.test regex
|
||||
@@ -372,6 +383,16 @@ exports.Lexer = class Lexer
|
||||
size = indent.length - 1 - indent.lastIndexOf '\n'
|
||||
noNewlines = @unfinished()
|
||||
|
||||
newIndentLiteral = if size > 0 then indent[-size..] else ''
|
||||
unless /^(.?)\1*$/.exec newIndentLiteral
|
||||
@error 'mixed indentation', offset: indent.length
|
||||
return indent.length
|
||||
|
||||
minLiteralLength = Math.min newIndentLiteral.length, @indentLiteral.length
|
||||
if newIndentLiteral[...minLiteralLength] isnt @indentLiteral[...minLiteralLength]
|
||||
@error 'indentation mismatch', offset: indent.length
|
||||
return indent.length
|
||||
|
||||
if size - @indebt is @indent
|
||||
if noNewlines then @suppressNewlines() else @newlineToken 0
|
||||
return indent.length
|
||||
@@ -383,6 +404,7 @@ exports.Lexer = class Lexer
|
||||
return indent.length
|
||||
unless @tokens.length
|
||||
@baseIndent = @indent = size
|
||||
@indentLiteral = newIndentLiteral
|
||||
return indent.length
|
||||
diff = size - @indent + @outdebt
|
||||
@token 'INDENT', diff, indent.length - size, size
|
||||
@@ -390,6 +412,7 @@ exports.Lexer = class Lexer
|
||||
@ends.push {tag: 'OUTDENT'}
|
||||
@outdebt = @indebt = 0
|
||||
@indent = size
|
||||
@indentLiteral = newIndentLiteral
|
||||
else if size < @baseIndent
|
||||
@error 'missing indentation', offset: indent.length
|
||||
else
|
||||
@@ -405,12 +428,9 @@ exports.Lexer = class Lexer
|
||||
lastIndent = @indents[@indents.length - 1]
|
||||
if not lastIndent
|
||||
moveOut = 0
|
||||
else if lastIndent is @outdebt
|
||||
moveOut -= @outdebt
|
||||
@outdebt = 0
|
||||
else if lastIndent < @outdebt
|
||||
@outdebt -= lastIndent
|
||||
moveOut -= lastIndent
|
||||
else if @outdebt and moveOut <= @outdebt
|
||||
@outdebt -= moveOut
|
||||
moveOut = 0
|
||||
else
|
||||
dent = @indents.pop() + @outdebt
|
||||
if outdentLength and @chunk[outdentLength] in INDENTABLE_CLOSERS
|
||||
@@ -426,6 +446,7 @@ exports.Lexer = class Lexer
|
||||
|
||||
@token 'TERMINATOR', '\n', outdentLength, 0 unless @tag() is 'TERMINATOR' or noNewlines
|
||||
@indent = decreasedIndent
|
||||
@indentLiteral = @indentLiteral[...decreasedIndent]
|
||||
this
|
||||
|
||||
# Matches and consumes non-meaningful whitespace. Tag the previous token
|
||||
@@ -433,7 +454,7 @@ exports.Lexer = class Lexer
|
||||
whitespaceToken: ->
|
||||
return 0 unless (match = WHITESPACE.exec @chunk) or
|
||||
(nline = @chunk.charAt(0) is '\n')
|
||||
[..., prev] = @tokens
|
||||
prev = @prev()
|
||||
prev[if match then 'spaced' else 'newLine'] = true if prev
|
||||
if match then match[0].length else 0
|
||||
|
||||
@@ -461,7 +482,7 @@ exports.Lexer = class Lexer
|
||||
else
|
||||
value = @chunk.charAt 0
|
||||
tag = value
|
||||
[..., prev] = @tokens
|
||||
prev = @prev()
|
||||
|
||||
if prev and value in ['=', COMPOUND_ASSIGN...]
|
||||
skipToken = false
|
||||
@@ -755,6 +776,10 @@ exports.Lexer = class Lexer
|
||||
[..., token] = @tokens
|
||||
token?[1]
|
||||
|
||||
# Get the previous token in the token stream.
|
||||
prev: ->
|
||||
@tokens[@tokens.length - 1]
|
||||
|
||||
# Are we in the midst of an unfinished expression?
|
||||
unfinished: ->
|
||||
LINE_CONTINUER.test(@chunk) or
|
||||
@@ -864,7 +889,7 @@ isForFrom = (prev) ->
|
||||
JS_KEYWORDS = [
|
||||
'true', 'false', 'null', 'this'
|
||||
'new', 'delete', 'typeof', 'in', 'instanceof'
|
||||
'return', 'throw', 'break', 'continue', 'debugger', 'yield'
|
||||
'return', 'throw', 'break', 'continue', 'debugger', 'yield', 'await'
|
||||
'if', 'else', 'switch', 'for', 'while', 'do', 'try', 'catch', 'finally'
|
||||
'class', 'extends', 'super'
|
||||
'import', 'export', 'default'
|
||||
|
||||
1506
src/nodes.coffee
1506
src/nodes.coffee
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,4 @@
|
||||
CoffeeScript = require './coffee-script'
|
||||
CoffeeScript = require './coffeescript'
|
||||
child_process = require 'child_process'
|
||||
helpers = require './helpers'
|
||||
path = require 'path'
|
||||
|
||||
@@ -2,7 +2,7 @@ fs = require 'fs'
|
||||
path = require 'path'
|
||||
vm = require 'vm'
|
||||
nodeREPL = require 'repl'
|
||||
CoffeeScript = require './coffee-script'
|
||||
CoffeeScript = require './coffeescript'
|
||||
{merge, updateSyntaxError} = require './helpers'
|
||||
|
||||
replDefaults =
|
||||
@@ -109,7 +109,7 @@ addHistory = (repl, filename, maxSize) ->
|
||||
size = Math.min maxSize, stat.size
|
||||
# Read last `size` bytes from the file
|
||||
readFd = fs.openSync filename, 'r'
|
||||
buffer = new Buffer(size)
|
||||
buffer = Buffer.alloc size
|
||||
fs.readSync readFd, buffer, 0, size, stat.size - size
|
||||
fs.closeSync readFd
|
||||
# Set the history on the interpreter
|
||||
@@ -147,8 +147,8 @@ module.exports =
|
||||
start: (opts = {}) ->
|
||||
[major, minor, build] = process.versions.node.split('.').map (n) -> parseInt(n)
|
||||
|
||||
if major is 0 and minor < 8
|
||||
console.warn "Node 0.8.0+ required for CoffeeScript REPL"
|
||||
if major < 6
|
||||
console.warn "Node 6+ required for CoffeeScript REPL"
|
||||
process.exit 1
|
||||
|
||||
CoffeeScript.register()
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user