mirror of
https://github.com/jashkenas/coffeescript.git
synced 2026-01-13 08:47:55 -05:00
Compare commits
185 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b51361abe7 | ||
|
|
519248fc7d | ||
|
|
6b4f166eb9 | ||
|
|
4f365524d7 | ||
|
|
8d32c713c5 | ||
|
|
76cf769abf | ||
|
|
44bf59923e | ||
|
|
d535a78e32 | ||
|
|
3ad26de8f0 | ||
|
|
3d39d205d8 | ||
|
|
6fd58ef11c | ||
|
|
f557c0579b | ||
|
|
20b8362887 | ||
|
|
726c0858e4 | ||
|
|
887a6174e9 | ||
|
|
ed6733d177 | ||
|
|
d572d744eb | ||
|
|
e82de9c0f6 | ||
|
|
f5073fa132 | ||
|
|
f9c3316aa5 | ||
|
|
ff13d85625 | ||
|
|
c4f1fe7132 | ||
|
|
b0946c3c60 | ||
|
|
b90bc2459a | ||
|
|
07f644c392 | ||
|
|
2fd9ee403c | ||
|
|
389ce89555 | ||
|
|
75d376f2ef | ||
|
|
3136bde928 | ||
|
|
26a7ba1659 | ||
|
|
9cef39d21a | ||
|
|
92ad04b9b1 | ||
|
|
6fe980e569 | ||
|
|
bb8df1e052 | ||
|
|
61d408f093 | ||
|
|
ba41b4417d | ||
|
|
33bbef963c | ||
|
|
c4f0c9ed06 | ||
|
|
8677a0dbc4 | ||
|
|
ee2a107f3c | ||
|
|
8fb5c1ba4f | ||
|
|
b2b2f97873 | ||
|
|
0045cb21ba | ||
|
|
a8273bf980 | ||
|
|
3e7c570679 | ||
|
|
a34c0c9502 | ||
|
|
2ab714b4fe | ||
|
|
56eec0bc4e | ||
|
|
f528e5e754 | ||
|
|
bdcb2c73af | ||
|
|
9b37f16f11 | ||
|
|
26351096a6 | ||
|
|
a091bb82f9 | ||
|
|
a6d4bf1982 | ||
|
|
0e51cdaccd | ||
|
|
d4b7bd3a1f | ||
|
|
559e735994 | ||
|
|
09caa217c2 | ||
|
|
a35df430db | ||
|
|
05d45e9b27 | ||
|
|
69521b97ce | ||
|
|
c7e538a624 | ||
|
|
44be72a4d9 | ||
|
|
9cfcf8623c | ||
|
|
25c23786af | ||
|
|
47bf5d962b | ||
|
|
a30e6807b1 | ||
|
|
d735c81da0 | ||
|
|
f56515b100 | ||
|
|
74d6635f95 | ||
|
|
e8d0deae78 | ||
|
|
95d6ec7492 | ||
|
|
09c95394e1 | ||
|
|
ddb5dac49d | ||
|
|
265b251a7d | ||
|
|
7539f7af2e | ||
|
|
2f27225e8c | ||
|
|
99ad0cc16c | ||
|
|
70c2c4706f | ||
|
|
9d1af43c91 | ||
|
|
c6fdde8834 | ||
|
|
0174ee082c | ||
|
|
82b7bd3a92 | ||
|
|
1f22c16bee | ||
|
|
f33d4dd4f1 | ||
|
|
9c913f86fa | ||
|
|
f0bb59790a | ||
|
|
391fcc4afa | ||
|
|
7b2fb18a0b | ||
|
|
5596a5c209 | ||
|
|
71750554c3 | ||
|
|
0574b664e8 | ||
|
|
ca0ac814b3 | ||
|
|
c0b3217766 | ||
|
|
12a5271489 | ||
|
|
f4fcf65750 | ||
|
|
92f69b2bca | ||
|
|
742224471f | ||
|
|
086430840e | ||
|
|
82f92fea97 | ||
|
|
d23919c430 | ||
|
|
ada35d8951 | ||
|
|
7e0eb6a92d | ||
|
|
28a1a1d304 | ||
|
|
0c2d3673d3 | ||
|
|
e6f6aa8c85 | ||
|
|
c09d8fbedb | ||
|
|
730a4bcdad | ||
|
|
7466c81414 | ||
|
|
b79ea321a3 | ||
|
|
ae2f72e15d | ||
|
|
f6d63776c3 | ||
|
|
b982b7cd0e | ||
|
|
0b5bac666f | ||
|
|
41b31c7293 | ||
|
|
eaeb77a527 | ||
|
|
ec034e2673 | ||
|
|
ff24e5ce52 | ||
|
|
4549f9a4c5 | ||
|
|
d0be6391c6 | ||
|
|
f70f4f09b7 | ||
|
|
3f5abb3c60 | ||
|
|
ca275c2a1c | ||
|
|
99b7826f1b | ||
|
|
806a442894 | ||
|
|
63ffe0aead | ||
|
|
74e0798f89 | ||
|
|
247b511c6a | ||
|
|
6a8e6a4078 | ||
|
|
42402da526 | ||
|
|
42622b15a9 | ||
|
|
1879af6585 | ||
|
|
a7b1fa51e7 | ||
|
|
38c8b2f35f | ||
|
|
4392d26985 | ||
|
|
2f82b75862 | ||
|
|
459814f58d | ||
|
|
088659f893 | ||
|
|
0e37130f2e | ||
|
|
fb539579c3 | ||
|
|
7c54532010 | ||
|
|
5d57ea785c | ||
|
|
94e29c9a95 | ||
|
|
fe7377aed5 | ||
|
|
e934a42e75 | ||
|
|
294bb4754e | ||
|
|
5eab5f1d22 | ||
|
|
8b775c95ad | ||
|
|
251700549a | ||
|
|
3fbf76e135 | ||
|
|
ca04dd6e47 | ||
|
|
a82f869453 | ||
|
|
f932206213 | ||
|
|
849dd53287 | ||
|
|
e03a87da04 | ||
|
|
29aa9b36fe | ||
|
|
c6472fa617 | ||
|
|
1bbbca6496 | ||
|
|
6b1e9bb82b | ||
|
|
eb22196850 | ||
|
|
3b1c49240b | ||
|
|
ea33c28f1b | ||
|
|
7b251f493d | ||
|
|
0be8c5d161 | ||
|
|
617a2d5b65 | ||
|
|
e1625a0d31 | ||
|
|
4c6cc8d060 | ||
|
|
e6153d9841 | ||
|
|
d83b95bd39 | ||
|
|
4ba1be131c | ||
|
|
8dabec0f9b | ||
|
|
e679cbccf7 | ||
|
|
b18e91f936 | ||
|
|
c31a30d3fa | ||
|
|
99b2578aa7 | ||
|
|
ddfde6810c | ||
|
|
71350d67c4 | ||
|
|
13857a5d71 | ||
|
|
6ce1d36acd | ||
|
|
b2669abecc | ||
|
|
db86dc4d8b | ||
|
|
16b4448fe8 | ||
|
|
af82c1f41f | ||
|
|
3e089ca59d | ||
|
|
8a25195442 |
44
.github/workflows/continuous-integration.yml
vendored
Normal file
44
.github/workflows/continuous-integration.yml
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
# Based on https://github.com/actions/starter-workflows/blob/master/ci/node.js.yml
|
||||
|
||||
name: Build and Test
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
ci:
|
||||
runs-on: ${{ matrix.operating-system }}
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
operating-system: [ubuntu-latest, macos-latest, windows-latest]
|
||||
node-version: [12.x, 14.x, 16.x, 17.x]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
cache: 'npm'
|
||||
|
||||
- run: npm ci
|
||||
|
||||
# Ensure that we can still build in the current version of Node
|
||||
- run: node ./bin/cake build:except-parser
|
||||
- run: node ./bin/cake build:parser
|
||||
# Build twice to ensure that the latest build of the compiler can still build itself
|
||||
- run: node ./bin/cake build:except-parser
|
||||
- run: node ./bin/cake build:parser
|
||||
# Build the browser compiler for the headless browser test
|
||||
- run: node ./bin/cake build:browser
|
||||
# Build test.html, so that test:browser uses the latest tests
|
||||
- run: node ./bin/cake doc:test
|
||||
|
||||
# Check that the git diff is clean, to ensure that the updated build output was committed
|
||||
- run: git diff --exit-code
|
||||
|
||||
# Test
|
||||
- run: node ./bin/cake test
|
||||
- run: node ./bin/cake test:browser
|
||||
- run: node ./bin/cake test:browser:node
|
||||
- run: node ./bin/cake test:integrations
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -9,3 +9,4 @@ parser.output
|
||||
/node_modules
|
||||
npm-debug.log*
|
||||
yarn.lock
|
||||
.DS_Store
|
||||
|
||||
20
.travis.yml
20
.travis.yml
@@ -1,20 +0,0 @@
|
||||
language: node_js
|
||||
|
||||
node_js:
|
||||
- 6
|
||||
- 8
|
||||
- 10
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- node_modules
|
||||
|
||||
script:
|
||||
- node ./bin/cake build:except-parser
|
||||
- node ./bin/cake build:parser
|
||||
- node ./bin/cake build:full
|
||||
- node ./bin/cake build:browser
|
||||
- node ./bin/cake test
|
||||
- node --harmony ./bin/cake test
|
||||
- node ./bin/cake test:browser
|
||||
- node ./bin/cake test:integrations
|
||||
145
Cakefile
145
Cakefile
@@ -21,7 +21,7 @@ header = """
|
||||
* CoffeeScript Compiler v#{CoffeeScript.VERSION}
|
||||
* https://coffeescript.org
|
||||
*
|
||||
* Copyright 2011, Jeremy Ashkenas
|
||||
* Copyright 2011-#{new Date().getFullYear()}, Jeremy Ashkenas
|
||||
* Released under the MIT License
|
||||
*/
|
||||
"""
|
||||
@@ -66,18 +66,23 @@ build = (callback) ->
|
||||
buildParser()
|
||||
buildExceptParser callback
|
||||
|
||||
transpile = (code) ->
|
||||
transpile = (code, options = {}) ->
|
||||
options.minify = process.env.MINIFY isnt 'false'
|
||||
options.transform = process.env.TRANSFORM isnt 'false'
|
||||
options.sourceType ?= 'script'
|
||||
babel = require '@babel/core'
|
||||
presets = []
|
||||
# Exclude the `modules` plugin in order to not break the `}(this));`
|
||||
# at the end of the `build:browser` code block.
|
||||
presets.push ['@babel/env', {modules: no}] unless process.env.TRANSFORM is 'false'
|
||||
presets.push ['minify', {mangle: no, evaluate: no, removeUndefined: no}] unless process.env.MINIFY is 'false'
|
||||
presets.push ['@babel/env', {modules: no}] if options.transform
|
||||
presets.push ['minify', {mangle: no, evaluate: no, removeUndefined: no}] if options.minify
|
||||
babelOptions =
|
||||
compact: process.env.MINIFY isnt 'false'
|
||||
presets: presets
|
||||
sourceType: 'script'
|
||||
{ code } = babel.transform code, babelOptions unless presets.length is 0
|
||||
compact: options.minify
|
||||
minified: options.minify
|
||||
comments: not options.minify
|
||||
sourceType: options.sourceType
|
||||
{ code } = babel.transformSync code, babelOptions unless presets.length is 0
|
||||
code
|
||||
|
||||
testBuiltCode = (watch = no) ->
|
||||
@@ -140,13 +145,18 @@ task 'build:browser', 'merge the built scripts into a single file for use in a b
|
||||
return module.exports;
|
||||
})();
|
||||
"""
|
||||
# From here, we generate two outputs: a legacy script output for all browsers
|
||||
# and a module output for browsers that support `<script type="module">`.
|
||||
code = """
|
||||
var CoffeeScript = function() {
|
||||
function require(path){ return require[path]; }
|
||||
#{code}
|
||||
return require['./browser'];
|
||||
}();
|
||||
"""
|
||||
scriptCode = transpile """
|
||||
(function(root) {
|
||||
var CoffeeScript = function() {
|
||||
function require(path){ return require[path]; }
|
||||
#{code}
|
||||
return require['./browser'];
|
||||
}();
|
||||
#{code}
|
||||
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
define(function() { return CoffeeScript; });
|
||||
@@ -155,10 +165,25 @@ task 'build:browser', 'merge the built scripts into a single file for use in a b
|
||||
}
|
||||
}(this));
|
||||
"""
|
||||
code = transpile code
|
||||
outputFolder = "docs/v#{majorVersion}/browser-compiler"
|
||||
fs.mkdirSync outputFolder unless fs.existsSync outputFolder
|
||||
fs.writeFileSync "#{outputFolder}/coffeescript.js", header + '\n' + code
|
||||
moduleCode = transpile """
|
||||
#{code}
|
||||
|
||||
export default CoffeeScript;
|
||||
const { VERSION, compile, eval: evaluate, load, run, runScripts } = CoffeeScript;
|
||||
export { VERSION, compile, evaluate as eval, load, run, runScripts };
|
||||
""", {sourceType: 'module'}
|
||||
outputFolders = [
|
||||
"docs/v#{majorVersion}/browser-compiler-legacy"
|
||||
"docs/v#{majorVersion}/browser-compiler-modern"
|
||||
"lib/coffeescript-browser-compiler-legacy"
|
||||
"lib/coffeescript-browser-compiler-modern"
|
||||
]
|
||||
for outputFolder in outputFolders
|
||||
fs.mkdirSync outputFolder unless fs.existsSync outputFolder
|
||||
fs.writeFileSync "#{outputFolder}/coffeescript.js", """
|
||||
#{header}
|
||||
#{if outputFolder.includes('legacy') then scriptCode else moduleCode}
|
||||
"""
|
||||
|
||||
task 'build:browser:full', 'merge the built scripts into a single file for use in a browser, and test it', ->
|
||||
invoke 'build:browser'
|
||||
@@ -174,11 +199,12 @@ task 'build:watch:harmony', 'watch and continually rebuild the CoffeeScript comp
|
||||
|
||||
buildDocs = (watch = no) ->
|
||||
# Constants
|
||||
indexFile = 'documentation/site/index.html'
|
||||
siteSourceFolder = "documentation/site"
|
||||
sectionsSourceFolder = 'documentation/sections'
|
||||
examplesSourceFolder = 'documentation/examples'
|
||||
outputFolder = "docs/v#{majorVersion}"
|
||||
indexFile = 'documentation/site/index.html'
|
||||
siteSourceFolder = "documentation/site"
|
||||
sectionsSourceFolder = 'documentation/sections'
|
||||
changelogSourceFolder = 'documentation/sections/changelog'
|
||||
examplesSourceFolder = 'documentation/examples'
|
||||
outputFolder = "docs/v#{majorVersion}"
|
||||
|
||||
# Helpers
|
||||
releaseHeader = (date, version, prevVersion) ->
|
||||
@@ -196,11 +222,11 @@ buildDocs = (watch = no) ->
|
||||
markdownRenderer = require('markdown-it')
|
||||
html: yes
|
||||
typographer: yes
|
||||
highlight: (str, lang) ->
|
||||
highlight: (str, language) ->
|
||||
# From https://github.com/markdown-it/markdown-it#syntax-highlighting
|
||||
if lang and hljs.getLanguage(lang)
|
||||
if language and hljs.getLanguage(language)
|
||||
try
|
||||
return hljs.highlight(lang, str).value
|
||||
return hljs.highlight(str, { language }).value
|
||||
catch ex
|
||||
return '' # No syntax highlighting
|
||||
|
||||
@@ -261,7 +287,7 @@ buildDocs = (watch = no) ->
|
||||
catch exception
|
||||
|
||||
if watch
|
||||
for target in [indexFile, siteSourceFolder, examplesSourceFolder, sectionsSourceFolder]
|
||||
for target in [indexFile, siteSourceFolder, examplesSourceFolder, sectionsSourceFolder, changelogSourceFolder]
|
||||
fs.watch target, interval: 200, renderIndex
|
||||
log 'watching...', green
|
||||
|
||||
@@ -284,7 +310,7 @@ buildDocTests = (watch = no) ->
|
||||
# Helpers
|
||||
testsInScriptBlocks = ->
|
||||
output = ''
|
||||
for filename in fs.readdirSync testsSourceFolder
|
||||
for filename in fs.readdirSync(testsSourceFolder).sort()
|
||||
if filename.indexOf('.coffee') isnt -1
|
||||
type = 'coffeescript'
|
||||
else if filename.indexOf('.litcoffee') isnt -1
|
||||
@@ -342,11 +368,13 @@ task 'release', 'build and test the CoffeeScript source, and build the documenta
|
||||
execSync '''
|
||||
cake build:full
|
||||
cake build:browser
|
||||
cake doc:test
|
||||
cake test:browser:node
|
||||
cake test:browser
|
||||
cake test:integrations
|
||||
cake doc:site
|
||||
cake doc:test
|
||||
cake doc:source''', stdio: 'inherit'
|
||||
cake doc:source
|
||||
''', stdio: 'inherit'
|
||||
|
||||
|
||||
task 'bench', 'quick benchmark of compilation time', ->
|
||||
@@ -446,6 +474,9 @@ runTests = (CoffeeScript) ->
|
||||
skipUnless 'var a = 2 ** 2; a **= 3', ['exponentiation.coffee']
|
||||
skipUnless 'var {...a} = {}', ['object_rest_spread.coffee']
|
||||
skipUnless '/foo.bar/s.test("foo\tbar")', ['regex_dotall.coffee']
|
||||
skipUnless '1_2_3', ['numeric_literal_separators.coffee']
|
||||
skipUnless '1n', ['numbers_bigint.coffee']
|
||||
skipUnless 'async () => { await import(\'data:application/json,{"foo":"bar"}\', { assert: { type: "json" } }) }', ['import_assertions.coffee']
|
||||
files = fs.readdirSync('test').filter (filename) ->
|
||||
filename not in testFilesToSkip
|
||||
|
||||
@@ -467,8 +498,54 @@ task 'test', 'run the CoffeeScript language test suite', ->
|
||||
runTests(CoffeeScript).catch -> process.exit 1
|
||||
|
||||
|
||||
task 'test:browser', 'run the test suite against the merged browser script', ->
|
||||
source = fs.readFileSync "docs/v#{majorVersion}/browser-compiler/coffeescript.js", 'utf-8'
|
||||
task 'test:browser', 'run the test suite against the modern browser compiler in a headless browser', ->
|
||||
# Create very simple web server to serve the two files we need.
|
||||
http = require 'http'
|
||||
serveFile = (res, fileToServe, mimeType) ->
|
||||
res.statusCode = 200
|
||||
res.setHeader 'Content-Type', mimeType
|
||||
fs.createReadStream(fileToServe).pipe res
|
||||
server = http.createServer (req, res) ->
|
||||
if req.url is '/'
|
||||
serveFile res, path.join(__dirname, 'docs', "v#{majorVersion}", 'test.html'), 'text/html'
|
||||
else if req.url is '/browser-compiler-modern/coffeescript.js'
|
||||
# The `text/javascript` MIME type is required for an ES module file to be
|
||||
# loaded in a browser.
|
||||
serveFile res, path.join(__dirname, 'docs', "v#{majorVersion}", 'browser-compiler-modern', 'coffeescript.js'), 'text/javascript'
|
||||
else
|
||||
res.statusCode = 404
|
||||
res.end()
|
||||
|
||||
server.listen 8080, ->
|
||||
puppeteer = require 'puppeteer'
|
||||
browser = await puppeteer.launch()
|
||||
page = await browser.newPage()
|
||||
result = ""
|
||||
|
||||
try
|
||||
await page.goto 'http://localhost:8080/'
|
||||
|
||||
element = await page.waitForSelector '#result',
|
||||
visible: yes
|
||||
polling: 'mutation'
|
||||
timeout: 60000
|
||||
|
||||
result = await page.evaluate ((el) => el.textContent), element
|
||||
catch e
|
||||
log e, red
|
||||
finally
|
||||
try browser.close()
|
||||
server.close()
|
||||
|
||||
if result and not result.includes('failed')
|
||||
log result, green
|
||||
else
|
||||
log result, red
|
||||
process.exit 1
|
||||
|
||||
|
||||
task 'test:browser:node', 'run the test suite against the legacy browser compiler in Node', ->
|
||||
source = fs.readFileSync "lib/coffeescript-browser-compiler-legacy/coffeescript.js", 'utf-8'
|
||||
result = {}
|
||||
global.testingBrowser = yes
|
||||
(-> eval source).call result
|
||||
@@ -482,10 +559,16 @@ task 'test:integrations', 'test the module integrated with other libraries and e
|
||||
# can be built by such tools; if such a build succeeds, it verifies that no
|
||||
# Node modules are required as part of the compiler (as opposed to the tests)
|
||||
# and that therefore the compiler will run in a browser environment.
|
||||
# Webpack 5 requires Node >= 10.13.0.
|
||||
[major, minor] = process.versions.node.split('.').map (n) -> parseInt(n, 10)
|
||||
return if major < 10 or (major is 10 and minor < 13)
|
||||
tmpdir = os.tmpdir()
|
||||
webpack = require 'webpack'
|
||||
webpack {
|
||||
entry: './'
|
||||
optimization:
|
||||
# Webpack’s minification causes the CoffeeScript module to fail some tests.
|
||||
minimize: off
|
||||
output:
|
||||
path: tmpdir
|
||||
filename: 'coffeescript.js'
|
||||
@@ -503,7 +586,7 @@ task 'test:integrations', 'test the module integrated with other libraries and e
|
||||
process.exit 1
|
||||
|
||||
builtCompiler = path.join tmpdir, 'coffeescript.js'
|
||||
CoffeeScript = require builtCompiler
|
||||
{ CoffeeScript } = require builtCompiler
|
||||
global.testingBrowser = yes
|
||||
testResults = runTests CoffeeScript
|
||||
fs.unlinkSync builtCompiler
|
||||
|
||||
29
appveyor.yml
29
appveyor.yml
@@ -1,29 +0,0 @@
|
||||
environment:
|
||||
matrix:
|
||||
- nodejs_version: '6'
|
||||
- nodejs_version: '8'
|
||||
- nodejs_version: '10'
|
||||
- nodejs_version: '' # Installs latest.
|
||||
|
||||
install:
|
||||
- ps: Install-Product node $env:nodejs_version
|
||||
- node --version
|
||||
- npm --version
|
||||
- npm install
|
||||
|
||||
cache:
|
||||
- node_modules
|
||||
|
||||
test_script:
|
||||
- node ./bin/cake build:except-parser
|
||||
- node ./bin/cake build:parser
|
||||
- node ./bin/cake build:full
|
||||
- node ./bin/cake build:browser
|
||||
- node ./bin/cake test
|
||||
- node --harmony ./bin/cake test
|
||||
- node ./bin/cake test:browser
|
||||
- node ./bin/cake test:integrations
|
||||
|
||||
build: off
|
||||
|
||||
version: "{build}"
|
||||
@@ -1 +1 @@
|
||||
v2/browser-compiler
|
||||
v2/browser-compiler-legacy
|
||||
1
docs/browser-compiler-legacy
Symbolic link
1
docs/browser-compiler-legacy
Symbolic link
@@ -0,0 +1 @@
|
||||
v2/browser-compiler-legacy
|
||||
1
docs/browser-compiler-modern
Symbolic link
1
docs/browser-compiler-modern
Symbolic link
@@ -0,0 +1 @@
|
||||
v2/browser-compiler-modern
|
||||
@@ -555,7 +555,8 @@ pre .xml .cdata {
|
||||
<a href="#destructuring">Destructuring Assignment</a>
|
||||
<a href="#fat-arrow">Bound and Generator Functions</a>
|
||||
<a href="#embedded">Embedded JavaScript</a>
|
||||
<a href="#switch">Switch and Try/Catch</a>
|
||||
<a href="#switch">Switch/When/Else</a>
|
||||
<a href="#try-catch">Try/Catch/Finally</a>
|
||||
<a href="#comparisons">Chained Comparisons</a>
|
||||
<a href="#strings">String Interpolation, Block Strings, and Block Comments</a>
|
||||
<a href="#tagged-template-literals">Tagged Template Literals</a>
|
||||
@@ -853,7 +854,7 @@ cubes = (function() {
|
||||
<h2>Language Reference</h2>
|
||||
<p><em>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.</em></p>
|
||||
<p><em>Many of the examples can be run (where it makes sense) by pressing the <strong>run</strong> button on the right, and can be loaded into the “Try CoffeeScript” console by pressing the <strong>load</strong> button on the left.</em></p>
|
||||
<p>First, the basics: CoffeeScript uses significant whitespace to delimit blocks of code. You don’t need to use semicolons <code>;</code> 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 <code>{ }</code> to surround blocks of code in <a href="#literals">functions</a>, <a href="#conditionals">if-statements</a>, <a href="#switch">switch</a>, and <a href="#try">try/catch</a>, use indentation.</p>
|
||||
<p>First, the basics: CoffeeScript uses significant whitespace to delimit blocks of code. You don’t need to use semicolons <code>;</code> 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 <code>{ }</code> to surround blocks of code in <a href="#literals">functions</a>, <a href="#conditionals">if-statements</a>, <a href="#switch">switch</a>, and <a href="#try-catch">try/catch</a>, use indentation.</p>
|
||||
<p>You don’t need to use parentheses to invoke a function if you’re passing arguments. The implicit call wraps forward to the end of the line or block expression.<br>
|
||||
<code>console.log sys.inspect object</code> → <code>console.log(sys.inspect(object));</code></p>
|
||||
|
||||
|
||||
@@ -112,8 +112,8 @@
|
||||
<li id="section-1">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-1">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-1">§</a>
|
||||
</div>
|
||||
<p>This <strong>Browser</strong> compatibility layer extends core CoffeeScript functions
|
||||
to make things work smoothly when compiling code directly in the browser.
|
||||
@@ -123,7 +123,7 @@ We add support for loading remote Coffee scripts via <strong>XHR</strong>, and
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre>
|
||||
CoffeeScript = <span class="hljs-built_in">require</span> <span class="hljs-string">'./coffeescript'</span>
|
||||
CoffeeScript = <span class="hljs-built_in">require</span> <span class="hljs-string">'./coffeescript'</span>
|
||||
{ compile } = CoffeeScript</pre></div></div>
|
||||
|
||||
</li>
|
||||
@@ -132,8 +132,8 @@ CoffeeScript = <span class="hljs-built_in">require</span> <span class="hljs-stri
|
||||
<li id="section-2">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-2">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-2">§</a>
|
||||
</div>
|
||||
<p>Use <code>window.eval</code> to evaluate code, rather than just <code>eval</code>, to run the
|
||||
script in a clean global scope rather than inheriting the scope of the
|
||||
@@ -142,10 +142,10 @@ use either <code>window.eval</code> or <code>global.eval</code> as appropriate).
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre>CoffeeScript.eval = <span class="hljs-function"><span class="hljs-params">(code, options = {})</span> -></span>
|
||||
<div class="content"><div class='highlight'><pre>CoffeeScript.<span class="hljs-built_in">eval</span> = <span class="hljs-function"><span class="hljs-params">(code, options = {})</span> -></span>
|
||||
options.bare ?= <span class="hljs-literal">on</span>
|
||||
globalRoot = <span class="hljs-keyword">if</span> <span class="hljs-built_in">window</span>? <span class="hljs-keyword">then</span> <span class="hljs-built_in">window</span> <span class="hljs-keyword">else</span> <span class="hljs-built_in">global</span>
|
||||
globalRoot[<span class="hljs-string">'eval'</span>] compile code, options</pre></div></div>
|
||||
globalRoot = <span class="hljs-keyword">if</span> window? <span class="hljs-keyword">then</span> window <span class="hljs-keyword">else</span> global
|
||||
globalRoot[<span class="hljs-string">'eval'</span>] compile code, options</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -153,8 +153,8 @@ use either <code>window.eval</code> or <code>global.eval</code> as appropriate).
|
||||
<li id="section-3">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-3">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-3">§</a>
|
||||
</div>
|
||||
<p>Running code does not provide access to this scope.</p>
|
||||
|
||||
@@ -163,7 +163,7 @@ use either <code>window.eval</code> or <code>global.eval</code> as appropriate).
|
||||
<div class="content"><div class='highlight'><pre>CoffeeScript.run = <span class="hljs-function"><span class="hljs-params">(code, options = {})</span> -></span>
|
||||
options.bare = <span class="hljs-literal">on</span>
|
||||
options.shiftLine = <span class="hljs-literal">on</span>
|
||||
Function(compile code, options)()</pre></div></div>
|
||||
<span class="hljs-built_in">Function</span>(compile code, options)()</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -171,15 +171,15 @@ use either <code>window.eval</code> or <code>global.eval</code> as appropriate).
|
||||
<li id="section-4">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-4">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-4">§</a>
|
||||
</div>
|
||||
<p>Export this more limited <code>CoffeeScript</code> than what is exported by
|
||||
<code>index.coffee</code>, which is intended for a Node environment.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre><span class="hljs-built_in">module</span>.exports = CoffeeScript</pre></div></div>
|
||||
<div class="content"><div class='highlight'><pre>module.<span class="hljs-built_in">exports</span> = CoffeeScript</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -187,14 +187,14 @@ use either <code>window.eval</code> or <code>global.eval</code> as appropriate).
|
||||
<li id="section-5">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-5">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-5">§</a>
|
||||
</div>
|
||||
<p>If we’re not in a browser environment, we’re finished with the public API.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre><span class="hljs-keyword">return</span> <span class="hljs-keyword">unless</span> <span class="hljs-built_in">window</span>?</pre></div></div>
|
||||
<div class="content"><div class='highlight'><pre><span class="hljs-keyword">return</span> <span class="hljs-keyword">unless</span> window?</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -202,8 +202,8 @@ use either <code>window.eval</code> or <code>global.eval</code> as appropriate).
|
||||
<li id="section-6">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-6">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-6">§</a>
|
||||
</div>
|
||||
<p>Include source maps where possible. If we’ve got a base64 encoder, a
|
||||
JSON serializer, and tools for escaping unicode characters, we’re good to go.
|
||||
@@ -211,7 +211,7 @@ Ported from <a href="https://developer.mozilla.org/en-US/docs/DOM/window.btoa">h
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre><span class="hljs-keyword">if</span> btoa? <span class="hljs-keyword">and</span> JSON?
|
||||
<div class="content"><div class='highlight'><pre><span class="hljs-keyword">if</span> btoa? <span class="hljs-keyword">and</span> <span class="hljs-built_in">JSON</span>?
|
||||
<span class="hljs-function"> <span class="hljs-title">compile</span> = <span class="hljs-params">(code, options = {})</span> -></span>
|
||||
options.inlineMap = <span class="hljs-literal">true</span>
|
||||
CoffeeScript.compile code, options</pre></div></div>
|
||||
@@ -222,8 +222,8 @@ Ported from <a href="https://developer.mozilla.org/en-US/docs/DOM/window.btoa">h
|
||||
<li id="section-7">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-7">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-7">§</a>
|
||||
</div>
|
||||
<p>Load a remote script from the current domain via XHR.</p>
|
||||
|
||||
@@ -231,19 +231,19 @@ Ported from <a href="https://developer.mozilla.org/en-US/docs/DOM/window.btoa">h
|
||||
|
||||
<div class="content"><div class='highlight'><pre>CoffeeScript.load = <span class="hljs-function"><span class="hljs-params">(url, callback, options = {}, hold = <span class="hljs-literal">false</span>)</span> -></span>
|
||||
options.sourceFiles = [url]
|
||||
xhr = <span class="hljs-keyword">if</span> <span class="hljs-built_in">window</span>.ActiveXObject
|
||||
<span class="hljs-keyword">new</span> <span class="hljs-built_in">window</span>.ActiveXObject(<span class="hljs-string">'Microsoft.XMLHTTP'</span>)
|
||||
xhr = <span class="hljs-keyword">if</span> window.ActiveXObject
|
||||
<span class="hljs-keyword">new</span> window.ActiveXObject(<span class="hljs-string">'Microsoft.XMLHTTP'</span>)
|
||||
<span class="hljs-keyword">else</span>
|
||||
<span class="hljs-keyword">new</span> <span class="hljs-built_in">window</span>.XMLHttpRequest()
|
||||
xhr.open <span class="hljs-string">'GET'</span>, url, <span class="hljs-literal">true</span>
|
||||
xhr.overrideMimeType <span class="hljs-string">'text/plain'</span> <span class="hljs-keyword">if</span> <span class="hljs-string">'overrideMimeType'</span> <span class="hljs-keyword">of</span> xhr
|
||||
<span class="hljs-keyword">new</span> window.XMLHttpRequest()
|
||||
xhr.open <span class="hljs-string">'GET'</span>, url, <span class="hljs-literal">true</span>
|
||||
xhr.overrideMimeType <span class="hljs-string">'text/plain'</span> <span class="hljs-keyword">if</span> <span class="hljs-string">'overrideMimeType'</span> <span class="hljs-keyword">of</span> xhr
|
||||
xhr.onreadystatechange = <span class="hljs-function">-></span>
|
||||
<span class="hljs-keyword">if</span> xhr.readyState <span class="hljs-keyword">is</span> <span class="hljs-number">4</span>
|
||||
<span class="hljs-keyword">if</span> xhr.status <span class="hljs-keyword">in</span> [<span class="hljs-number">0</span>, <span class="hljs-number">200</span>]
|
||||
param = [xhr.responseText, options]
|
||||
CoffeeScript.run param... <span class="hljs-keyword">unless</span> hold
|
||||
<span class="hljs-keyword">else</span>
|
||||
<span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> Error <span class="hljs-string">"Could not load <span class="hljs-subst">#{url}</span>"</span>
|
||||
<span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span> <span class="hljs-string">"Could not load <span class="hljs-subst">#{url}</span>"</span>
|
||||
callback param <span class="hljs-keyword">if</span> callback
|
||||
xhr.send <span class="hljs-literal">null</span></pre></div></div>
|
||||
|
||||
@@ -253,8 +253,8 @@ Ported from <a href="https://developer.mozilla.org/en-US/docs/DOM/window.btoa">h
|
||||
<li id="section-8">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-8">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-8">§</a>
|
||||
</div>
|
||||
<p>Activate CoffeeScript in the browser by having it compile and evaluate
|
||||
all script tags with a content-type of <code>text/coffeescript</code>.
|
||||
@@ -262,15 +262,15 @@ This happens on page load.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">runScripts</span> = -></span>
|
||||
scripts = <span class="hljs-built_in">window</span>.<span class="hljs-built_in">document</span>.getElementsByTagName <span class="hljs-string">'script'</span>
|
||||
coffeetypes = [<span class="hljs-string">'text/coffeescript'</span>, <span class="hljs-string">'text/literate-coffeescript'</span>]
|
||||
<div class="content"><div class='highlight'><pre>CoffeeScript.runScripts = <span class="hljs-function">-></span>
|
||||
scripts = window.document.getElementsByTagName <span class="hljs-string">'script'</span>
|
||||
coffeetypes = [<span class="hljs-string">'text/coffeescript'</span>, <span class="hljs-string">'text/literate-coffeescript'</span>]
|
||||
coffees = (s <span class="hljs-keyword">for</span> s <span class="hljs-keyword">in</span> scripts <span class="hljs-keyword">when</span> s.type <span class="hljs-keyword">in</span> coffeetypes)
|
||||
index = <span class="hljs-number">0</span>
|
||||
<span class="hljs-function">
|
||||
<span class="hljs-title">execute</span> = -></span>
|
||||
param = coffees[index]
|
||||
<span class="hljs-keyword">if</span> param <span class="hljs-keyword">instanceof</span> Array
|
||||
<span class="hljs-keyword">if</span> param <span class="hljs-keyword">instanceof</span> <span class="hljs-built_in">Array</span>
|
||||
CoffeeScript.run param...
|
||||
index++
|
||||
execute()
|
||||
@@ -278,7 +278,7 @@ This happens on page load.</p>
|
||||
<span class="hljs-keyword">for</span> script, i <span class="hljs-keyword">in</span> coffees
|
||||
<span class="hljs-keyword">do</span> (script, i) ->
|
||||
options = literate: script.type <span class="hljs-keyword">is</span> coffeetypes[<span class="hljs-number">1</span>]
|
||||
source = script.src <span class="hljs-keyword">or</span> script.getAttribute(<span class="hljs-string">'data-src'</span>)
|
||||
source = script.src <span class="hljs-keyword">or</span> script.getAttribute(<span class="hljs-string">'data-src'</span>)
|
||||
<span class="hljs-keyword">if</span> source
|
||||
options.filename = source
|
||||
CoffeeScript.load source,
|
||||
@@ -295,8 +295,8 @@ This happens on page load.</p>
|
||||
<li id="section-9">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-9">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-9">§</a>
|
||||
</div>
|
||||
<p><code>options.filename</code> defines the filename the source map appears as
|
||||
in Developer Tools. If a script tag has an <code>id</code>, use that as the
|
||||
@@ -306,8 +306,8 @@ only one CoffeeScript script block to parse.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> options.filename = <span class="hljs-keyword">if</span> script.id <span class="hljs-keyword">and</span> script.id <span class="hljs-keyword">isnt</span> <span class="hljs-string">''</span> <span class="hljs-keyword">then</span> script.id <span class="hljs-keyword">else</span> <span class="hljs-string">"coffeescript<span class="hljs-subst">#{<span class="hljs-keyword">if</span> i <span class="hljs-keyword">isnt</span> <span class="hljs-number">0</span> <span class="hljs-keyword">then</span> i <span class="hljs-keyword">else</span> <span class="hljs-string">''</span>}</span>"</span>
|
||||
options.sourceFiles = [<span class="hljs-string">'embedded'</span>]
|
||||
<div class="content"><div class='highlight'><pre> options.filename = <span class="hljs-keyword">if</span> script.id <span class="hljs-keyword">and</span> script.id <span class="hljs-keyword">isnt</span> <span class="hljs-string">''</span> <span class="hljs-keyword">then</span> script.id <span class="hljs-keyword">else</span> <span class="hljs-string">"coffeescript<span class="hljs-subst">#{<span class="hljs-keyword">if</span> i <span class="hljs-keyword">isnt</span> <span class="hljs-number">0</span> <span class="hljs-keyword">then</span> i <span class="hljs-keyword">else</span> <span class="hljs-string">''</span>}</span>"</span>
|
||||
options.sourceFiles = [<span class="hljs-string">'embedded'</span>]
|
||||
coffees[i] = [script.innerHTML, options]
|
||||
|
||||
execute()</pre></div></div>
|
||||
@@ -318,17 +318,22 @@ only one CoffeeScript script block to parse.</p>
|
||||
<li id="section-10">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-10">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-10">§</a>
|
||||
</div>
|
||||
<p>Listen for window load, both in decent browsers and in IE.</p>
|
||||
<p>Listen for window load, both in decent browsers and in IE.
|
||||
Only attach this event handler on startup for the
|
||||
non-ES module version of the browser compiler, to preserve
|
||||
backward compatibility while letting the ES module version
|
||||
be importable without side effects.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre><span class="hljs-keyword">if</span> <span class="hljs-built_in">window</span>.addEventListener
|
||||
<span class="hljs-built_in">window</span>.addEventListener <span class="hljs-string">'DOMContentLoaded'</span>, runScripts, <span class="hljs-literal">no</span>
|
||||
<span class="hljs-keyword">else</span>
|
||||
<span class="hljs-built_in">window</span>.attachEvent <span class="hljs-string">'onload'</span>, runScripts</pre></div></div>
|
||||
<div class="content"><div class='highlight'><pre><span class="hljs-keyword">if</span> this <span class="hljs-keyword">is</span> window
|
||||
<span class="hljs-keyword">if</span> window.addEventListener
|
||||
window.addEventListener <span class="hljs-string">'DOMContentLoaded'</span>, CoffeeScript.runScripts, <span class="hljs-literal">no</span>
|
||||
<span class="hljs-keyword">else</span>
|
||||
window.attachEvent <span class="hljs-string">'onload'</span>, CoffeeScript.runScripts</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
@@ -112,8 +112,8 @@
|
||||
<li id="section-1">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-1">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-1">§</a>
|
||||
</div>
|
||||
<p><code>cake</code> is a simplified version of <a href="http://www.gnu.org/software/make/">Make</a>
|
||||
(<a href="http://rake.rubyforge.org/">Rake</a>, <a href="https://github.com/280north/jake">Jake</a>)
|
||||
@@ -130,18 +130,18 @@ current directory’s Cakefile.</p>
|
||||
<li id="section-2">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-2">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-2">§</a>
|
||||
</div>
|
||||
<p>External dependencies.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre>fs = <span class="hljs-built_in">require</span> <span class="hljs-string">'fs'</span>
|
||||
path = <span class="hljs-built_in">require</span> <span class="hljs-string">'path'</span>
|
||||
helpers = <span class="hljs-built_in">require</span> <span class="hljs-string">'./helpers'</span>
|
||||
optparse = <span class="hljs-built_in">require</span> <span class="hljs-string">'./optparse'</span>
|
||||
CoffeeScript = <span class="hljs-built_in">require</span> <span class="hljs-string">'./'</span></pre></div></div>
|
||||
<div class="content"><div class='highlight'><pre>fs = <span class="hljs-built_in">require</span> <span class="hljs-string">'fs'</span>
|
||||
path = <span class="hljs-built_in">require</span> <span class="hljs-string">'path'</span>
|
||||
helpers = <span class="hljs-built_in">require</span> <span class="hljs-string">'./helpers'</span>
|
||||
optparse = <span class="hljs-built_in">require</span> <span class="hljs-string">'./optparse'</span>
|
||||
CoffeeScript = <span class="hljs-built_in">require</span> <span class="hljs-string">'./'</span></pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -149,8 +149,8 @@ CoffeeScript = <span class="hljs-built_in">require</span> <span class="hljs-stri
|
||||
<li id="section-3">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-3">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-3">§</a>
|
||||
</div>
|
||||
<p>Register .coffee extension</p>
|
||||
|
||||
@@ -164,8 +164,8 @@ CoffeeScript = <span class="hljs-built_in">require</span> <span class="hljs-stri
|
||||
<li id="section-4">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-4">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-4">§</a>
|
||||
</div>
|
||||
<p>Keep track of the list of defined tasks, the accepted options, and so on.</p>
|
||||
|
||||
@@ -182,14 +182,14 @@ oparse = <span class="hljs-literal">null</span></pre></div></div>
|
||||
<li id="section-5">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-5">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-5">§</a>
|
||||
</div>
|
||||
<p>Mixin the top-level Cake functions for Cakefiles to use directly.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre>helpers.extend <span class="hljs-built_in">global</span>,</pre></div></div>
|
||||
<div class="content"><div class='highlight'><pre>helpers.extend global,</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -197,8 +197,8 @@ oparse = <span class="hljs-literal">null</span></pre></div></div>
|
||||
<li id="section-6">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-6">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-6">§</a>
|
||||
</div>
|
||||
<p>Define a Cake task with a short name, an optional sentence description,
|
||||
and the function to run as the action itself.</p>
|
||||
@@ -215,8 +215,8 @@ and the function to run as the action itself.</p>
|
||||
<li id="section-7">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-7">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-7">§</a>
|
||||
</div>
|
||||
<p>Define an option that the Cakefile accepts. The parsed options hash,
|
||||
containing all of the command-line options passed, will be made available
|
||||
@@ -233,8 +233,8 @@ as the first argument to the action.</p>
|
||||
<li id="section-8">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-8">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-8">§</a>
|
||||
</div>
|
||||
<p>Invoke another task in the current Cakefile.</p>
|
||||
|
||||
@@ -250,8 +250,8 @@ as the first argument to the action.</p>
|
||||
<li id="section-9">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-9">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-9">§</a>
|
||||
</div>
|
||||
<p>Run <code>cake</code>. Executes all of the tasks you pass, in order. Note that Node’s
|
||||
asynchrony may cause tasks to execute in a different order than you’d expect.
|
||||
@@ -260,17 +260,17 @@ original directory name, when running Cake tasks from subdirectories.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre>exports.run = <span class="hljs-function">-></span>
|
||||
<span class="hljs-built_in">global</span>.__originalDirname = fs.realpathSync <span class="hljs-string">'.'</span>
|
||||
<div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.run = <span class="hljs-function">-></span>
|
||||
global.__originalDirname = fs.realpathSync <span class="hljs-string">'.'</span>
|
||||
process.chdir cakefileDirectory __originalDirname
|
||||
args = process.argv[<span class="hljs-number">2.</span>.]
|
||||
CoffeeScript.run fs.readFileSync(<span class="hljs-string">'Cakefile'</span>).toString(), filename: <span class="hljs-string">'Cakefile'</span>
|
||||
CoffeeScript.run fs.readFileSync(<span class="hljs-string">'Cakefile'</span>).toString(), filename: <span class="hljs-string">'Cakefile'</span>
|
||||
oparse = <span class="hljs-keyword">new</span> optparse.OptionParser switches
|
||||
<span class="hljs-keyword">return</span> printTasks() <span class="hljs-keyword">unless</span> args.length
|
||||
<span class="hljs-keyword">try</span>
|
||||
options = oparse.parse(args)
|
||||
<span class="hljs-keyword">catch</span> e
|
||||
<span class="hljs-keyword">return</span> fatalError <span class="hljs-string">"<span class="hljs-subst">#{e}</span>"</span>
|
||||
<span class="hljs-keyword">return</span> fatalError <span class="hljs-string">"<span class="hljs-subst">#{e}</span>"</span>
|
||||
invoke arg <span class="hljs-keyword">for</span> arg <span class="hljs-keyword">in</span> options.arguments</pre></div></div>
|
||||
|
||||
</li>
|
||||
@@ -279,8 +279,8 @@ original directory name, when running Cake tasks from subdirectories.</p>
|
||||
<li id="section-10">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-10">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-10">§</a>
|
||||
</div>
|
||||
<p>Display the list of Cake tasks in a format similar to <code>rake -T</code></p>
|
||||
|
||||
@@ -288,14 +288,14 @@ original directory name, when running Cake tasks from subdirectories.</p>
|
||||
|
||||
<div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">printTasks</span> = -></span>
|
||||
relative = path.relative <span class="hljs-keyword">or</span> path.resolve
|
||||
cakefilePath = path.join relative(__originalDirname, process.cwd()), <span class="hljs-string">'Cakefile'</span>
|
||||
<span class="hljs-built_in">console</span>.log <span class="hljs-string">"<span class="hljs-subst">#{cakefilePath}</span> defines the following tasks:\n"</span>
|
||||
cakefilePath = path.join relative(__originalDirname, process.cwd()), <span class="hljs-string">'Cakefile'</span>
|
||||
console.log <span class="hljs-string">"<span class="hljs-subst">#{cakefilePath}</span> defines the following tasks:\n"</span>
|
||||
<span class="hljs-keyword">for</span> name, task <span class="hljs-keyword">of</span> tasks
|
||||
spaces = <span class="hljs-number">20</span> - name.length
|
||||
spaces = <span class="hljs-keyword">if</span> spaces > <span class="hljs-number">0</span> <span class="hljs-keyword">then</span> Array(spaces + <span class="hljs-number">1</span>).join(<span class="hljs-string">' '</span>) <span class="hljs-keyword">else</span> <span class="hljs-string">''</span>
|
||||
desc = <span class="hljs-keyword">if</span> task.description <span class="hljs-keyword">then</span> <span class="hljs-string">"# <span class="hljs-subst">#{task.description}</span>"</span> <span class="hljs-keyword">else</span> <span class="hljs-string">''</span>
|
||||
<span class="hljs-built_in">console</span>.log <span class="hljs-string">"cake <span class="hljs-subst">#{name}</span><span class="hljs-subst">#{spaces}</span> <span class="hljs-subst">#{desc}</span>"</span>
|
||||
<span class="hljs-built_in">console</span>.log oparse.help() <span class="hljs-keyword">if</span> switches.length</pre></div></div>
|
||||
spaces = <span class="hljs-keyword">if</span> spaces > <span class="hljs-number">0</span> <span class="hljs-keyword">then</span> <span class="hljs-built_in">Array</span>(spaces + <span class="hljs-number">1</span>).join(<span class="hljs-string">' '</span>) <span class="hljs-keyword">else</span> <span class="hljs-string">''</span>
|
||||
desc = <span class="hljs-keyword">if</span> task.description <span class="hljs-keyword">then</span> <span class="hljs-string">"# <span class="hljs-subst">#{task.description}</span>"</span> <span class="hljs-keyword">else</span> <span class="hljs-string">''</span>
|
||||
console.log <span class="hljs-string">"cake <span class="hljs-subst">#{name}</span><span class="hljs-subst">#{spaces}</span> <span class="hljs-subst">#{desc}</span>"</span>
|
||||
console.log oparse.help() <span class="hljs-keyword">if</span> switches.length</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -303,19 +303,19 @@ original directory name, when running Cake tasks from subdirectories.</p>
|
||||
<li id="section-11">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-11">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-11">§</a>
|
||||
</div>
|
||||
<p>Print an error and exit when attempting to use an invalid task/option.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">fatalError</span> = <span class="hljs-params">(message)</span> -></span>
|
||||
<span class="hljs-built_in">console</span>.error message + <span class="hljs-string">'\n'</span>
|
||||
<span class="hljs-built_in">console</span>.log <span class="hljs-string">'To see a list of all tasks/options, run "cake"'</span>
|
||||
console.error message + <span class="hljs-string">'\n'</span>
|
||||
console.log <span class="hljs-string">'To see a list of all tasks/options, run "cake"'</span>
|
||||
process.exit <span class="hljs-number">1</span>
|
||||
<span class="hljs-function">
|
||||
<span class="hljs-title">missingTask</span> = <span class="hljs-params">(task)</span> -></span> fatalError <span class="hljs-string">"No such task: <span class="hljs-subst">#{task}</span>"</span></pre></div></div>
|
||||
<span class="hljs-title">missingTask</span> = <span class="hljs-params">(task)</span> -></span> fatalError <span class="hljs-string">"No such task: <span class="hljs-subst">#{task}</span>"</span></pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -323,8 +323,8 @@ original directory name, when running Cake tasks from subdirectories.</p>
|
||||
<li id="section-12">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-12">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-12">§</a>
|
||||
</div>
|
||||
<p>When <code>cake</code> is invoked, search in the current and all parent directories
|
||||
to find the relevant Cakefile.</p>
|
||||
@@ -332,10 +332,10 @@ to find the relevant Cakefile.</p>
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">cakefileDirectory</span> = <span class="hljs-params">(dir)</span> -></span>
|
||||
<span class="hljs-keyword">return</span> dir <span class="hljs-keyword">if</span> fs.existsSync path.join dir, <span class="hljs-string">'Cakefile'</span>
|
||||
parent = path.normalize path.join dir, <span class="hljs-string">'..'</span>
|
||||
<span class="hljs-keyword">return</span> dir <span class="hljs-keyword">if</span> fs.existsSync path.join dir, <span class="hljs-string">'Cakefile'</span>
|
||||
parent = path.normalize path.join dir, <span class="hljs-string">'..'</span>
|
||||
<span class="hljs-keyword">return</span> cakefileDirectory parent <span class="hljs-keyword">unless</span> parent <span class="hljs-keyword">is</span> dir
|
||||
<span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> Error <span class="hljs-string">"Cakefile not found in <span class="hljs-subst">#{process.cwd()}</span>"</span></pre></div></div>
|
||||
<span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span> <span class="hljs-string">"Cakefile not found in <span class="hljs-subst">#{process.cwd()}</span>"</span></pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -112,8 +112,8 @@
|
||||
<li id="section-1">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-1">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-1">§</a>
|
||||
</div>
|
||||
<p>The <code>coffee</code> utility. Handles command-line compilation of CoffeeScript
|
||||
into various forms: saved into <code>.js</code> files or printed to stdout
|
||||
@@ -129,22 +129,22 @@ interactive REPL.</p>
|
||||
<li id="section-2">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-2">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-2">§</a>
|
||||
</div>
|
||||
<p>External dependencies.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre>fs = <span class="hljs-built_in">require</span> <span class="hljs-string">'fs'</span>
|
||||
path = <span class="hljs-built_in">require</span> <span class="hljs-string">'path'</span>
|
||||
helpers = <span class="hljs-built_in">require</span> <span class="hljs-string">'./helpers'</span>
|
||||
optparse = <span class="hljs-built_in">require</span> <span class="hljs-string">'./optparse'</span>
|
||||
CoffeeScript = <span class="hljs-built_in">require</span> <span class="hljs-string">'./'</span>
|
||||
{spawn, exec} = <span class="hljs-built_in">require</span> <span class="hljs-string">'child_process'</span>
|
||||
{EventEmitter} = <span class="hljs-built_in">require</span> <span class="hljs-string">'events'</span>
|
||||
<div class="content"><div class='highlight'><pre>fs = <span class="hljs-built_in">require</span> <span class="hljs-string">'fs'</span>
|
||||
path = <span class="hljs-built_in">require</span> <span class="hljs-string">'path'</span>
|
||||
helpers = <span class="hljs-built_in">require</span> <span class="hljs-string">'./helpers'</span>
|
||||
optparse = <span class="hljs-built_in">require</span> <span class="hljs-string">'./optparse'</span>
|
||||
CoffeeScript = <span class="hljs-built_in">require</span> <span class="hljs-string">'./'</span>
|
||||
{spawn, exec} = <span class="hljs-built_in">require</span> <span class="hljs-string">'child_process'</span>
|
||||
{EventEmitter} = <span class="hljs-built_in">require</span> <span class="hljs-string">'events'</span>
|
||||
|
||||
useWinPathSep = path.sep <span class="hljs-keyword">is</span> <span class="hljs-string">'\\'</span></pre></div></div>
|
||||
useWinPathSep = path.sep <span class="hljs-keyword">is</span> <span class="hljs-string">'\\'</span></pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -152,8 +152,8 @@ useWinPathSep = path.sep <span class="hljs-keyword">is</span> <span class="hljs
|
||||
<li id="section-3">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-3">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-3">§</a>
|
||||
</div>
|
||||
<p>Allow CoffeeScript to emit Node.js events.</p>
|
||||
|
||||
@@ -161,8 +161,8 @@ useWinPathSep = path.sep <span class="hljs-keyword">is</span> <span class="hljs
|
||||
|
||||
<div class="content"><div class='highlight'><pre>helpers.extend CoffeeScript, <span class="hljs-keyword">new</span> EventEmitter
|
||||
<span class="hljs-function">
|
||||
<span class="hljs-title">printLine</span> = <span class="hljs-params">(line)</span> -></span> process.stdout.write line + <span class="hljs-string">'\n'</span>
|
||||
<span class="hljs-function"><span class="hljs-title">printWarn</span> = <span class="hljs-params">(line)</span> -></span> process.stderr.write line + <span class="hljs-string">'\n'</span>
|
||||
<span class="hljs-title">printLine</span> = <span class="hljs-params">(line)</span> -></span> process.stdout.write line + <span class="hljs-string">'\n'</span>
|
||||
<span class="hljs-function"><span class="hljs-title">printWarn</span> = <span class="hljs-params">(line)</span> -></span> process.stderr.write line + <span class="hljs-string">'\n'</span>
|
||||
<span class="hljs-function">
|
||||
<span class="hljs-title">hidden</span> = <span class="hljs-params">(file)</span> -></span> <span class="hljs-regexp">/^\.|~$/</span>.test file</pre></div></div>
|
||||
|
||||
@@ -172,18 +172,18 @@ useWinPathSep = path.sep <span class="hljs-keyword">is</span> <span class="hljs
|
||||
<li id="section-4">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-4">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-4">§</a>
|
||||
</div>
|
||||
<p>The help banner that is printed in conjunction with <code>-h</code>/<code>--help</code>.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre>BANNER = <span class="hljs-string">'''
|
||||
<div class="content"><div class='highlight'><pre>BANNER = <span class="hljs-string">'''
|
||||
Usage: coffee [options] path/to/script.coffee [args]
|
||||
|
||||
If called without options, `coffee` will run your script.
|
||||
'''</span></pre></div></div>
|
||||
'''</span></pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -191,34 +191,35 @@ useWinPathSep = path.sep <span class="hljs-keyword">is</span> <span class="hljs
|
||||
<li id="section-5">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-5">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-5">§</a>
|
||||
</div>
|
||||
<p>The list of all the valid option flags that <code>coffee</code> knows how to handle.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre>SWITCHES = [
|
||||
[<span class="hljs-string">'-b'</span>, <span class="hljs-string">'--bare'</span>, <span class="hljs-string">'compile without a top-level function wrapper'</span>]
|
||||
[<span class="hljs-string">'-c'</span>, <span class="hljs-string">'--compile'</span>, <span class="hljs-string">'compile to JavaScript and save as .js files'</span>]
|
||||
[<span class="hljs-string">'-e'</span>, <span class="hljs-string">'--eval'</span>, <span class="hljs-string">'pass a string from the command line as input'</span>]
|
||||
[<span class="hljs-string">'-h'</span>, <span class="hljs-string">'--help'</span>, <span class="hljs-string">'display this help message'</span>]
|
||||
[<span class="hljs-string">'-i'</span>, <span class="hljs-string">'--interactive'</span>, <span class="hljs-string">'run an interactive CoffeeScript REPL'</span>]
|
||||
[<span class="hljs-string">'-j'</span>, <span class="hljs-string">'--join [FILE]'</span>, <span class="hljs-string">'concatenate the source CoffeeScript before compiling'</span>]
|
||||
[<span class="hljs-string">'-m'</span>, <span class="hljs-string">'--map'</span>, <span class="hljs-string">'generate source map and save as .js.map files'</span>]
|
||||
[<span class="hljs-string">'-M'</span>, <span class="hljs-string">'--inline-map'</span>, <span class="hljs-string">'generate source map and include it directly in output'</span>]
|
||||
[<span class="hljs-string">'-n'</span>, <span class="hljs-string">'--nodes'</span>, <span class="hljs-string">'print out the parse tree that the parser produces'</span>]
|
||||
[ <span class="hljs-string">'--nodejs [ARGS]'</span>, <span class="hljs-string">'pass options directly to the "node" binary'</span>]
|
||||
[ <span class="hljs-string">'--no-header'</span>, <span class="hljs-string">'suppress the "Generated by" header'</span>]
|
||||
[<span class="hljs-string">'-o'</span>, <span class="hljs-string">'--output [PATH]'</span>, <span class="hljs-string">'set the output path or path/filename for compiled JavaScript'</span>]
|
||||
[<span class="hljs-string">'-p'</span>, <span class="hljs-string">'--print'</span>, <span class="hljs-string">'print out the compiled JavaScript'</span>]
|
||||
[<span class="hljs-string">'-r'</span>, <span class="hljs-string">'--require [MODULE*]'</span>, <span class="hljs-string">'require the given module before eval or REPL'</span>]
|
||||
[<span class="hljs-string">'-s'</span>, <span class="hljs-string">'--stdio'</span>, <span class="hljs-string">'listen for and compile scripts over stdio'</span>]
|
||||
[<span class="hljs-string">'-l'</span>, <span class="hljs-string">'--literate'</span>, <span class="hljs-string">'treat stdio as literate style coffeescript'</span>]
|
||||
[<span class="hljs-string">'-t'</span>, <span class="hljs-string">'--transpile'</span>, <span class="hljs-string">'pipe generated JavaScript through Babel'</span>]
|
||||
[ <span class="hljs-string">'--tokens'</span>, <span class="hljs-string">'print out the tokens that the lexer/rewriter produce'</span>]
|
||||
[<span class="hljs-string">'-v'</span>, <span class="hljs-string">'--version'</span>, <span class="hljs-string">'display the version number'</span>]
|
||||
[<span class="hljs-string">'-w'</span>, <span class="hljs-string">'--watch'</span>, <span class="hljs-string">'watch scripts for changes and rerun commands'</span>]
|
||||
[ <span class="hljs-string">'--ast'</span>, <span class="hljs-string">'generate an abstract syntax tree of nodes'</span>]
|
||||
[<span class="hljs-string">'-b'</span>, <span class="hljs-string">'--bare'</span>, <span class="hljs-string">'compile without a top-level function wrapper'</span>]
|
||||
[<span class="hljs-string">'-c'</span>, <span class="hljs-string">'--compile'</span>, <span class="hljs-string">'compile to JavaScript and save as .js files'</span>]
|
||||
[<span class="hljs-string">'-e'</span>, <span class="hljs-string">'--eval'</span>, <span class="hljs-string">'pass a string from the command line as input'</span>]
|
||||
[<span class="hljs-string">'-h'</span>, <span class="hljs-string">'--help'</span>, <span class="hljs-string">'display this help message'</span>]
|
||||
[<span class="hljs-string">'-i'</span>, <span class="hljs-string">'--interactive'</span>, <span class="hljs-string">'run an interactive CoffeeScript REPL'</span>]
|
||||
[<span class="hljs-string">'-j'</span>, <span class="hljs-string">'--join [FILE]'</span>, <span class="hljs-string">'concatenate the source CoffeeScript before compiling'</span>]
|
||||
[<span class="hljs-string">'-l'</span>, <span class="hljs-string">'--literate'</span>, <span class="hljs-string">'treat stdio as literate style coffeescript'</span>]
|
||||
[<span class="hljs-string">'-m'</span>, <span class="hljs-string">'--map'</span>, <span class="hljs-string">'generate source map and save as .js.map files'</span>]
|
||||
[<span class="hljs-string">'-M'</span>, <span class="hljs-string">'--inline-map'</span>, <span class="hljs-string">'generate source map and include it directly in output'</span>]
|
||||
[<span class="hljs-string">'-n'</span>, <span class="hljs-string">'--nodes'</span>, <span class="hljs-string">'print out the parse tree that the parser produces'</span>]
|
||||
[ <span class="hljs-string">'--nodejs [ARGS]'</span>, <span class="hljs-string">'pass options directly to the "node" binary'</span>]
|
||||
[ <span class="hljs-string">'--no-header'</span>, <span class="hljs-string">'suppress the "Generated by" header'</span>]
|
||||
[<span class="hljs-string">'-o'</span>, <span class="hljs-string">'--output [PATH]'</span>, <span class="hljs-string">'set the output path or path/filename for compiled JavaScript'</span>]
|
||||
[<span class="hljs-string">'-p'</span>, <span class="hljs-string">'--print'</span>, <span class="hljs-string">'print out the compiled JavaScript'</span>]
|
||||
[<span class="hljs-string">'-r'</span>, <span class="hljs-string">'--require [MODULE*]'</span>, <span class="hljs-string">'require the given module before eval or REPL'</span>]
|
||||
[<span class="hljs-string">'-s'</span>, <span class="hljs-string">'--stdio'</span>, <span class="hljs-string">'listen for and compile scripts over stdio'</span>]
|
||||
[<span class="hljs-string">'-t'</span>, <span class="hljs-string">'--transpile'</span>, <span class="hljs-string">'pipe generated JavaScript through Babel'</span>]
|
||||
[ <span class="hljs-string">'--tokens'</span>, <span class="hljs-string">'print out the tokens that the lexer/rewriter produce'</span>]
|
||||
[<span class="hljs-string">'-v'</span>, <span class="hljs-string">'--version'</span>, <span class="hljs-string">'display the version number'</span>]
|
||||
[<span class="hljs-string">'-w'</span>, <span class="hljs-string">'--watch'</span>, <span class="hljs-string">'watch scripts for changes and rerun commands'</span>]
|
||||
]</pre></div></div>
|
||||
|
||||
</li>
|
||||
@@ -227,8 +228,8 @@ useWinPathSep = path.sep <span class="hljs-keyword">is</span> <span class="hljs
|
||||
<li id="section-6">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-6">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-6">§</a>
|
||||
</div>
|
||||
<p>Top-level objects shared by all the functions.</p>
|
||||
|
||||
@@ -241,7 +242,7 @@ notSources = {}
|
||||
watchedDirs = {}
|
||||
optionParser = <span class="hljs-literal">null</span>
|
||||
|
||||
exports.buildCSOptionParser = buildCSOptionParser = <span class="hljs-function">-></span>
|
||||
<span class="hljs-built_in">exports</span>.buildCSOptionParser = buildCSOptionParser = <span class="hljs-function">-></span>
|
||||
<span class="hljs-keyword">new</span> optparse.OptionParser SWITCHES, BANNER</pre></div></div>
|
||||
|
||||
</li>
|
||||
@@ -250,8 +251,8 @@ exports.buildCSOptionParser = buildCSOptionParser = <span class="hljs-function">
|
||||
<li id="section-7">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-7">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-7">§</a>
|
||||
</div>
|
||||
<p>Run <code>coffee</code> by parsing passed options and determining what action to take.
|
||||
Many flags cause us to divert before compiling anything. Flags passed after
|
||||
@@ -259,22 +260,22 @@ Many flags cause us to divert before compiling anything. Flags passed after
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre>exports.run = <span class="hljs-function">-></span>
|
||||
<div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.run = <span class="hljs-function">-></span>
|
||||
optionParser = buildCSOptionParser()
|
||||
<span class="hljs-keyword">try</span> parseOptions()
|
||||
<span class="hljs-keyword">catch</span> err
|
||||
<span class="hljs-built_in">console</span>.error <span class="hljs-string">"option parsing error: <span class="hljs-subst">#{err.message}</span>"</span>
|
||||
console.error <span class="hljs-string">"option parsing error: <span class="hljs-subst">#{err.message}</span>"</span>
|
||||
process.exit <span class="hljs-number">1</span>
|
||||
|
||||
<span class="hljs-keyword">if</span> (<span class="hljs-keyword">not</span> opts.doubleDashed) <span class="hljs-keyword">and</span> (opts.arguments[<span class="hljs-number">1</span>] <span class="hljs-keyword">is</span> <span class="hljs-string">'--'</span>)
|
||||
printWarn <span class="hljs-string">'''
|
||||
coffee was invoked with '--' as the second positional argument, which is
|
||||
now deprecated. To pass '--' as an argument to a script to run, put an
|
||||
additional '--' before the path to your script.
|
||||
<span class="hljs-keyword">if</span> (<span class="hljs-keyword">not</span> opts.doubleDashed) <span class="hljs-keyword">and</span> (opts.arguments[<span class="hljs-number">1</span>] <span class="hljs-keyword">is</span> <span class="hljs-string">'--'</span>)
|
||||
printWarn <span class="hljs-string">'''
|
||||
coffee was invoked with '--' as the second positional argument, which is
|
||||
now deprecated. To pass '--' as an argument to a script to run, put an
|
||||
additional '--' before the path to your script.
|
||||
|
||||
'--' will be removed from the argument list.
|
||||
'''</span>
|
||||
printWarn <span class="hljs-string">"The positional arguments were: <span class="hljs-subst">#{JSON.stringify opts.arguments}</span>"</span>
|
||||
'--' will be removed from the argument list.
|
||||
'''</span>
|
||||
printWarn <span class="hljs-string">"The positional arguments were: <span class="hljs-subst">#{<span class="hljs-built_in">JSON</span>.stringify opts.arguments}</span>"</span>
|
||||
opts.arguments = [opts.arguments[<span class="hljs-number">0</span>]].concat opts.arguments[<span class="hljs-number">2.</span>.]</pre></div></div>
|
||||
|
||||
</li>
|
||||
@@ -283,8 +284,8 @@ Many flags cause us to divert before compiling anything. Flags passed after
|
||||
<li id="section-8">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-8">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-8">§</a>
|
||||
</div>
|
||||
<p>Make the REPL <em>CLI</em> use the global context so as to (a) be consistent with the
|
||||
<code>node</code> REPL CLI and, therefore, (b) make packages that modify native prototypes
|
||||
@@ -299,18 +300,18 @@ Many flags cause us to divert before compiling anything. Flags passed after
|
||||
<span class="hljs-keyword">return</span> forkNode() <span class="hljs-keyword">if</span> opts.nodejs
|
||||
<span class="hljs-keyword">return</span> usage() <span class="hljs-keyword">if</span> opts.help
|
||||
<span class="hljs-keyword">return</span> version() <span class="hljs-keyword">if</span> opts.version
|
||||
<span class="hljs-keyword">return</span> <span class="hljs-built_in">require</span>(<span class="hljs-string">'./repl'</span>).start(replCliOpts) <span class="hljs-keyword">if</span> opts.interactive
|
||||
<span class="hljs-keyword">return</span> <span class="hljs-built_in">require</span>(<span class="hljs-string">'./repl'</span>).start(replCliOpts) <span class="hljs-keyword">if</span> opts.interactive
|
||||
<span class="hljs-keyword">return</span> compileStdio() <span class="hljs-keyword">if</span> opts.stdio
|
||||
<span class="hljs-keyword">return</span> compileScript <span class="hljs-literal">null</span>, opts.arguments[<span class="hljs-number">0</span>] <span class="hljs-keyword">if</span> opts.eval
|
||||
<span class="hljs-keyword">return</span> <span class="hljs-built_in">require</span>(<span class="hljs-string">'./repl'</span>).start(replCliOpts) <span class="hljs-keyword">unless</span> opts.arguments.length
|
||||
<span class="hljs-keyword">return</span> compileScript <span class="hljs-literal">null</span>, opts.arguments[<span class="hljs-number">0</span>] <span class="hljs-keyword">if</span> opts.<span class="hljs-built_in">eval</span>
|
||||
<span class="hljs-keyword">return</span> <span class="hljs-built_in">require</span>(<span class="hljs-string">'./repl'</span>).start(replCliOpts) <span class="hljs-keyword">unless</span> opts.arguments.length
|
||||
literals = <span class="hljs-keyword">if</span> opts.run <span class="hljs-keyword">then</span> opts.arguments.splice <span class="hljs-number">1</span> <span class="hljs-keyword">else</span> []
|
||||
process.argv = process.argv[<span class="hljs-number">0.</span><span class="hljs-number">.1</span>].concat literals
|
||||
process.argv[<span class="hljs-number">0</span>] = <span class="hljs-string">'coffee'</span>
|
||||
process.argv[<span class="hljs-number">0</span>] = <span class="hljs-string">'coffee'</span>
|
||||
|
||||
<span class="hljs-keyword">if</span> opts.output
|
||||
outputBasename = path.basename opts.output
|
||||
<span class="hljs-keyword">if</span> <span class="hljs-string">'.'</span> <span class="hljs-keyword">in</span> outputBasename <span class="hljs-keyword">and</span>
|
||||
outputBasename <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> [<span class="hljs-string">'.'</span>, <span class="hljs-string">'..'</span>] <span class="hljs-keyword">and</span>
|
||||
<span class="hljs-keyword">if</span> <span class="hljs-string">'.'</span> <span class="hljs-keyword">in</span> outputBasename <span class="hljs-keyword">and</span>
|
||||
outputBasename <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> [<span class="hljs-string">'.'</span>, <span class="hljs-string">'..'</span>] <span class="hljs-keyword">and</span>
|
||||
<span class="hljs-keyword">not</span> helpers.ends(opts.output, path.sep)</pre></div></div>
|
||||
|
||||
</li>
|
||||
@@ -319,8 +320,8 @@ Many flags cause us to divert before compiling anything. Flags passed after
|
||||
<li id="section-9">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-9">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-9">§</a>
|
||||
</div>
|
||||
<p>An output filename was specified, e.g. <code>/dist/scripts.js</code>.</p>
|
||||
|
||||
@@ -336,8 +337,8 @@ Many flags cause us to divert before compiling anything. Flags passed after
|
||||
<li id="section-10">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-10">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-10">§</a>
|
||||
</div>
|
||||
<p>An output path was specified, e.g. <code>/dist</code>.</p>
|
||||
|
||||
@@ -348,11 +349,11 @@ Many flags cause us to divert before compiling anything. Flags passed after
|
||||
|
||||
<span class="hljs-keyword">if</span> opts.join
|
||||
opts.join = path.resolve opts.join
|
||||
<span class="hljs-built_in">console</span>.error <span class="hljs-string">'''
|
||||
console.error <span class="hljs-string">'''
|
||||
|
||||
The --join option is deprecated and will be removed in a future version.
|
||||
|
||||
If for some reason it's necessary to share local variables between files,
|
||||
If for some reason it's necessary to share local variables between files,
|
||||
replace...
|
||||
|
||||
$ coffee --compile --join bundle.js -- a.coffee b.coffee c.coffee
|
||||
@@ -361,17 +362,17 @@ Many flags cause us to divert before compiling anything. Flags passed after
|
||||
|
||||
$ cat a.coffee b.coffee c.coffee | coffee --compile --stdio > bundle.js
|
||||
|
||||
'''</span>
|
||||
'''</span>
|
||||
<span class="hljs-keyword">for</span> source <span class="hljs-keyword">in</span> opts.arguments
|
||||
source = path.resolve source
|
||||
compilePath source, <span class="hljs-literal">yes</span>, source
|
||||
<span class="hljs-function">
|
||||
<span class="hljs-title">makePrelude</span> = <span class="hljs-params">(requires)</span> -></span>
|
||||
requires.map (<span class="hljs-built_in">module</span>) ->
|
||||
[full, name, <span class="hljs-built_in">module</span>] = match <span class="hljs-keyword">if</span> match = <span class="hljs-built_in">module</span>.match(<span class="hljs-regexp">/^(.*)=(.*)$/</span>)
|
||||
name <span class="hljs-keyword">or</span>= helpers.baseFileName <span class="hljs-built_in">module</span>, <span class="hljs-literal">yes</span>, useWinPathSep
|
||||
<span class="hljs-string">"global['<span class="hljs-subst">#{name}</span>'] = require('<span class="hljs-subst">#{<span class="hljs-built_in">module</span>}</span>')"</span>
|
||||
.join <span class="hljs-string">';'</span></pre></div></div>
|
||||
requires.map (module) ->
|
||||
[full, name, module] = match <span class="hljs-keyword">if</span> match = module.match(<span class="hljs-regexp">/^(.*)=(.*)$/</span>)
|
||||
name <span class="hljs-keyword">or</span>= helpers.baseFileName module, <span class="hljs-literal">yes</span>, useWinPathSep
|
||||
<span class="hljs-string">"global['<span class="hljs-subst">#{name}</span>'] = require('<span class="hljs-subst">#{module}</span>')"</span>
|
||||
.join <span class="hljs-string">';'</span></pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -379,8 +380,8 @@ Many flags cause us to divert before compiling anything. Flags passed after
|
||||
<li id="section-11">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-11">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-11">§</a>
|
||||
</div>
|
||||
<p>Compile a path, which could be a script or a directory. If a directory
|
||||
is passed, recursively compile all ‘.coffee’, ‘.litcoffee’, and ‘.coffee.md’
|
||||
@@ -395,12 +396,12 @@ extension source files in it and all subdirectories.</p>
|
||||
<span class="hljs-keyword">try</span>
|
||||
stats = fs.statSync source
|
||||
<span class="hljs-keyword">catch</span> err
|
||||
<span class="hljs-keyword">if</span> err.code <span class="hljs-keyword">is</span> <span class="hljs-string">'ENOENT'</span>
|
||||
<span class="hljs-built_in">console</span>.error <span class="hljs-string">"File not found: <span class="hljs-subst">#{source}</span>"</span>
|
||||
<span class="hljs-keyword">if</span> err.code <span class="hljs-keyword">is</span> <span class="hljs-string">'ENOENT'</span>
|
||||
console.error <span class="hljs-string">"File not found: <span class="hljs-subst">#{source}</span>"</span>
|
||||
process.exit <span class="hljs-number">1</span>
|
||||
<span class="hljs-keyword">throw</span> err
|
||||
<span class="hljs-keyword">if</span> stats.isDirectory()
|
||||
<span class="hljs-keyword">if</span> path.basename(source) <span class="hljs-keyword">is</span> <span class="hljs-string">'node_modules'</span>
|
||||
<span class="hljs-keyword">if</span> path.basename(source) <span class="hljs-keyword">is</span> <span class="hljs-string">'node_modules'</span>
|
||||
notSources[source] = <span class="hljs-literal">yes</span>
|
||||
<span class="hljs-keyword">return</span>
|
||||
<span class="hljs-keyword">if</span> opts.run
|
||||
@@ -410,7 +411,7 @@ extension source files in it and all subdirectories.</p>
|
||||
<span class="hljs-keyword">try</span>
|
||||
files = fs.readdirSync source
|
||||
<span class="hljs-keyword">catch</span> err
|
||||
<span class="hljs-keyword">if</span> err.code <span class="hljs-keyword">is</span> <span class="hljs-string">'ENOENT'</span> <span class="hljs-keyword">then</span> <span class="hljs-keyword">return</span> <span class="hljs-keyword">else</span> <span class="hljs-keyword">throw</span> err
|
||||
<span class="hljs-keyword">if</span> err.code <span class="hljs-keyword">is</span> <span class="hljs-string">'ENOENT'</span> <span class="hljs-keyword">then</span> <span class="hljs-keyword">return</span> <span class="hljs-keyword">else</span> <span class="hljs-keyword">throw</span> err
|
||||
<span class="hljs-keyword">for</span> file <span class="hljs-keyword">in</span> files
|
||||
compilePath (path.join source, file), <span class="hljs-literal">no</span>, base
|
||||
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> topLevel <span class="hljs-keyword">or</span> helpers.isCoffee source
|
||||
@@ -421,19 +422,19 @@ extension source files in it and all subdirectories.</p>
|
||||
<span class="hljs-keyword">try</span>
|
||||
code = fs.readFileSync source
|
||||
<span class="hljs-keyword">catch</span> err
|
||||
<span class="hljs-keyword">if</span> err.code <span class="hljs-keyword">is</span> <span class="hljs-string">'ENOENT'</span> <span class="hljs-keyword">then</span> <span class="hljs-keyword">return</span> <span class="hljs-keyword">else</span> <span class="hljs-keyword">throw</span> err
|
||||
<span class="hljs-keyword">if</span> err.code <span class="hljs-keyword">is</span> <span class="hljs-string">'ENOENT'</span> <span class="hljs-keyword">then</span> <span class="hljs-keyword">return</span> <span class="hljs-keyword">else</span> <span class="hljs-keyword">throw</span> err
|
||||
compileScript source, code.toString(), base
|
||||
<span class="hljs-keyword">else</span>
|
||||
notSources[source] = <span class="hljs-literal">yes</span>
|
||||
<span class="hljs-function">
|
||||
<span class="hljs-title">findDirectoryIndex</span> = <span class="hljs-params">(source)</span> -></span>
|
||||
<span class="hljs-keyword">for</span> ext <span class="hljs-keyword">in</span> CoffeeScript.FILE_EXTENSIONS
|
||||
index = path.join source, <span class="hljs-string">"index<span class="hljs-subst">#{ext}</span>"</span>
|
||||
index = path.join source, <span class="hljs-string">"index<span class="hljs-subst">#{ext}</span>"</span>
|
||||
<span class="hljs-keyword">try</span>
|
||||
<span class="hljs-keyword">return</span> index <span class="hljs-keyword">if</span> (fs.statSync index).isFile()
|
||||
<span class="hljs-keyword">catch</span> err
|
||||
<span class="hljs-keyword">throw</span> err <span class="hljs-keyword">unless</span> err.code <span class="hljs-keyword">is</span> <span class="hljs-string">'ENOENT'</span>
|
||||
<span class="hljs-built_in">console</span>.error <span class="hljs-string">"Missing index.coffee or index.litcoffee in <span class="hljs-subst">#{source}</span>"</span>
|
||||
<span class="hljs-keyword">throw</span> err <span class="hljs-keyword">unless</span> err.code <span class="hljs-keyword">is</span> <span class="hljs-string">'ENOENT'</span>
|
||||
console.error <span class="hljs-string">"Missing index.coffee or index.litcoffee in <span class="hljs-subst">#{source}</span>"</span>
|
||||
process.exit <span class="hljs-number">1</span></pre></div></div>
|
||||
|
||||
</li>
|
||||
@@ -442,8 +443,8 @@ extension source files in it and all subdirectories.</p>
|
||||
<li id="section-12">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-12">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-12">§</a>
|
||||
</div>
|
||||
<p>Compile a single source script, containing the given code, according to the
|
||||
requested options. If evaluating the script directly, set <code>__filename</code>,
|
||||
@@ -455,14 +456,17 @@ requested options. If evaluating the script directly, set <code>__filename</code
|
||||
options = compileOptions file, base
|
||||
<span class="hljs-keyword">try</span>
|
||||
task = {file, input, options}
|
||||
CoffeeScript.emit <span class="hljs-string">'compile'</span>, task
|
||||
CoffeeScript.emit <span class="hljs-string">'compile'</span>, task
|
||||
<span class="hljs-keyword">if</span> opts.tokens
|
||||
printTokens CoffeeScript.tokens task.input, task.options
|
||||
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> opts.nodes
|
||||
printLine CoffeeScript.nodes(task.input, task.options).toString().trim()
|
||||
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> opts.ast
|
||||
compiled = CoffeeScript.compile task.input, task.options
|
||||
printLine <span class="hljs-built_in">JSON</span>.stringify(compiled, <span class="hljs-literal">null</span>, <span class="hljs-number">2</span>)
|
||||
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> opts.run
|
||||
CoffeeScript.register()
|
||||
CoffeeScript.eval opts.prelude, task.options <span class="hljs-keyword">if</span> opts.prelude
|
||||
CoffeeScript.<span class="hljs-built_in">eval</span> opts.prelude, task.options <span class="hljs-keyword">if</span> opts.prelude
|
||||
CoffeeScript.run task.input, task.options
|
||||
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> opts.join <span class="hljs-keyword">and</span> task.file <span class="hljs-keyword">isnt</span> opts.join
|
||||
task.input = helpers.invertLiterate task.input <span class="hljs-keyword">if</span> helpers.isLiterate file
|
||||
@@ -475,7 +479,7 @@ requested options. If evaluating the script directly, set <code>__filename</code
|
||||
task.output = compiled.js
|
||||
task.sourceMap = compiled.v3SourceMap
|
||||
|
||||
CoffeeScript.emit <span class="hljs-string">'success'</span>, task
|
||||
CoffeeScript.emit <span class="hljs-string">'success'</span>, task
|
||||
<span class="hljs-keyword">if</span> opts.<span class="hljs-built_in">print</span>
|
||||
printLine task.output.trim()
|
||||
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> opts.compile <span class="hljs-keyword">or</span> opts.map
|
||||
@@ -485,11 +489,11 @@ requested options. If evaluating the script directly, set <code>__filename</code
|
||||
options.jsPath
|
||||
writeJs base, task.file, task.output, saveTo, task.sourceMap
|
||||
<span class="hljs-keyword">catch</span> err
|
||||
CoffeeScript.emit <span class="hljs-string">'failure'</span>, err, task
|
||||
<span class="hljs-keyword">return</span> <span class="hljs-keyword">if</span> CoffeeScript.listeners(<span class="hljs-string">'failure'</span>).length
|
||||
message = err?.stack <span class="hljs-keyword">or</span> <span class="hljs-string">"<span class="hljs-subst">#{err}</span>"</span>
|
||||
CoffeeScript.emit <span class="hljs-string">'failure'</span>, err, task
|
||||
<span class="hljs-keyword">return</span> <span class="hljs-keyword">if</span> CoffeeScript.listeners(<span class="hljs-string">'failure'</span>).length
|
||||
message = err?.stack <span class="hljs-keyword">or</span> <span class="hljs-string">"<span class="hljs-subst">#{err}</span>"</span>
|
||||
<span class="hljs-keyword">if</span> opts.watch
|
||||
printLine message + <span class="hljs-string">'\x07'</span>
|
||||
printLine message + <span class="hljs-string">'\x07'</span>
|
||||
<span class="hljs-keyword">else</span>
|
||||
printWarn message
|
||||
process.exit <span class="hljs-number">1</span></pre></div></div>
|
||||
@@ -500,8 +504,8 @@ requested options. If evaluating the script directly, set <code>__filename</code
|
||||
<li id="section-13">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-13">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-13">§</a>
|
||||
</div>
|
||||
<p>Attach the appropriate listeners to compile scripts incoming over <strong>stdin</strong>,
|
||||
and write them back to <strong>stdout</strong>.</p>
|
||||
@@ -510,13 +514,13 @@ and write them back to <strong>stdout</strong>.</p>
|
||||
|
||||
<div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">compileStdio</span> = -></span>
|
||||
<span class="hljs-keyword">if</span> opts.map
|
||||
<span class="hljs-built_in">console</span>.error <span class="hljs-string">'--stdio and --map cannot be used together'</span>
|
||||
console.error <span class="hljs-string">'--stdio and --map cannot be used together'</span>
|
||||
process.exit <span class="hljs-number">1</span>
|
||||
buffers = []
|
||||
stdin = process.openStdin()
|
||||
stdin.<span class="hljs-literal">on</span> <span class="hljs-string">'data'</span>, <span class="hljs-function"><span class="hljs-params">(buffer)</span> -></span>
|
||||
stdin.<span class="hljs-literal">on</span> <span class="hljs-string">'data'</span>, <span class="hljs-function"><span class="hljs-params">(buffer)</span> -></span>
|
||||
buffers.push buffer <span class="hljs-keyword">if</span> buffer
|
||||
stdin.<span class="hljs-literal">on</span> <span class="hljs-string">'end'</span>, <span class="hljs-function">-></span>
|
||||
stdin.<span class="hljs-literal">on</span> <span class="hljs-string">'end'</span>, <span class="hljs-function">-></span>
|
||||
compileScript <span class="hljs-literal">null</span>, Buffer.concat(buffers).toString()</pre></div></div>
|
||||
|
||||
</li>
|
||||
@@ -525,8 +529,8 @@ and write them back to <strong>stdout</strong>.</p>
|
||||
<li id="section-14">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-14">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-14">§</a>
|
||||
</div>
|
||||
<p>If all of the source files are done being read, concatenate and compile
|
||||
them together.</p>
|
||||
@@ -537,9 +541,9 @@ them together.</p>
|
||||
<span class="hljs-function"><span class="hljs-title">compileJoin</span> = -></span>
|
||||
<span class="hljs-keyword">return</span> <span class="hljs-keyword">unless</span> opts.join
|
||||
<span class="hljs-keyword">unless</span> sourceCode.some(<span class="hljs-function"><span class="hljs-params">(code)</span> -></span> code <span class="hljs-keyword">is</span> <span class="hljs-literal">null</span>)
|
||||
clearTimeout joinTimeout
|
||||
<span class="hljs-built_in">clearTimeout</span> joinTimeout
|
||||
joinTimeout = wait <span class="hljs-number">100</span>, <span class="hljs-function">-></span>
|
||||
compileScript opts.join, sourceCode.join(<span class="hljs-string">'\n'</span>), opts.join</pre></div></div>
|
||||
compileScript opts.join, sourceCode.join(<span class="hljs-string">'\n'</span>), opts.join</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -547,8 +551,8 @@ them together.</p>
|
||||
<li id="section-15">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-15">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-15">§</a>
|
||||
</div>
|
||||
<p>Watch a source CoffeeScript file using <code>fs.watch</code>, recompiling it every
|
||||
time the file is updated. May be used in combination with other options,
|
||||
@@ -562,7 +566,7 @@ such as <code>--print</code>.</p>
|
||||
compileTimeout = <span class="hljs-literal">null</span>
|
||||
<span class="hljs-function">
|
||||
<span class="hljs-title">watchErr</span> = <span class="hljs-params">(err)</span> -></span>
|
||||
<span class="hljs-keyword">throw</span> err <span class="hljs-keyword">unless</span> err.code <span class="hljs-keyword">is</span> <span class="hljs-string">'ENOENT'</span>
|
||||
<span class="hljs-keyword">throw</span> err <span class="hljs-keyword">unless</span> err.code <span class="hljs-keyword">is</span> <span class="hljs-string">'ENOENT'</span>
|
||||
<span class="hljs-keyword">return</span> <span class="hljs-keyword">unless</span> source <span class="hljs-keyword">in</span> sources
|
||||
<span class="hljs-keyword">try</span>
|
||||
rewatch()
|
||||
@@ -572,7 +576,7 @@ such as <code>--print</code>.</p>
|
||||
compileJoin()
|
||||
<span class="hljs-function">
|
||||
<span class="hljs-title">compile</span> = -></span>
|
||||
clearTimeout compileTimeout
|
||||
<span class="hljs-built_in">clearTimeout</span> compileTimeout
|
||||
compileTimeout = wait <span class="hljs-number">25</span>, <span class="hljs-function">-></span>
|
||||
fs.stat source, <span class="hljs-function"><span class="hljs-params">(err, stats)</span> -></span>
|
||||
<span class="hljs-keyword">return</span> watchErr err <span class="hljs-keyword">if</span> err
|
||||
@@ -587,9 +591,9 @@ such as <code>--print</code>.</p>
|
||||
<span class="hljs-function">
|
||||
<span class="hljs-title">startWatcher</span> = -></span>
|
||||
watcher = fs.watch source
|
||||
.<span class="hljs-literal">on</span> <span class="hljs-string">'change'</span>, compile
|
||||
.<span class="hljs-literal">on</span> <span class="hljs-string">'error'</span>, <span class="hljs-function"><span class="hljs-params">(err)</span> -></span>
|
||||
<span class="hljs-keyword">throw</span> err <span class="hljs-keyword">unless</span> err.code <span class="hljs-keyword">is</span> <span class="hljs-string">'EPERM'</span>
|
||||
.<span class="hljs-literal">on</span> <span class="hljs-string">'change'</span>, compile
|
||||
.<span class="hljs-literal">on</span> <span class="hljs-string">'error'</span>, <span class="hljs-function"><span class="hljs-params">(err)</span> -></span>
|
||||
<span class="hljs-keyword">throw</span> err <span class="hljs-keyword">unless</span> err.code <span class="hljs-keyword">is</span> <span class="hljs-string">'EPERM'</span>
|
||||
removeSource source, base
|
||||
<span class="hljs-function">
|
||||
<span class="hljs-title">rewatch</span> = -></span>
|
||||
@@ -607,8 +611,8 @@ such as <code>--print</code>.</p>
|
||||
<li id="section-16">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-16">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-16">§</a>
|
||||
</div>
|
||||
<p>Watch a directory of files for new additions.</p>
|
||||
|
||||
@@ -620,16 +624,16 @@ such as <code>--print</code>.</p>
|
||||
<span class="hljs-function">
|
||||
<span class="hljs-title">startWatcher</span> = -></span>
|
||||
watcher = fs.watch source
|
||||
.<span class="hljs-literal">on</span> <span class="hljs-string">'error'</span>, <span class="hljs-function"><span class="hljs-params">(err)</span> -></span>
|
||||
<span class="hljs-keyword">throw</span> err <span class="hljs-keyword">unless</span> err.code <span class="hljs-keyword">is</span> <span class="hljs-string">'EPERM'</span>
|
||||
.<span class="hljs-literal">on</span> <span class="hljs-string">'error'</span>, <span class="hljs-function"><span class="hljs-params">(err)</span> -></span>
|
||||
<span class="hljs-keyword">throw</span> err <span class="hljs-keyword">unless</span> err.code <span class="hljs-keyword">is</span> <span class="hljs-string">'EPERM'</span>
|
||||
stopWatcher()
|
||||
.<span class="hljs-literal">on</span> <span class="hljs-string">'change'</span>, <span class="hljs-function">-></span>
|
||||
clearTimeout readdirTimeout
|
||||
.<span class="hljs-literal">on</span> <span class="hljs-string">'change'</span>, <span class="hljs-function">-></span>
|
||||
<span class="hljs-built_in">clearTimeout</span> readdirTimeout
|
||||
readdirTimeout = wait <span class="hljs-number">25</span>, <span class="hljs-function">-></span>
|
||||
<span class="hljs-keyword">try</span>
|
||||
files = fs.readdirSync source
|
||||
<span class="hljs-keyword">catch</span> err
|
||||
<span class="hljs-keyword">throw</span> err <span class="hljs-keyword">unless</span> err.code <span class="hljs-keyword">is</span> <span class="hljs-string">'ENOENT'</span>
|
||||
<span class="hljs-keyword">throw</span> err <span class="hljs-keyword">unless</span> err.code <span class="hljs-keyword">is</span> <span class="hljs-string">'ENOENT'</span>
|
||||
<span class="hljs-keyword">return</span> stopWatcher()
|
||||
<span class="hljs-keyword">for</span> file <span class="hljs-keyword">in</span> files
|
||||
compilePath (path.join source, file), <span class="hljs-literal">no</span>, base
|
||||
@@ -642,7 +646,7 @@ such as <code>--print</code>.</p>
|
||||
<span class="hljs-keyword">try</span>
|
||||
startWatcher()
|
||||
<span class="hljs-keyword">catch</span> err
|
||||
<span class="hljs-keyword">throw</span> err <span class="hljs-keyword">unless</span> err.code <span class="hljs-keyword">is</span> <span class="hljs-string">'ENOENT'</span>
|
||||
<span class="hljs-keyword">throw</span> err <span class="hljs-keyword">unless</span> err.code <span class="hljs-keyword">is</span> <span class="hljs-string">'ENOENT'</span>
|
||||
<span class="hljs-function">
|
||||
<span class="hljs-title">removeSourceDir</span> = <span class="hljs-params">(source, base)</span> -></span>
|
||||
<span class="hljs-keyword">delete</span> watchedDirs[source]
|
||||
@@ -658,8 +662,8 @@ such as <code>--print</code>.</p>
|
||||
<li id="section-17">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-17">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-17">§</a>
|
||||
</div>
|
||||
<p>Remove a file from our source list, and source code cache. Optionally remove
|
||||
the compiled JS version as well.</p>
|
||||
@@ -672,14 +676,14 @@ the compiled JS version as well.</p>
|
||||
sourceCode.splice index, <span class="hljs-number">1</span>
|
||||
<span class="hljs-keyword">unless</span> opts.join
|
||||
silentUnlink outputPath source, base
|
||||
silentUnlink outputPath source, base, <span class="hljs-string">'.js.map'</span>
|
||||
timeLog <span class="hljs-string">"removed <span class="hljs-subst">#{source}</span>"</span>
|
||||
silentUnlink outputPath source, base, <span class="hljs-string">'.js.map'</span>
|
||||
timeLog <span class="hljs-string">"removed <span class="hljs-subst">#{source}</span>"</span>
|
||||
<span class="hljs-function">
|
||||
<span class="hljs-title">silentUnlink</span> = <span class="hljs-params">(path)</span> -></span>
|
||||
<span class="hljs-keyword">try</span>
|
||||
fs.unlinkSync path
|
||||
<span class="hljs-keyword">catch</span> err
|
||||
<span class="hljs-keyword">throw</span> err <span class="hljs-keyword">unless</span> err.code <span class="hljs-keyword">in</span> [<span class="hljs-string">'ENOENT'</span>, <span class="hljs-string">'EPERM'</span>]</pre></div></div>
|
||||
<span class="hljs-keyword">throw</span> err <span class="hljs-keyword">unless</span> err.code <span class="hljs-keyword">in</span> [<span class="hljs-string">'ENOENT'</span>, <span class="hljs-string">'EPERM'</span>]</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -687,14 +691,14 @@ the compiled JS version as well.</p>
|
||||
<li id="section-18">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-18">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-18">§</a>
|
||||
</div>
|
||||
<p>Get the corresponding output JavaScript path for a source file.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">outputPath</span> = <span class="hljs-params">(source, base, extension=<span class="hljs-string">".js"</span>)</span> -></span>
|
||||
<div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">outputPath</span> = <span class="hljs-params">(source, base, extension=<span class="hljs-string">".js"</span>)</span> -></span>
|
||||
basename = helpers.baseFileName source, <span class="hljs-literal">yes</span>, useWinPathSep
|
||||
srcDir = path.dirname source
|
||||
dir = <span class="hljs-keyword">unless</span> opts.outputPath
|
||||
@@ -711,8 +715,8 @@ the compiled JS version as well.</p>
|
||||
<li id="section-19">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-19">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-19">§</a>
|
||||
</div>
|
||||
<p>Recursively mkdir, like <code>mkdir -p</code>.</p>
|
||||
|
||||
@@ -737,8 +741,8 @@ the compiled JS version as well.</p>
|
||||
<li id="section-20">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-20">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-20">§</a>
|
||||
</div>
|
||||
<p>Write out a JavaScript source file with the compiled code. By default, files
|
||||
are written out in <code>cwd</code> as <code>.js</code> files with the same name, but the output
|
||||
@@ -749,22 +753,22 @@ same directory as the <code>.js</code> file.</p>
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">writeJs</span> = <span class="hljs-params">(base, sourcePath, js, jsPath, generatedSourceMap = <span class="hljs-literal">null</span>)</span> -></span>
|
||||
sourceMapPath = <span class="hljs-string">"<span class="hljs-subst">#{jsPath}</span>.map"</span>
|
||||
sourceMapPath = <span class="hljs-string">"<span class="hljs-subst">#{jsPath}</span>.map"</span>
|
||||
jsDir = path.dirname jsPath
|
||||
<span class="hljs-function"> <span class="hljs-title">compile</span> = -></span>
|
||||
<span class="hljs-keyword">if</span> opts.compile
|
||||
js = <span class="hljs-string">' '</span> <span class="hljs-keyword">if</span> js.length <= <span class="hljs-number">0</span>
|
||||
<span class="hljs-keyword">if</span> generatedSourceMap <span class="hljs-keyword">then</span> js = <span class="hljs-string">"<span class="hljs-subst">#{js}</span>\n//# sourceMappingURL=<span class="hljs-subst">#{helpers.baseFileName sourceMapPath, <span class="hljs-literal">no</span>, useWinPathSep}</span>\n"</span>
|
||||
js = <span class="hljs-string">' '</span> <span class="hljs-keyword">if</span> js.length <= <span class="hljs-number">0</span>
|
||||
<span class="hljs-keyword">if</span> generatedSourceMap <span class="hljs-keyword">then</span> js = <span class="hljs-string">"<span class="hljs-subst">#{js}</span>\n//# sourceMappingURL=<span class="hljs-subst">#{helpers.baseFileName sourceMapPath, <span class="hljs-literal">no</span>, useWinPathSep}</span>\n"</span>
|
||||
fs.writeFile jsPath, js, <span class="hljs-function"><span class="hljs-params">(err)</span> -></span>
|
||||
<span class="hljs-keyword">if</span> err
|
||||
printLine err.message
|
||||
process.exit <span class="hljs-number">1</span>
|
||||
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> opts.compile <span class="hljs-keyword">and</span> opts.watch
|
||||
timeLog <span class="hljs-string">"compiled <span class="hljs-subst">#{sourcePath}</span>"</span>
|
||||
timeLog <span class="hljs-string">"compiled <span class="hljs-subst">#{sourcePath}</span>"</span>
|
||||
<span class="hljs-keyword">if</span> generatedSourceMap
|
||||
fs.writeFile sourceMapPath, generatedSourceMap, <span class="hljs-function"><span class="hljs-params">(err)</span> -></span>
|
||||
<span class="hljs-keyword">if</span> err
|
||||
printLine <span class="hljs-string">"Could not write source map: <span class="hljs-subst">#{err.message}</span>"</span>
|
||||
printLine <span class="hljs-string">"Could not write source map: <span class="hljs-subst">#{err.message}</span>"</span>
|
||||
process.exit <span class="hljs-number">1</span>
|
||||
fs.exists jsDir, <span class="hljs-function"><span class="hljs-params">(itExists)</span> -></span>
|
||||
<span class="hljs-keyword">if</span> itExists <span class="hljs-keyword">then</span> compile() <span class="hljs-keyword">else</span> mkdirp jsDir, compile</pre></div></div>
|
||||
@@ -775,14 +779,14 @@ same directory as the <code>.js</code> file.</p>
|
||||
<li id="section-21">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-21">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-21">§</a>
|
||||
</div>
|
||||
<p>Convenience for cleaner setTimeouts.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">wait</span> = <span class="hljs-params">(milliseconds, func)</span> -></span> setTimeout func, milliseconds</pre></div></div>
|
||||
<div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">wait</span> = <span class="hljs-params">(milliseconds, func)</span> -></span> <span class="hljs-built_in">setTimeout</span> func, milliseconds</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -790,15 +794,15 @@ same directory as the <code>.js</code> file.</p>
|
||||
<li id="section-22">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-22">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-22">§</a>
|
||||
</div>
|
||||
<p>When watching scripts, it’s useful to log changes with the timestamp.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">timeLog</span> = <span class="hljs-params">(message)</span> -></span>
|
||||
<span class="hljs-built_in">console</span>.log <span class="hljs-string">"<span class="hljs-subst">#{(<span class="hljs-keyword">new</span> Date).toLocaleTimeString()}</span> - <span class="hljs-subst">#{message}</span>"</span></pre></div></div>
|
||||
console.log <span class="hljs-string">"<span class="hljs-subst">#{(<span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>).toLocaleTimeString()}</span> - <span class="hljs-subst">#{message}</span>"</span></pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -806,8 +810,8 @@ same directory as the <code>.js</code> file.</p>
|
||||
<li id="section-23">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-23">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-23">§</a>
|
||||
</div>
|
||||
<p>Pretty-print a stream of tokens, sans location data.</p>
|
||||
|
||||
@@ -816,9 +820,9 @@ same directory as the <code>.js</code> file.</p>
|
||||
<div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">printTokens</span> = <span class="hljs-params">(tokens)</span> -></span>
|
||||
strings = <span class="hljs-keyword">for</span> token <span class="hljs-keyword">in</span> tokens
|
||||
tag = token[<span class="hljs-number">0</span>]
|
||||
value = token[<span class="hljs-number">1</span>].toString().replace(<span class="hljs-regexp">/\n/</span>, <span class="hljs-string">'\\n'</span>)
|
||||
<span class="hljs-string">"[<span class="hljs-subst">#{tag}</span> <span class="hljs-subst">#{value}</span>]"</span>
|
||||
printLine strings.join(<span class="hljs-string">' '</span>)</pre></div></div>
|
||||
value = token[<span class="hljs-number">1</span>].toString().replace(<span class="hljs-regexp">/\n/</span>, <span class="hljs-string">'\\n'</span>)
|
||||
<span class="hljs-string">"[<span class="hljs-subst">#{tag}</span> <span class="hljs-subst">#{value}</span>]"</span>
|
||||
printLine strings.join(<span class="hljs-string">' '</span>)</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -826,8 +830,8 @@ same directory as the <code>.js</code> file.</p>
|
||||
<li id="section-24">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-24">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-24">§</a>
|
||||
</div>
|
||||
<p>Use the <a href="optparse.html">OptionParser module</a> to extract all options from
|
||||
<code>process.argv</code> that are specified in <code>SWITCHES</code>.</p>
|
||||
@@ -838,7 +842,7 @@ same directory as the <code>.js</code> file.</p>
|
||||
o = opts = optionParser.parse process.argv[<span class="hljs-number">2.</span>.]
|
||||
o.compile <span class="hljs-keyword">or</span>= !!o.output
|
||||
o.run = <span class="hljs-keyword">not</span> (o.compile <span class="hljs-keyword">or</span> o.<span class="hljs-built_in">print</span> <span class="hljs-keyword">or</span> o.map)
|
||||
o.<span class="hljs-built_in">print</span> = !! (o.<span class="hljs-built_in">print</span> <span class="hljs-keyword">or</span> (o.eval <span class="hljs-keyword">or</span> o.stdio <span class="hljs-keyword">and</span> o.compile))</pre></div></div>
|
||||
o.<span class="hljs-built_in">print</span> = !! (o.<span class="hljs-built_in">print</span> <span class="hljs-keyword">or</span> (o.<span class="hljs-built_in">eval</span> <span class="hljs-keyword">or</span> o.stdio <span class="hljs-keyword">and</span> o.compile))</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -846,8 +850,8 @@ same directory as the <code>.js</code> file.</p>
|
||||
<li id="section-25">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-25">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-25">§</a>
|
||||
</div>
|
||||
<p>The compile-time options to pass to the CoffeeScript compiler.</p>
|
||||
|
||||
@@ -862,8 +866,8 @@ same directory as the <code>.js</code> file.</p>
|
||||
<li id="section-26">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-26">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-26">§</a>
|
||||
</div>
|
||||
<p>The user has requested that the CoffeeScript compiler also transpile
|
||||
via Babel. We don’t include Babel as a dependency because we want to
|
||||
@@ -875,10 +879,10 @@ browsers) or use a proper build chain like Gulp or Webpack.</p>
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">try</span>
|
||||
<span class="hljs-built_in">require</span> <span class="hljs-string">'@babel/core'</span>
|
||||
<span class="hljs-built_in">require</span> <span class="hljs-string">'@babel/core'</span>
|
||||
<span class="hljs-keyword">catch</span>
|
||||
<span class="hljs-keyword">try</span>
|
||||
<span class="hljs-built_in">require</span> <span class="hljs-string">'babel-core'</span>
|
||||
<span class="hljs-built_in">require</span> <span class="hljs-string">'babel-core'</span>
|
||||
<span class="hljs-keyword">catch</span></pre></div></div>
|
||||
|
||||
</li>
|
||||
@@ -887,31 +891,31 @@ browsers) or use a proper build chain like Gulp or Webpack.</p>
|
||||
<li id="section-27">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-27">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-27">§</a>
|
||||
</div>
|
||||
<p>Give appropriate instructions depending on whether <code>coffee</code> was run
|
||||
locally or globally.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> <span class="hljs-built_in">require</span>.resolve(<span class="hljs-string">'.'</span>).indexOf(process.cwd()) <span class="hljs-keyword">is</span> <span class="hljs-number">0</span>
|
||||
<span class="hljs-built_in">console</span>.error <span class="hljs-string">'''
|
||||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> <span class="hljs-built_in">require</span>.resolve(<span class="hljs-string">'.'</span>).indexOf(process.cwd()) <span class="hljs-keyword">is</span> <span class="hljs-number">0</span>
|
||||
console.error <span class="hljs-string">'''
|
||||
To use --transpile, you must have @babel/core installed:
|
||||
npm install --save-dev @babel/core
|
||||
And you must save options to configure Babel in one of the places it looks to find its options.
|
||||
See https://coffeescript.org/#transpilation
|
||||
'''</span>
|
||||
'''</span>
|
||||
<span class="hljs-keyword">else</span>
|
||||
<span class="hljs-built_in">console</span>.error <span class="hljs-string">'''
|
||||
console.error <span class="hljs-string">'''
|
||||
To use --transpile with globally-installed CoffeeScript, you must have @babel/core installed globally:
|
||||
npm install --global @babel/core
|
||||
And you must save options to configure Babel in one of the places it looks to find its options, relative to the file being compiled or to the current folder.
|
||||
See https://coffeescript.org/#transpilation
|
||||
'''</span>
|
||||
'''</span>
|
||||
process.exit <span class="hljs-number">1</span>
|
||||
|
||||
opts.transpile = {} <span class="hljs-keyword">unless</span> <span class="hljs-keyword">typeof</span> opts.transpile <span class="hljs-keyword">is</span> <span class="hljs-string">'object'</span></pre></div></div>
|
||||
opts.transpile = {} <span class="hljs-keyword">unless</span> <span class="hljs-keyword">typeof</span> opts.transpile <span class="hljs-keyword">is</span> <span class="hljs-string">'object'</span></pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -919,8 +923,8 @@ locally or globally.</p>
|
||||
<li id="section-28">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-28">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-28">§</a>
|
||||
</div>
|
||||
<p>Pass a reference to Babel into the compiler, so that the transpile option
|
||||
is available for the CLI. We need to do this so that tools like Webpack
|
||||
@@ -937,8 +941,8 @@ require Babel.</p>
|
||||
<li id="section-29">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-29">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-29">§</a>
|
||||
</div>
|
||||
<p>Babel searches for its options (a <code>.babelrc</code> file, a <code>.babelrc.js</code> file,
|
||||
a <code>package.json</code> file with a <code>babel</code> key, etc.) relative to the path
|
||||
@@ -948,7 +952,7 @@ along.</p>
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">unless</span> opts.transpile.filename
|
||||
opts.transpile.filename = filename <span class="hljs-keyword">or</span> path.resolve(base <span class="hljs-keyword">or</span> process.cwd(), <span class="hljs-string">'<anonymous>'</span>)
|
||||
opts.transpile.filename = filename <span class="hljs-keyword">or</span> path.resolve(base <span class="hljs-keyword">or</span> process.cwd(), <span class="hljs-string">'<anonymous>'</span>)
|
||||
<span class="hljs-keyword">else</span>
|
||||
opts.transpile = <span class="hljs-literal">no</span>
|
||||
|
||||
@@ -956,10 +960,11 @@ along.</p>
|
||||
filename: filename
|
||||
literate: opts.literate <span class="hljs-keyword">or</span> helpers.isLiterate(filename)
|
||||
bare: opts.bare
|
||||
header: opts.compile <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> opts[<span class="hljs-string">'no-header'</span>]
|
||||
header: opts.compile <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> opts[<span class="hljs-string">'no-header'</span>]
|
||||
transpile: opts.transpile
|
||||
sourceMap: opts.map
|
||||
inlineMap: opts[<span class="hljs-string">'inline-map'</span>]
|
||||
inlineMap: opts[<span class="hljs-string">'inline-map'</span>]
|
||||
ast: opts.ast
|
||||
|
||||
<span class="hljs-keyword">if</span> filename
|
||||
<span class="hljs-keyword">if</span> base
|
||||
@@ -968,15 +973,15 @@ along.</p>
|
||||
jsDir = path.dirname jsPath
|
||||
answer = helpers.merge answer, {
|
||||
jsPath
|
||||
sourceRoot: path.relative jsDir, cwd
|
||||
sourceRoot: path.relative(jsDir, cwd) + path.sep
|
||||
sourceFiles: [path.relative cwd, filename]
|
||||
generatedFile: helpers.baseFileName(jsPath, <span class="hljs-literal">no</span>, useWinPathSep)
|
||||
}
|
||||
<span class="hljs-keyword">else</span>
|
||||
answer = helpers.merge answer,
|
||||
sourceRoot: <span class="hljs-string">""</span>
|
||||
sourceRoot: <span class="hljs-string">""</span>
|
||||
sourceFiles: [helpers.baseFileName filename, <span class="hljs-literal">no</span>, useWinPathSep]
|
||||
generatedFile: helpers.baseFileName(filename, <span class="hljs-literal">yes</span>, useWinPathSep) + <span class="hljs-string">".js"</span>
|
||||
generatedFile: helpers.baseFileName(filename, <span class="hljs-literal">yes</span>, useWinPathSep) + <span class="hljs-string">".js"</span>
|
||||
answer</pre></div></div>
|
||||
|
||||
</li>
|
||||
@@ -985,8 +990,8 @@ along.</p>
|
||||
<li id="section-30">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-30">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-30">§</a>
|
||||
</div>
|
||||
<p>Start up a new Node.js instance with the arguments in <code>--nodejs</code> passed to
|
||||
the <code>node</code> binary, preserving the other options.</p>
|
||||
@@ -996,15 +1001,15 @@ the <code>node</code> binary, preserving the other options.</p>
|
||||
<div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">forkNode</span> = -></span>
|
||||
nodeArgs = opts.nodejs.split <span class="hljs-regexp">/\s+/</span>
|
||||
args = process.argv[<span class="hljs-number">1.</span>.]
|
||||
args.splice args.indexOf(<span class="hljs-string">'--nodejs'</span>), <span class="hljs-number">2</span>
|
||||
args.splice args.indexOf(<span class="hljs-string">'--nodejs'</span>), <span class="hljs-number">2</span>
|
||||
p = spawn process.execPath, nodeArgs.concat(args),
|
||||
cwd: process.cwd()
|
||||
env: process.env
|
||||
stdio: [<span class="hljs-number">0</span>, <span class="hljs-number">1</span>, <span class="hljs-number">2</span>]
|
||||
<span class="hljs-keyword">for</span> signal <span class="hljs-keyword">in</span> [<span class="hljs-string">'SIGINT'</span>, <span class="hljs-string">'SIGTERM'</span>]
|
||||
<span class="hljs-keyword">for</span> signal <span class="hljs-keyword">in</span> [<span class="hljs-string">'SIGINT'</span>, <span class="hljs-string">'SIGTERM'</span>]
|
||||
process.<span class="hljs-literal">on</span> signal, <span class="hljs-keyword">do</span> (signal) ->
|
||||
-> p.kill signal
|
||||
p.<span class="hljs-literal">on</span> <span class="hljs-string">'exit'</span>, <span class="hljs-function"><span class="hljs-params">(code)</span> -></span> process.exit code</pre></div></div>
|
||||
p.<span class="hljs-literal">on</span> <span class="hljs-string">'exit'</span>, <span class="hljs-function"><span class="hljs-params">(code)</span> -></span> process.exit code</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -1012,8 +1017,8 @@ the <code>node</code> binary, preserving the other options.</p>
|
||||
<li id="section-31">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-31">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-31">§</a>
|
||||
</div>
|
||||
<p>Print the <code>--help</code> usage message and exit. Deprecated switches are not
|
||||
shown.</p>
|
||||
@@ -1029,15 +1034,15 @@ shown.</p>
|
||||
<li id="section-32">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-32">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-32">§</a>
|
||||
</div>
|
||||
<p>Print the <code>--version</code> message and exit.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">version</span> = -></span>
|
||||
printLine <span class="hljs-string">"CoffeeScript version <span class="hljs-subst">#{CoffeeScript.VERSION}</span>"</span></pre></div></div>
|
||||
printLine <span class="hljs-string">"CoffeeScript version <span class="hljs-subst">#{CoffeeScript.VERSION}</span>"</span></pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
@@ -213,7 +213,7 @@ ul.sections > li > div {
|
||||
|
||||
/*---------------------- Low resolutions (> 320px) ---------------------*/
|
||||
@media only screen and (min-width: 320px) {
|
||||
.pilwrap { display: none; }
|
||||
.sswrap { display: none; }
|
||||
|
||||
ul.sections > li > div {
|
||||
display: block;
|
||||
@@ -330,12 +330,12 @@ ul.sections > li > div {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.pilwrap {
|
||||
.sswrap {
|
||||
position: relative;
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.pilcrow {
|
||||
.ss {
|
||||
font: 12px Arial;
|
||||
text-decoration: none;
|
||||
color: #454545;
|
||||
@@ -345,14 +345,14 @@ ul.sections > li > div {
|
||||
opacity: 0;
|
||||
-webkit-transition: opacity 0.2s linear;
|
||||
}
|
||||
.for-h1 .pilcrow {
|
||||
.for-h1 .ss {
|
||||
top: 47px;
|
||||
}
|
||||
.for-h2 .pilcrow, .for-h3 .pilcrow, .for-h4 .pilcrow {
|
||||
.for-h2 .ss, .for-h3 .ss, .for-h4 .ss {
|
||||
top: 35px;
|
||||
}
|
||||
|
||||
ul.sections > li > div.annotation:hover .pilcrow {
|
||||
ul.sections > li > div.annotation:hover .ss {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -112,8 +112,8 @@
|
||||
<li id="section-1">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-1">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-1">§</a>
|
||||
</div>
|
||||
<p>This file contains the common helper functions that we’d like to share among
|
||||
the <strong>Lexer</strong>, <strong>Rewriter</strong>, and the <strong>Nodes</strong>. Merge objects, flatten
|
||||
@@ -127,14 +127,14 @@ arrays, count characters, that sort of thing.</p>
|
||||
<li id="section-2">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-2">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-2">§</a>
|
||||
</div>
|
||||
<p>Peek at the beginning of a given string to see if it matches a sequence.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre>exports.starts = <span class="hljs-function"><span class="hljs-params">(string, literal, start)</span> -></span>
|
||||
<div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.starts = <span class="hljs-function"><span class="hljs-params">(string, literal, start)</span> -></span>
|
||||
literal <span class="hljs-keyword">is</span> string.substr start, literal.length</pre></div></div>
|
||||
|
||||
</li>
|
||||
@@ -143,14 +143,14 @@ arrays, count characters, that sort of thing.</p>
|
||||
<li id="section-3">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-3">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-3">§</a>
|
||||
</div>
|
||||
<p>Peek at the end of a given string to see if it matches a sequence.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre>exports.ends = <span class="hljs-function"><span class="hljs-params">(string, literal, back)</span> -></span>
|
||||
<div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.ends = <span class="hljs-function"><span class="hljs-params">(string, literal, back)</span> -></span>
|
||||
len = literal.length
|
||||
literal <span class="hljs-keyword">is</span> string.substr string.length - len - (back <span class="hljs-keyword">or</span> <span class="hljs-number">0</span>), len</pre></div></div>
|
||||
|
||||
@@ -160,14 +160,14 @@ arrays, count characters, that sort of thing.</p>
|
||||
<li id="section-4">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-4">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-4">§</a>
|
||||
</div>
|
||||
<p>Repeat a string <code>n</code> times.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre>exports.repeat = repeat = <span class="hljs-function"><span class="hljs-params">(str, n)</span> -></span></pre></div></div>
|
||||
<div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.repeat = repeat = <span class="hljs-function"><span class="hljs-params">(str, n)</span> -></span></pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -175,14 +175,14 @@ arrays, count characters, that sort of thing.</p>
|
||||
<li id="section-5">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-5">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-5">§</a>
|
||||
</div>
|
||||
<p>Use clever algorithm to have O(log(n)) string concatenation operations.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> res = <span class="hljs-string">''</span>
|
||||
<div class="content"><div class='highlight'><pre> res = <span class="hljs-string">''</span>
|
||||
<span class="hljs-keyword">while</span> n > <span class="hljs-number">0</span>
|
||||
res += str <span class="hljs-keyword">if</span> n & <span class="hljs-number">1</span>
|
||||
n >>>= <span class="hljs-number">1</span>
|
||||
@@ -195,14 +195,14 @@ arrays, count characters, that sort of thing.</p>
|
||||
<li id="section-6">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-6">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-6">§</a>
|
||||
</div>
|
||||
<p>Trim out all falsy values from an array.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre>exports.compact = <span class="hljs-function"><span class="hljs-params">(array)</span> -></span>
|
||||
<div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.compact = <span class="hljs-function"><span class="hljs-params">(array)</span> -></span>
|
||||
item <span class="hljs-keyword">for</span> item <span class="hljs-keyword">in</span> array <span class="hljs-keyword">when</span> item</pre></div></div>
|
||||
|
||||
</li>
|
||||
@@ -211,14 +211,14 @@ arrays, count characters, that sort of thing.</p>
|
||||
<li id="section-7">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-7">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-7">§</a>
|
||||
</div>
|
||||
<p>Count the number of occurrences of a string in a string.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre>exports.count = <span class="hljs-function"><span class="hljs-params">(string, substr)</span> -></span>
|
||||
<div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.count = <span class="hljs-function"><span class="hljs-params">(string, substr)</span> -></span>
|
||||
num = pos = <span class="hljs-number">0</span>
|
||||
<span class="hljs-keyword">return</span> <span class="hljs-number">1</span>/<span class="hljs-number">0</span> <span class="hljs-keyword">unless</span> substr.length
|
||||
num++ <span class="hljs-keyword">while</span> pos = <span class="hljs-number">1</span> + string.indexOf substr, pos
|
||||
@@ -230,8 +230,8 @@ arrays, count characters, that sort of thing.</p>
|
||||
<li id="section-8">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-8">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" 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
|
||||
@@ -239,7 +239,7 @@ options hash to propagate down the tree without polluting other branches.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre>exports.merge = <span class="hljs-function"><span class="hljs-params">(options, overrides)</span> -></span>
|
||||
<div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.merge = <span class="hljs-function"><span class="hljs-params">(options, overrides)</span> -></span>
|
||||
extend (extend {}, options), overrides</pre></div></div>
|
||||
|
||||
</li>
|
||||
@@ -248,14 +248,14 @@ options hash to propagate down the tree without polluting other branches.</p>
|
||||
<li id="section-9">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-9">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-9">§</a>
|
||||
</div>
|
||||
<p>Extend a source object with the properties of another object (shallow copy).</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre>extend = exports.extend = <span class="hljs-function"><span class="hljs-params">(object, properties)</span> -></span>
|
||||
<div class="content"><div class='highlight'><pre>extend = <span class="hljs-built_in">exports</span>.extend = <span class="hljs-function"><span class="hljs-params">(object, properties)</span> -></span>
|
||||
<span class="hljs-keyword">for</span> key, val <span class="hljs-keyword">of</span> properties
|
||||
object[key] = val
|
||||
object</pre></div></div>
|
||||
@@ -266,18 +266,18 @@ options hash to propagate down the tree without polluting other branches.</p>
|
||||
<li id="section-10">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-10">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" 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>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre>exports.flatten = flatten = <span class="hljs-function"><span class="hljs-params">(array)</span> -></span>
|
||||
<div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.flatten = flatten = <span class="hljs-function"><span class="hljs-params">(array)</span> -></span>
|
||||
flattened = []
|
||||
<span class="hljs-keyword">for</span> element <span class="hljs-keyword">in</span> array
|
||||
<span class="hljs-keyword">if</span> <span class="hljs-string">'[object Array]'</span> <span class="hljs-keyword">is</span> Object::toString.call element
|
||||
<span class="hljs-keyword">if</span> <span class="hljs-string">'[object Array]'</span> <span class="hljs-keyword">is</span> Object::toString.call element
|
||||
flattened = flattened.concat flatten element
|
||||
<span class="hljs-keyword">else</span>
|
||||
flattened.push element
|
||||
@@ -289,15 +289,15 @@ Handy for getting a list of <code>children</code> from the nodes.</p>
|
||||
<li id="section-11">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-11">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" 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>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre>exports.del = <span class="hljs-function"><span class="hljs-params">(obj, key)</span> -></span>
|
||||
<div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.del = <span class="hljs-function"><span class="hljs-params">(obj, key)</span> -></span>
|
||||
val = obj[key]
|
||||
<span class="hljs-keyword">delete</span> obj[key]
|
||||
val</pre></div></div>
|
||||
@@ -308,15 +308,15 @@ looking for a particular method in an options hash.</p>
|
||||
<li id="section-12">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-12">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-12">§</a>
|
||||
</div>
|
||||
<p>Typical Array::some</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre>exports.some = Array::some ? (fn) ->
|
||||
<span class="hljs-keyword">return</span> <span class="hljs-literal">true</span> <span class="hljs-keyword">for</span> e <span class="hljs-keyword">in</span> <span class="hljs-keyword">this</span> <span class="hljs-keyword">when</span> fn e
|
||||
<div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.some = Array::some ? (fn) ->
|
||||
<span class="hljs-keyword">return</span> <span class="hljs-literal">true</span> <span class="hljs-keyword">for</span> e <span class="hljs-keyword">in</span> this <span class="hljs-keyword">when</span> fn e
|
||||
<span class="hljs-literal">false</span></pre></div></div>
|
||||
|
||||
</li>
|
||||
@@ -325,8 +325,8 @@ looking for a particular method in an options hash.</p>
|
||||
<li id="section-13">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-13">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-13">§</a>
|
||||
</div>
|
||||
<p>Helper function for extracting code from Literate CoffeeScript by stripping
|
||||
out all non-code blocks, producing a string of CoffeeScript code that can
|
||||
@@ -334,7 +334,7 @@ be compiled “normally.”</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre>exports.invertLiterate = <span class="hljs-function"><span class="hljs-params">(code)</span> -></span>
|
||||
<div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.invertLiterate = <span class="hljs-function"><span class="hljs-params">(code)</span> -></span>
|
||||
out = []
|
||||
blankLine = <span class="hljs-regexp">/^\s*$/</span>
|
||||
indented = <span class="hljs-regexp">/^[\t ]/</span>
|
||||
@@ -347,19 +347,19 @@ be compiled “normally.”</p>
|
||||
[\ \t] <span class="hljs-comment"># followed by a space or a tab.</span>
|
||||
///</span>
|
||||
insideComment = <span class="hljs-literal">no</span>
|
||||
<span class="hljs-keyword">for</span> line <span class="hljs-keyword">in</span> code.split(<span class="hljs-string">'\n'</span>)
|
||||
<span class="hljs-keyword">for</span> line <span class="hljs-keyword">in</span> code.split(<span class="hljs-string">'\n'</span>)
|
||||
<span class="hljs-keyword">if</span> blankLine.test(line)
|
||||
insideComment = <span class="hljs-literal">no</span>
|
||||
out.push line
|
||||
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> insideComment <span class="hljs-keyword">or</span> listItemStart.test(line)
|
||||
insideComment = <span class="hljs-literal">yes</span>
|
||||
out.push <span class="hljs-string">"# <span class="hljs-subst">#{line}</span>"</span>
|
||||
out.push <span class="hljs-string">"# <span class="hljs-subst">#{line}</span>"</span>
|
||||
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> insideComment <span class="hljs-keyword">and</span> indented.test(line)
|
||||
out.push line
|
||||
<span class="hljs-keyword">else</span>
|
||||
insideComment = <span class="hljs-literal">yes</span>
|
||||
out.push <span class="hljs-string">"# <span class="hljs-subst">#{line}</span>"</span>
|
||||
out.join <span class="hljs-string">'\n'</span></pre></div></div>
|
||||
out.push <span class="hljs-string">"# <span class="hljs-subst">#{line}</span>"</span>
|
||||
out.join <span class="hljs-string">'\n'</span></pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -367,8 +367,8 @@ be compiled “normally.”</p>
|
||||
<li id="section-14">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-14">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-14">§</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>
|
||||
@@ -383,9 +383,12 @@ If <code>last</code> is not provided, this will simply return <code>first</code>
|
||||
first_column: first.first_column
|
||||
last_line: last.last_line
|
||||
last_column: last.last_column
|
||||
<span class="hljs-function">
|
||||
<span class="hljs-title">buildLocationHash</span> = <span class="hljs-params">(loc)</span> -></span>
|
||||
<span class="hljs-string">"<span class="hljs-subst">#{loc.first_line}</span>x<span class="hljs-subst">#{loc.first_column}</span>-<span class="hljs-subst">#{loc.last_line}</span>x<span class="hljs-subst">#{loc.last_column}</span>"</span></pre></div></div>
|
||||
last_line_exclusive: last.last_line_exclusive
|
||||
last_column_exclusive: last.last_column_exclusive
|
||||
range: [
|
||||
first.range[<span class="hljs-number">0</span>]
|
||||
last.range[<span class="hljs-number">1</span>]
|
||||
]</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -393,18 +396,22 @@ If <code>last</code> is not provided, this will simply return <code>first</code>
|
||||
<li id="section-15">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-15">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-15">§</a>
|
||||
</div>
|
||||
<p>Build a dictionary of extra token properties organized by tokens’ locations
|
||||
used as lookup hashes.</p>
|
||||
<p>Build a list of all comments attached to tokens.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">buildTokenDataDictionary</span> = <span class="hljs-params">(parserState)</span> -></span>
|
||||
tokenData = {}
|
||||
<span class="hljs-keyword">for</span> token <span class="hljs-keyword">in</span> parserState.parser.tokens <span class="hljs-keyword">when</span> token.comments
|
||||
tokenHash = buildLocationHash token[<span class="hljs-number">2</span>]</pre></div></div>
|
||||
<div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.extractAllCommentTokens = <span class="hljs-function"><span class="hljs-params">(tokens)</span> -></span>
|
||||
allCommentsObj = {}
|
||||
<span class="hljs-keyword">for</span> token <span class="hljs-keyword">in</span> tokens <span class="hljs-keyword">when</span> token.comments
|
||||
<span class="hljs-keyword">for</span> comment <span class="hljs-keyword">in</span> token.comments
|
||||
commentKey = comment.locationData.range[<span class="hljs-number">0</span>]
|
||||
allCommentsObj[commentKey] = comment
|
||||
sortedKeys = <span class="hljs-built_in">Object</span>.keys(allCommentsObj).sort (a, b) -> a - b
|
||||
<span class="hljs-keyword">for</span> key <span class="hljs-keyword">in</span> sortedKeys
|
||||
allCommentsObj[key]</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -412,8 +419,46 @@ used as lookup hashes.</p>
|
||||
<li id="section-16">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-16">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-16">§</a>
|
||||
</div>
|
||||
<p>Get a lookup hash for a token based on its location data.
|
||||
Multiple tokens might have the same location hash, but using exclusive
|
||||
location data distinguishes e.g. zero-length generated tokens from
|
||||
actual source tokens.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">buildLocationHash</span> = <span class="hljs-params">(loc)</span> -></span>
|
||||
<span class="hljs-string">"<span class="hljs-subst">#{loc.range[<span class="hljs-number">0</span>]}</span>-<span class="hljs-subst">#{loc.range[<span class="hljs-number">1</span>]}</span>"</span></pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-17">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-17">§</a>
|
||||
</div>
|
||||
<p>Build a dictionary of extra token properties organized by tokens’ locations
|
||||
used as lookup hashes.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.buildTokenDataDictionary = buildTokenDataDictionary = <span class="hljs-function"><span class="hljs-params">(tokens)</span> -></span>
|
||||
tokenData = {}
|
||||
<span class="hljs-keyword">for</span> token <span class="hljs-keyword">in</span> tokens <span class="hljs-keyword">when</span> token.comments
|
||||
tokenHash = buildLocationHash token[<span class="hljs-number">2</span>]</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-18">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-18">§</a>
|
||||
</div>
|
||||
<p>Multiple tokens might have the same location hash, such as the generated
|
||||
<code>JS</code> tokens added at the start or end of the token stream to hold
|
||||
@@ -427,11 +472,11 @@ comments that start or end a file.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-17">
|
||||
<li id="section-19">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-17">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-19">§</a>
|
||||
</div>
|
||||
<p>For “overlapping” tokens, that is tokens with the same location data
|
||||
and therefore matching <code>tokenHash</code>es, merge the comments from both/all
|
||||
@@ -446,11 +491,11 @@ they will get sorted out later.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-18">
|
||||
<li id="section-20">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-18">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-20">§</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.
|
||||
@@ -458,74 +503,27 @@ The object is returned either way.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre>exports.addDataToNode = <span class="hljs-function"><span class="hljs-params">(parserState, first, last)</span> -></span>
|
||||
<div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.addDataToNode = <span class="hljs-function"><span class="hljs-params">(parserState, firstLocationData, firstValue, lastLocationData, lastValue, forceUpdateLocation = <span class="hljs-literal">yes</span>)</span> -></span>
|
||||
(obj) -></pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-19">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-19">¶</a>
|
||||
</div>
|
||||
<p>Add location data.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> obj?.updateLocationDataIfMissing? <span class="hljs-keyword">and</span> first?
|
||||
obj.updateLocationDataIfMissing buildLocationData(first, last)</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-20">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-20">¶</a>
|
||||
</div>
|
||||
<p>Add comments, building the dictionary of token data if it hasn’t been
|
||||
built yet.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> parserState.tokenData ?= buildTokenDataDictionary parserState
|
||||
<span class="hljs-keyword">if</span> obj.locationData?
|
||||
objHash = buildLocationHash obj.locationData
|
||||
<span class="hljs-keyword">if</span> parserState.tokenData[objHash]?.comments?
|
||||
attachCommentsToNode parserState.tokenData[objHash].comments, obj
|
||||
obj
|
||||
|
||||
exports.attachCommentsToNode = attachCommentsToNode = <span class="hljs-function"><span class="hljs-params">(comments, node)</span> -></span>
|
||||
<span class="hljs-keyword">return</span> <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> comments? <span class="hljs-keyword">or</span> comments.length <span class="hljs-keyword">is</span> <span class="hljs-number">0</span>
|
||||
node.comments ?= []
|
||||
node.comments.push comments...</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-21">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-21">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-21">§</a>
|
||||
</div>
|
||||
<p>Convert jison location data to a string.
|
||||
<code>obj</code> can be a token, or a locationData.</p>
|
||||
<p>Add location data.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre>exports.locationDataToString = <span class="hljs-function"><span class="hljs-params">(obj)</span> -></span>
|
||||
<span class="hljs-keyword">if</span> (<span class="hljs-string">"2"</span> <span class="hljs-keyword">of</span> obj) <span class="hljs-keyword">and</span> (<span class="hljs-string">"first_line"</span> <span class="hljs-keyword">of</span> obj[<span class="hljs-number">2</span>]) <span class="hljs-keyword">then</span> locationData = obj[<span class="hljs-number">2</span>]
|
||||
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> <span class="hljs-string">"first_line"</span> <span class="hljs-keyword">of</span> obj <span class="hljs-keyword">then</span> locationData = obj
|
||||
|
||||
<span class="hljs-keyword">if</span> locationData
|
||||
<span class="hljs-string">"<span class="hljs-subst">#{locationData.first_line + <span class="hljs-number">1</span>}</span>:<span class="hljs-subst">#{locationData.first_column + <span class="hljs-number">1</span>}</span>-"</span> +
|
||||
<span class="hljs-string">"<span class="hljs-subst">#{locationData.last_line + <span class="hljs-number">1</span>}</span>:<span class="hljs-subst">#{locationData.last_column + <span class="hljs-number">1</span>}</span>"</span>
|
||||
<span class="hljs-keyword">else</span>
|
||||
<span class="hljs-string">"No location data"</span></pre></div></div>
|
||||
<div class="content"><div class='highlight'><pre> locationData = buildLocationData(firstValue?.locationData ? firstLocationData, lastValue?.locationData ? lastLocationData)
|
||||
<span class="hljs-keyword">if</span> obj?.updateLocationDataIfMissing? <span class="hljs-keyword">and</span> firstLocationData?
|
||||
obj.updateLocationDataIfMissing locationData, forceUpdateLocation
|
||||
<span class="hljs-keyword">else</span>
|
||||
obj.locationData = locationData</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -533,22 +531,25 @@ exports.attachCommentsToNode = attachCommentsToNode = <span class="hljs-function
|
||||
<li id="section-22">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-22">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-22">§</a>
|
||||
</div>
|
||||
<p>A <code>.coffee.md</code> compatible version of <code>basename</code>, that returns the file sans-extension.</p>
|
||||
<p>Add comments, building the dictionary of token data if it hasn’t been
|
||||
built yet.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre>exports.baseFileName = <span class="hljs-function"><span class="hljs-params">(file, stripExt = <span class="hljs-literal">no</span>, useWinPathSep = <span class="hljs-literal">no</span>)</span> -></span>
|
||||
pathSep = <span class="hljs-keyword">if</span> useWinPathSep <span class="hljs-keyword">then</span> <span class="hljs-regexp">/\\|\//</span> <span class="hljs-keyword">else</span> <span class="hljs-regexp">/\//</span>
|
||||
parts = file.split(pathSep)
|
||||
file = parts[parts.length - <span class="hljs-number">1</span>]
|
||||
<span class="hljs-keyword">return</span> file <span class="hljs-keyword">unless</span> stripExt <span class="hljs-keyword">and</span> file.indexOf(<span class="hljs-string">'.'</span>) >= <span class="hljs-number">0</span>
|
||||
parts = file.split(<span class="hljs-string">'.'</span>)
|
||||
parts.pop()
|
||||
parts.pop() <span class="hljs-keyword">if</span> parts[parts.length - <span class="hljs-number">1</span>] <span class="hljs-keyword">is</span> <span class="hljs-string">'coffee'</span> <span class="hljs-keyword">and</span> parts.length > <span class="hljs-number">1</span>
|
||||
parts.join(<span class="hljs-string">'.'</span>)</pre></div></div>
|
||||
<div class="content"><div class='highlight'><pre> parserState.tokenData ?= buildTokenDataDictionary parserState.parser.tokens
|
||||
<span class="hljs-keyword">if</span> obj.locationData?
|
||||
objHash = buildLocationHash obj.locationData
|
||||
<span class="hljs-keyword">if</span> parserState.tokenData[objHash]?.comments?
|
||||
attachCommentsToNode parserState.tokenData[objHash].comments, obj
|
||||
obj
|
||||
|
||||
<span class="hljs-built_in">exports</span>.attachCommentsToNode = attachCommentsToNode = <span class="hljs-function"><span class="hljs-params">(comments, node)</span> -></span>
|
||||
<span class="hljs-keyword">return</span> <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> comments? <span class="hljs-keyword">or</span> comments.length <span class="hljs-keyword">is</span> <span class="hljs-number">0</span>
|
||||
node.comments ?= []
|
||||
node.comments.push comments...</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -556,14 +557,23 @@ exports.attachCommentsToNode = attachCommentsToNode = <span class="hljs-function
|
||||
<li id="section-23">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-23">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-23">§</a>
|
||||
</div>
|
||||
<p>Determine if a filename represents a CoffeeScript file.</p>
|
||||
<p>Convert jison location data to a string.
|
||||
<code>obj</code> can be a token, or a locationData.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre>exports.isCoffee = <span class="hljs-function"><span class="hljs-params">(file)</span> -></span> <span class="hljs-regexp">/\.((lit)?coffee|coffee\.md)$/</span>.test file</pre></div></div>
|
||||
<div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.locationDataToString = <span class="hljs-function"><span class="hljs-params">(obj)</span> -></span>
|
||||
<span class="hljs-keyword">if</span> (<span class="hljs-string">"2"</span> <span class="hljs-keyword">of</span> obj) <span class="hljs-keyword">and</span> (<span class="hljs-string">"first_line"</span> <span class="hljs-keyword">of</span> obj[<span class="hljs-number">2</span>]) <span class="hljs-keyword">then</span> locationData = obj[<span class="hljs-number">2</span>]
|
||||
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> <span class="hljs-string">"first_line"</span> <span class="hljs-keyword">of</span> obj <span class="hljs-keyword">then</span> locationData = obj
|
||||
|
||||
<span class="hljs-keyword">if</span> locationData
|
||||
<span class="hljs-string">"<span class="hljs-subst">#{locationData.first_line + <span class="hljs-number">1</span>}</span>:<span class="hljs-subst">#{locationData.first_column + <span class="hljs-number">1</span>}</span>-"</span> +
|
||||
<span class="hljs-string">"<span class="hljs-subst">#{locationData.last_line + <span class="hljs-number">1</span>}</span>:<span class="hljs-subst">#{locationData.last_column + <span class="hljs-number">1</span>}</span>"</span>
|
||||
<span class="hljs-keyword">else</span>
|
||||
<span class="hljs-string">"No location data"</span></pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -571,14 +581,18 @@ exports.attachCommentsToNode = attachCommentsToNode = <span class="hljs-function
|
||||
<li id="section-24">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-24">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-24">§</a>
|
||||
</div>
|
||||
<p>Determine if a filename represents a Literate CoffeeScript file.</p>
|
||||
<p>Generate a unique anonymous file name so we can distinguish source map cache
|
||||
entries for any number of anonymous scripts.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre>exports.isLiterate = <span class="hljs-function"><span class="hljs-params">(file)</span> -></span> <span class="hljs-regexp">/\.(litcoffee|coffee\.md)$/</span>.test file</pre></div></div>
|
||||
<div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.anonymousFileName = <span class="hljs-keyword">do</span> ->
|
||||
n = <span class="hljs-number">0</span>
|
||||
->
|
||||
<span class="hljs-string">"<anonymous-<span class="hljs-subst">#{n++}</span>>"</span></pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -586,8 +600,61 @@ exports.attachCommentsToNode = attachCommentsToNode = <span class="hljs-function
|
||||
<li id="section-25">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-25">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-25">§</a>
|
||||
</div>
|
||||
<p>A <code>.coffee.md</code> compatible version of <code>basename</code>, that returns the file sans-extension.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.baseFileName = <span class="hljs-function"><span class="hljs-params">(file, stripExt = <span class="hljs-literal">no</span>, useWinPathSep = <span class="hljs-literal">no</span>)</span> -></span>
|
||||
pathSep = <span class="hljs-keyword">if</span> useWinPathSep <span class="hljs-keyword">then</span> <span class="hljs-regexp">/\\|\//</span> <span class="hljs-keyword">else</span> <span class="hljs-regexp">/\//</span>
|
||||
parts = file.split(pathSep)
|
||||
file = parts[parts.length - <span class="hljs-number">1</span>]
|
||||
<span class="hljs-keyword">return</span> file <span class="hljs-keyword">unless</span> stripExt <span class="hljs-keyword">and</span> file.indexOf(<span class="hljs-string">'.'</span>) >= <span class="hljs-number">0</span>
|
||||
parts = file.split(<span class="hljs-string">'.'</span>)
|
||||
parts.pop()
|
||||
parts.pop() <span class="hljs-keyword">if</span> parts[parts.length - <span class="hljs-number">1</span>] <span class="hljs-keyword">is</span> <span class="hljs-string">'coffee'</span> <span class="hljs-keyword">and</span> parts.length > <span class="hljs-number">1</span>
|
||||
parts.join(<span class="hljs-string">'.'</span>)</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-26">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-26">§</a>
|
||||
</div>
|
||||
<p>Determine if a filename represents a CoffeeScript file.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.isCoffee = <span class="hljs-function"><span class="hljs-params">(file)</span> -></span> <span class="hljs-regexp">/\.((lit)?coffee|coffee\.md)$/</span>.test file</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-27">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-27">§</a>
|
||||
</div>
|
||||
<p>Determine if a filename represents a Literate CoffeeScript file.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.isLiterate = <span class="hljs-function"><span class="hljs-params">(file)</span> -></span> <span class="hljs-regexp">/\.(litcoffee|coffee\.md)$/</span>.test file</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-28">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-28">§</a>
|
||||
</div>
|
||||
<p>Throws a SyntaxError from a given location.
|
||||
The error’s <code>toString</code> will return an error message following the “standard”
|
||||
@@ -596,19 +663,19 @@ marker showing where the error is.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre>exports.throwSyntaxError = <span class="hljs-function"><span class="hljs-params">(message, location)</span> -></span>
|
||||
error = <span class="hljs-keyword">new</span> SyntaxError message
|
||||
<div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.throwSyntaxError = <span class="hljs-function"><span class="hljs-params">(message, location)</span> -></span>
|
||||
error = <span class="hljs-keyword">new</span> <span class="hljs-built_in">SyntaxError</span> message
|
||||
error.location = location
|
||||
error.toString = syntaxErrorToString</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-26">
|
||||
<li id="section-29">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-26">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-29">§</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
|
||||
@@ -623,27 +690,27 @@ compile CoffeeScript for example).</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-27">
|
||||
<li id="section-30">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-27">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-30">§</a>
|
||||
</div>
|
||||
<p>Update a compiler SyntaxError with source code information if it didn’t have
|
||||
it already.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre>exports.updateSyntaxError = <span class="hljs-function"><span class="hljs-params">(error, code, filename)</span> -></span></pre></div></div>
|
||||
<div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.updateSyntaxError = <span class="hljs-function"><span class="hljs-params">(error, code, filename)</span> -></span></pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-28">
|
||||
<li id="section-31">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-28">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-31">§</a>
|
||||
</div>
|
||||
<p>Avoid screwing up the <code>stack</code> property of other errors (i.e. possible bugs).</p>
|
||||
|
||||
@@ -662,34 +729,38 @@ it already.</p>
|
||||
last_line ?= first_line
|
||||
last_column ?= first_column
|
||||
|
||||
filename = @filename <span class="hljs-keyword">or</span> <span class="hljs-string">'[stdin]'</span>
|
||||
codeLine = @code.split(<span class="hljs-string">'\n'</span>)[first_line]
|
||||
<span class="hljs-keyword">if</span> @filename?.startsWith <span class="hljs-string">'<anonymous'</span>
|
||||
filename = <span class="hljs-string">'[stdin]'</span>
|
||||
<span class="hljs-keyword">else</span>
|
||||
filename = @filename <span class="hljs-keyword">or</span> <span class="hljs-string">'[stdin]'</span>
|
||||
|
||||
codeLine = @code.split(<span class="hljs-string">'\n'</span>)[first_line]
|
||||
start = first_column</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-29">
|
||||
<li id="section-32">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-29">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-32">§</a>
|
||||
</div>
|
||||
<p>Show only the first line on multi-line errors.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> end = <span class="hljs-keyword">if</span> first_line <span class="hljs-keyword">is</span> last_line <span class="hljs-keyword">then</span> last_column + <span class="hljs-number">1</span> <span class="hljs-keyword">else</span> codeLine.length
|
||||
marker = codeLine[...start].replace(<span class="hljs-regexp">/[^\s]/g</span>, <span class="hljs-string">' '</span>) + repeat(<span class="hljs-string">'^'</span>, end - start)</pre></div></div>
|
||||
marker = codeLine[...start].replace(<span class="hljs-regexp">/[^\s]/g</span>, <span class="hljs-string">' '</span>) + repeat(<span class="hljs-string">'^'</span>, end - start)</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-30">
|
||||
<li id="section-33">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-30">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-33">§</a>
|
||||
</div>
|
||||
<p>Check to see if we’re running on a color-enabled TTY.</p>
|
||||
|
||||
@@ -699,23 +770,99 @@ it already.</p>
|
||||
colorsEnabled = process.stdout?.isTTY <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> process.env?.NODE_DISABLE_COLORS
|
||||
|
||||
<span class="hljs-keyword">if</span> @colorful ? colorsEnabled
|
||||
<span class="hljs-function"> <span class="hljs-title">colorize</span> = <span class="hljs-params">(str)</span> -></span> <span class="hljs-string">"\x1B[1;31m<span class="hljs-subst">#{str}</span>\x1B[0m"</span>
|
||||
<span class="hljs-function"> <span class="hljs-title">colorize</span> = <span class="hljs-params">(str)</span> -></span> <span class="hljs-string">"\x1B[1;31m<span class="hljs-subst">#{str}</span>\x1B[0m"</span>
|
||||
codeLine = codeLine[...start] + colorize(codeLine[start...end]) + codeLine[end..]
|
||||
marker = colorize marker
|
||||
|
||||
<span class="hljs-string">"""
|
||||
<span class="hljs-string">"""
|
||||
<span class="hljs-subst">#{filename}</span>:<span class="hljs-subst">#{first_line + <span class="hljs-number">1</span>}</span>:<span class="hljs-subst">#{first_column + <span class="hljs-number">1</span>}</span>: error: <span class="hljs-subst">#{@message}</span>
|
||||
<span class="hljs-subst">#{codeLine}</span>
|
||||
<span class="hljs-subst">#{marker}</span>
|
||||
"""</span>
|
||||
"""</span>
|
||||
|
||||
exports.nameWhitespaceCharacter = <span class="hljs-function"><span class="hljs-params">(string)</span> -></span>
|
||||
<span class="hljs-built_in">exports</span>.nameWhitespaceCharacter = <span class="hljs-function"><span class="hljs-params">(string)</span> -></span>
|
||||
<span class="hljs-keyword">switch</span> string
|
||||
<span class="hljs-keyword">when</span> <span class="hljs-string">' '</span> <span class="hljs-keyword">then</span> <span class="hljs-string">'space'</span>
|
||||
<span class="hljs-keyword">when</span> <span class="hljs-string">'\n'</span> <span class="hljs-keyword">then</span> <span class="hljs-string">'newline'</span>
|
||||
<span class="hljs-keyword">when</span> <span class="hljs-string">'\r'</span> <span class="hljs-keyword">then</span> <span class="hljs-string">'carriage return'</span>
|
||||
<span class="hljs-keyword">when</span> <span class="hljs-string">'\t'</span> <span class="hljs-keyword">then</span> <span class="hljs-string">'tab'</span>
|
||||
<span class="hljs-keyword">else</span> string</pre></div></div>
|
||||
<span class="hljs-keyword">when</span> <span class="hljs-string">' '</span> <span class="hljs-keyword">then</span> <span class="hljs-string">'space'</span>
|
||||
<span class="hljs-keyword">when</span> <span class="hljs-string">'\n'</span> <span class="hljs-keyword">then</span> <span class="hljs-string">'newline'</span>
|
||||
<span class="hljs-keyword">when</span> <span class="hljs-string">'\r'</span> <span class="hljs-keyword">then</span> <span class="hljs-string">'carriage return'</span>
|
||||
<span class="hljs-keyword">when</span> <span class="hljs-string">'\t'</span> <span class="hljs-keyword">then</span> <span class="hljs-string">'tab'</span>
|
||||
<span class="hljs-keyword">else</span> string
|
||||
|
||||
<span class="hljs-built_in">exports</span>.parseNumber = <span class="hljs-function"><span class="hljs-params">(string)</span> -></span>
|
||||
<span class="hljs-keyword">return</span> <span class="hljs-literal">NaN</span> <span class="hljs-keyword">unless</span> string?
|
||||
|
||||
base = <span class="hljs-keyword">switch</span> string.charAt <span class="hljs-number">1</span>
|
||||
<span class="hljs-keyword">when</span> <span class="hljs-string">'b'</span> <span class="hljs-keyword">then</span> <span class="hljs-number">2</span>
|
||||
<span class="hljs-keyword">when</span> <span class="hljs-string">'o'</span> <span class="hljs-keyword">then</span> <span class="hljs-number">8</span>
|
||||
<span class="hljs-keyword">when</span> <span class="hljs-string">'x'</span> <span class="hljs-keyword">then</span> <span class="hljs-number">16</span>
|
||||
<span class="hljs-keyword">else</span> <span class="hljs-literal">null</span>
|
||||
|
||||
<span class="hljs-keyword">if</span> base?
|
||||
<span class="hljs-built_in">parseInt</span> string[<span class="hljs-number">2.</span>.].replace(<span class="hljs-regexp">/_/g</span>, <span class="hljs-string">''</span>), base
|
||||
<span class="hljs-keyword">else</span>
|
||||
<span class="hljs-built_in">parseFloat</span> string.replace(<span class="hljs-regexp">/_/g</span>, <span class="hljs-string">''</span>)
|
||||
|
||||
<span class="hljs-built_in">exports</span>.isFunction = <span class="hljs-function"><span class="hljs-params">(obj)</span> -></span> Object::toString.call(obj) <span class="hljs-keyword">is</span> <span class="hljs-string">'[object Function]'</span>
|
||||
<span class="hljs-built_in">exports</span>.isNumber = isNumber = <span class="hljs-function"><span class="hljs-params">(obj)</span> -></span> Object::toString.call(obj) <span class="hljs-keyword">is</span> <span class="hljs-string">'[object Number]'</span>
|
||||
<span class="hljs-built_in">exports</span>.isString = isString = <span class="hljs-function"><span class="hljs-params">(obj)</span> -></span> Object::toString.call(obj) <span class="hljs-keyword">is</span> <span class="hljs-string">'[object String]'</span>
|
||||
<span class="hljs-built_in">exports</span>.isBoolean = isBoolean = <span class="hljs-function"><span class="hljs-params">(obj)</span> -></span> obj <span class="hljs-keyword">is</span> <span class="hljs-literal">yes</span> <span class="hljs-keyword">or</span> obj <span class="hljs-keyword">is</span> <span class="hljs-literal">no</span> <span class="hljs-keyword">or</span> Object::toString.call(obj) <span class="hljs-keyword">is</span> <span class="hljs-string">'[object Boolean]'</span>
|
||||
<span class="hljs-built_in">exports</span>.isPlainObject = <span class="hljs-function"><span class="hljs-params">(obj)</span> -></span> <span class="hljs-keyword">typeof</span> obj <span class="hljs-keyword">is</span> <span class="hljs-string">'object'</span> <span class="hljs-keyword">and</span> !!obj <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> <span class="hljs-built_in">Array</span>.isArray(obj) <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> isNumber(obj) <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> isString(obj) <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> isBoolean(obj)
|
||||
<span class="hljs-function">
|
||||
<span class="hljs-title">unicodeCodePointToUnicodeEscapes</span> = <span class="hljs-params">(codePoint)</span> -></span>
|
||||
<span class="hljs-function"> <span class="hljs-title">toUnicodeEscape</span> = <span class="hljs-params">(val)</span> -></span>
|
||||
str = val.toString <span class="hljs-number">16</span>
|
||||
<span class="hljs-string">"\\u<span class="hljs-subst">#{repeat <span class="hljs-string">'0'</span>, <span class="hljs-number">4</span> - str.length}</span><span class="hljs-subst">#{str}</span>"</span>
|
||||
<span class="hljs-keyword">return</span> toUnicodeEscape(codePoint) <span class="hljs-keyword">if</span> codePoint < <span class="hljs-number">0x10000</span></pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-34">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-34">§</a>
|
||||
</div>
|
||||
<p>surrogate pair</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> high = <span class="hljs-built_in">Math</span>.floor((codePoint - <span class="hljs-number">0x10000</span>) / <span class="hljs-number">0x400</span>) + <span class="hljs-number">0xD800</span>
|
||||
low = (codePoint - <span class="hljs-number">0x10000</span>) % <span class="hljs-number">0x400</span> + <span class="hljs-number">0xDC00</span>
|
||||
<span class="hljs-string">"<span class="hljs-subst">#{toUnicodeEscape(high)}</span><span class="hljs-subst">#{toUnicodeEscape(low)}</span>"</span></pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-35">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-35">§</a>
|
||||
</div>
|
||||
<p>Replace <code>\u{...}</code> with <code>\uxxxx[\uxxxx]</code> in regexes without <code>u</code> flag</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.replaceUnicodeCodePointEscapes = <span class="hljs-function"><span class="hljs-params">(str, {flags, error, delimiter = <span class="hljs-string">''</span>} = {})</span> -></span>
|
||||
shouldReplace = flags? <span class="hljs-keyword">and</span> <span class="hljs-string">'u'</span> <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> flags
|
||||
str.replace UNICODE_CODE_POINT_ESCAPE, <span class="hljs-function"><span class="hljs-params">(match, escapedBackslash, codePointHex, offset)</span> -></span>
|
||||
<span class="hljs-keyword">return</span> escapedBackslash <span class="hljs-keyword">if</span> escapedBackslash
|
||||
|
||||
codePointDecimal = <span class="hljs-built_in">parseInt</span> codePointHex, <span class="hljs-number">16</span>
|
||||
<span class="hljs-keyword">if</span> codePointDecimal > <span class="hljs-number">0x10ffff</span>
|
||||
error <span class="hljs-string">"unicode code point escapes greater than \\u{10ffff} are not allowed"</span>,
|
||||
offset: offset + delimiter.length
|
||||
length: codePointHex.length + <span class="hljs-number">4</span>
|
||||
<span class="hljs-keyword">return</span> match <span class="hljs-keyword">unless</span> shouldReplace
|
||||
|
||||
unicodeCodePointToUnicodeEscapes codePointDecimal
|
||||
|
||||
UNICODE_CODE_POINT_ESCAPE = <span class="hljs-regexp">///
|
||||
( \\\\ ) <span class="hljs-comment"># Make sure the escape isn’t escaped.</span>
|
||||
|
|
||||
\\u\{ ( [\da-fA-F]+ ) \}
|
||||
///</span>g</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
@@ -112,26 +112,26 @@
|
||||
<li id="section-1">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-1">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-1">§</a>
|
||||
</div>
|
||||
<p>Node.js Implementation</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre>CoffeeScript = <span class="hljs-built_in">require</span> <span class="hljs-string">'./coffeescript'</span>
|
||||
fs = <span class="hljs-built_in">require</span> <span class="hljs-string">'fs'</span>
|
||||
vm = <span class="hljs-built_in">require</span> <span class="hljs-string">'vm'</span>
|
||||
path = <span class="hljs-built_in">require</span> <span class="hljs-string">'path'</span>
|
||||
<div class="content"><div class='highlight'><pre>CoffeeScript = <span class="hljs-built_in">require</span> <span class="hljs-string">'./coffeescript'</span>
|
||||
fs = <span class="hljs-built_in">require</span> <span class="hljs-string">'fs'</span>
|
||||
vm = <span class="hljs-built_in">require</span> <span class="hljs-string">'vm'</span>
|
||||
path = <span class="hljs-built_in">require</span> <span class="hljs-string">'path'</span>
|
||||
|
||||
helpers = CoffeeScript.helpers
|
||||
|
||||
CoffeeScript.transpile = <span class="hljs-function"><span class="hljs-params">(js, options)</span> -></span>
|
||||
<span class="hljs-keyword">try</span>
|
||||
babel = <span class="hljs-built_in">require</span> <span class="hljs-string">'@babel/core'</span>
|
||||
babel = <span class="hljs-built_in">require</span> <span class="hljs-string">'@babel/core'</span>
|
||||
<span class="hljs-keyword">catch</span>
|
||||
<span class="hljs-keyword">try</span>
|
||||
babel = <span class="hljs-built_in">require</span> <span class="hljs-string">'babel-core'</span>
|
||||
babel = <span class="hljs-built_in">require</span> <span class="hljs-string">'babel-core'</span>
|
||||
<span class="hljs-keyword">catch</span></pre></div></div>
|
||||
|
||||
</li>
|
||||
@@ -140,15 +140,15 @@ CoffeeScript.transpile = <span class="hljs-function"><span class="hljs-params">(
|
||||
<li id="section-2">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-2">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-2">§</a>
|
||||
</div>
|
||||
<p>This error is only for Node, as CLI users will see a different error
|
||||
earlier if they don’t have Babel installed.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> Error <span class="hljs-string">'To use the transpile option, you must have the \'@babel/core\' module installed'</span>
|
||||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span> <span class="hljs-string">'To use the transpile option, you must have the \'@babel/core\' module installed'</span>
|
||||
babel.transform js, options</pre></div></div>
|
||||
|
||||
</li>
|
||||
@@ -157,8 +157,8 @@ earlier if they don’t have Babel installed.</p>
|
||||
<li id="section-3">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-3">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-3">§</a>
|
||||
</div>
|
||||
<p>The <code>compile</code> method shared by the CLI, Node and browser APIs.</p>
|
||||
|
||||
@@ -172,8 +172,8 @@ earlier if they don’t have Babel installed.</p>
|
||||
<li id="section-4">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-4">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-4">§</a>
|
||||
</div>
|
||||
<p>The <code>compile</code> method particular to the Node API.</p>
|
||||
|
||||
@@ -187,8 +187,8 @@ earlier if they don’t have Babel installed.</p>
|
||||
<li id="section-5">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-5">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-5">§</a>
|
||||
</div>
|
||||
<p>Pass a reference to Babel into the compiler, so that the transpile option
|
||||
is available in the Node API. We need to do this so that tools like Webpack
|
||||
@@ -207,8 +207,8 @@ require Babel.</p>
|
||||
<li id="section-6">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-6">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-6">§</a>
|
||||
</div>
|
||||
<p>Compile and execute a string of CoffeeScript (on the server), correctly
|
||||
setting <code>__filename</code>, <code>__dirname</code>, and relative <code>require()</code>.</p>
|
||||
@@ -224,15 +224,15 @@ setting <code>__filename</code>, <code>__dirname</code>, and relative <code>requ
|
||||
<li id="section-7">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-7">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-7">§</a>
|
||||
</div>
|
||||
<p>Set the filename.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> mainModule.filename = process.argv[<span class="hljs-number">1</span>] =
|
||||
<span class="hljs-keyword">if</span> options.filename <span class="hljs-keyword">then</span> fs.realpathSync(options.filename) <span class="hljs-keyword">else</span> <span class="hljs-string">'<anonymous>'</span></pre></div></div>
|
||||
<span class="hljs-keyword">if</span> options.filename <span class="hljs-keyword">then</span> fs.realpathSync(options.filename) <span class="hljs-keyword">else</span> helpers.anonymousFileName()</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -240,8 +240,8 @@ setting <code>__filename</code>, <code>__dirname</code>, and relative <code>requ
|
||||
<li id="section-8">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-8">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-8">§</a>
|
||||
</div>
|
||||
<p>Clear the module cache.</p>
|
||||
|
||||
@@ -255,8 +255,8 @@ setting <code>__filename</code>, <code>__dirname</code>, and relative <code>requ
|
||||
<li id="section-9">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-9">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-9">§</a>
|
||||
</div>
|
||||
<p>Assign paths for node_modules loading</p>
|
||||
|
||||
@@ -265,8 +265,8 @@ setting <code>__filename</code>, <code>__dirname</code>, and relative <code>requ
|
||||
<div class="content"><div class='highlight'><pre> dir = <span class="hljs-keyword">if</span> options.filename?
|
||||
path.dirname fs.realpathSync options.filename
|
||||
<span class="hljs-keyword">else</span>
|
||||
fs.realpathSync <span class="hljs-string">'.'</span>
|
||||
mainModule.paths = <span class="hljs-built_in">require</span>(<span class="hljs-string">'module'</span>)._nodeModulePaths dir</pre></div></div>
|
||||
fs.realpathSync <span class="hljs-string">'.'</span>
|
||||
mainModule.paths = <span class="hljs-built_in">require</span>(<span class="hljs-string">'module'</span>)._nodeModulePaths dir</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -274,14 +274,17 @@ setting <code>__filename</code>, <code>__dirname</code>, and relative <code>requ
|
||||
<li id="section-10">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-10">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-10">§</a>
|
||||
</div>
|
||||
<p>Save the options for compiling child imports.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> mainModule.options = options</pre></div></div>
|
||||
<div class="content"><div class='highlight'><pre> mainModule.options = options
|
||||
|
||||
options.filename = mainModule.filename
|
||||
options.inlineMap = <span class="hljs-literal">true</span></pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -289,16 +292,15 @@ setting <code>__filename</code>, <code>__dirname</code>, and relative <code>requ
|
||||
<li id="section-11">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-11">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-11">§</a>
|
||||
</div>
|
||||
<p>Compile.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> helpers.isCoffee(mainModule.filename) <span class="hljs-keyword">or</span> <span class="hljs-built_in">require</span>.extensions
|
||||
answer = CoffeeScript.compile code, options
|
||||
code = answer.js ? answer
|
||||
<div class="content"><div class='highlight'><pre> answer = CoffeeScript.compile code, options
|
||||
code = answer.js ? answer
|
||||
|
||||
mainModule._compile code, mainModule.filename</pre></div></div>
|
||||
|
||||
@@ -308,15 +310,15 @@ setting <code>__filename</code>, <code>__dirname</code>, and relative <code>requ
|
||||
<li id="section-12">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-12">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-12">§</a>
|
||||
</div>
|
||||
<p>Compile and evaluate a string of CoffeeScript (in a Node.js-like environment).
|
||||
The CoffeeScript REPL uses this to run the input.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre>CoffeeScript.eval = <span class="hljs-function"><span class="hljs-params">(code, options = {})</span> -></span>
|
||||
<div class="content"><div class='highlight'><pre>CoffeeScript.<span class="hljs-built_in">eval</span> = <span class="hljs-function"><span class="hljs-params">(code, options = {})</span> -></span>
|
||||
<span class="hljs-keyword">return</span> <span class="hljs-keyword">unless</span> code = code.trim()
|
||||
createContext = vm.Script.createContext ? vm.createContext
|
||||
|
||||
@@ -330,10 +332,10 @@ The CoffeeScript REPL uses this to run the input.</p>
|
||||
<span class="hljs-keyword">else</span>
|
||||
sandbox = createContext()
|
||||
sandbox[k] = v <span class="hljs-keyword">for</span> own k, v <span class="hljs-keyword">of</span> options.sandbox
|
||||
sandbox.<span class="hljs-built_in">global</span> = sandbox.root = sandbox.GLOBAL = sandbox
|
||||
sandbox.global = sandbox.root = sandbox.GLOBAL = sandbox
|
||||
<span class="hljs-keyword">else</span>
|
||||
sandbox = <span class="hljs-built_in">global</span>
|
||||
sandbox.__filename = options.filename || <span class="hljs-string">'eval'</span>
|
||||
sandbox = global
|
||||
sandbox.__filename = options.filename || <span class="hljs-string">'eval'</span>
|
||||
sandbox.__dirname = path.dirname sandbox.__filename</pre></div></div>
|
||||
|
||||
</li>
|
||||
@@ -342,19 +344,19 @@ The CoffeeScript REPL uses this to run the input.</p>
|
||||
<li id="section-13">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-13">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-13">§</a>
|
||||
</div>
|
||||
<p>define module/require only if they chose not to specify their own</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">unless</span> sandbox <span class="hljs-keyword">isnt</span> <span class="hljs-built_in">global</span> <span class="hljs-keyword">or</span> sandbox.<span class="hljs-built_in">module</span> <span class="hljs-keyword">or</span> sandbox.<span class="hljs-built_in">require</span>
|
||||
Module = <span class="hljs-built_in">require</span> <span class="hljs-string">'module'</span>
|
||||
sandbox.<span class="hljs-built_in">module</span> = _module = <span class="hljs-keyword">new</span> Module(options.modulename || <span class="hljs-string">'eval'</span>)
|
||||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">unless</span> sandbox <span class="hljs-keyword">isnt</span> global <span class="hljs-keyword">or</span> sandbox.module <span class="hljs-keyword">or</span> sandbox.<span class="hljs-built_in">require</span>
|
||||
Module = <span class="hljs-built_in">require</span> <span class="hljs-string">'module'</span>
|
||||
sandbox.module = _module = <span class="hljs-keyword">new</span> Module(options.modulename || <span class="hljs-string">'eval'</span>)
|
||||
sandbox.<span class="hljs-built_in">require</span> = _require = <span class="hljs-function"><span class="hljs-params">(path)</span> -></span> Module._load path, _module, <span class="hljs-literal">true</span>
|
||||
_module.filename = sandbox.__filename
|
||||
<span class="hljs-keyword">for</span> r <span class="hljs-keyword">in</span> Object.getOwnPropertyNames <span class="hljs-built_in">require</span> <span class="hljs-keyword">when</span> r <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> [<span class="hljs-string">'paths'</span>, <span class="hljs-string">'arguments'</span>, <span class="hljs-string">'caller'</span>]
|
||||
<span class="hljs-keyword">for</span> r <span class="hljs-keyword">in</span> <span class="hljs-built_in">Object</span>.getOwnPropertyNames <span class="hljs-built_in">require</span> <span class="hljs-keyword">when</span> r <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> [<span class="hljs-string">'paths'</span>, <span class="hljs-string">'arguments'</span>, <span class="hljs-string">'caller'</span>]
|
||||
_require[r] = <span class="hljs-built_in">require</span>[r]</pre></div></div>
|
||||
|
||||
</li>
|
||||
@@ -363,8 +365,8 @@ The CoffeeScript REPL uses this to run the input.</p>
|
||||
<li id="section-14">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-14">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-14">§</a>
|
||||
</div>
|
||||
<p>use the same hack node currently uses for their own REPL</p>
|
||||
|
||||
@@ -376,12 +378,12 @@ The CoffeeScript REPL uses this to run the input.</p>
|
||||
o[k] = v <span class="hljs-keyword">for</span> own k, v <span class="hljs-keyword">of</span> options
|
||||
o.bare = <span class="hljs-literal">on</span> <span class="hljs-comment"># ensure return value</span>
|
||||
js = CoffeeScript.compile code, o
|
||||
<span class="hljs-keyword">if</span> sandbox <span class="hljs-keyword">is</span> <span class="hljs-built_in">global</span>
|
||||
<span class="hljs-keyword">if</span> sandbox <span class="hljs-keyword">is</span> global
|
||||
vm.runInThisContext js
|
||||
<span class="hljs-keyword">else</span>
|
||||
vm.runInContext js, sandbox
|
||||
|
||||
CoffeeScript.register = <span class="hljs-function">-></span> <span class="hljs-built_in">require</span> <span class="hljs-string">'./register'</span></pre></div></div>
|
||||
CoffeeScript.register = <span class="hljs-function">-></span> <span class="hljs-built_in">require</span> <span class="hljs-string">'./register'</span></pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -389,8 +391,8 @@ CoffeeScript.register = <span class="hljs-function">-></span> <span class="hl
|
||||
<li id="section-15">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-15">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-15">§</a>
|
||||
</div>
|
||||
<p>Throw error with deprecation warning when depending upon implicit <code>require.extensions</code> registration</p>
|
||||
|
||||
@@ -399,12 +401,11 @@ CoffeeScript.register = <span class="hljs-function">-></span> <span class="hl
|
||||
<div class="content"><div class='highlight'><pre><span class="hljs-keyword">if</span> <span class="hljs-built_in">require</span>.extensions
|
||||
<span class="hljs-keyword">for</span> ext <span class="hljs-keyword">in</span> CoffeeScript.FILE_EXTENSIONS <span class="hljs-keyword">then</span> <span class="hljs-keyword">do</span> (ext) ->
|
||||
<span class="hljs-built_in">require</span>.extensions[ext] ?= <span class="hljs-function">-></span>
|
||||
<span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> Error <span class="hljs-string">"""
|
||||
<span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span> <span class="hljs-string">"""
|
||||
Use CoffeeScript.register() or require the coffeescript/register module to require <span class="hljs-subst">#{ext}</span> files.
|
||||
"""</span>
|
||||
"""</span>
|
||||
|
||||
CoffeeScript._compileFile = <span class="hljs-function"><span class="hljs-params">(filename, options = {})</span> -></span>
|
||||
raw = fs.readFileSync filename, <span class="hljs-string">'utf8'</span></pre></div></div>
|
||||
CoffeeScript._compileRawFileContent = <span class="hljs-function"><span class="hljs-params">(raw, filename, options = {})</span> -></span></pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -412,8 +413,8 @@ CoffeeScript._compileFile = <span class="hljs-function"><span class="hljs-params
|
||||
<li id="section-16">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-16">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-16">§</a>
|
||||
</div>
|
||||
<p>Strip the Unicode byte order mark, if this file begins with one.</p>
|
||||
|
||||
@@ -421,11 +422,10 @@ CoffeeScript._compileFile = <span class="hljs-function"><span class="hljs-params
|
||||
|
||||
<div class="content"><div class='highlight'><pre> stripped = <span class="hljs-keyword">if</span> raw.charCodeAt(<span class="hljs-number">0</span>) <span class="hljs-keyword">is</span> <span class="hljs-number">0xFEFF</span> <span class="hljs-keyword">then</span> raw.substring <span class="hljs-number">1</span> <span class="hljs-keyword">else</span> raw
|
||||
|
||||
options = Object.assign {}, options,
|
||||
options = <span class="hljs-built_in">Object</span>.assign {}, options,
|
||||
filename: filename
|
||||
literate: helpers.isLiterate filename
|
||||
sourceFiles: [filename]
|
||||
inlineMap: <span class="hljs-literal">yes</span> <span class="hljs-comment"># Always generate a source map, so that stack traces line up.</span>
|
||||
|
||||
<span class="hljs-keyword">try</span>
|
||||
answer = CoffeeScript.compile stripped, options
|
||||
@@ -437,8 +437,8 @@ CoffeeScript._compileFile = <span class="hljs-function"><span class="hljs-params
|
||||
<li id="section-17">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-17">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-17">§</a>
|
||||
</div>
|
||||
<p>As the filename and code of a dynamically loaded file will be different
|
||||
from the original file compiled with CoffeeScript.run, add that
|
||||
@@ -450,7 +450,44 @@ information to error so it can be pretty-printed later.</p>
|
||||
|
||||
answer
|
||||
|
||||
<span class="hljs-built_in">module</span>.exports = CoffeeScript</pre></div></div>
|
||||
CoffeeScript._compileFile = <span class="hljs-function"><span class="hljs-params">(filename, options = {})</span> -></span>
|
||||
raw = fs.readFileSync filename, <span class="hljs-string">'utf8'</span>
|
||||
|
||||
CoffeeScript._compileRawFileContent raw, filename, options
|
||||
|
||||
module.<span class="hljs-built_in">exports</span> = CoffeeScript</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-18">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-18">§</a>
|
||||
</div>
|
||||
<p>Explicitly define all named exports so that Node’s automatic detection of
|
||||
named exports from CommonJS packages finds all of them. This enables consuming
|
||||
packages to write code like <code>import { compile } from 'coffeescript'</code>.
|
||||
Don’t simplify this into a loop or similar; the <code>module.exports.name</code> part is
|
||||
essential for Node’s algorithm to successfully detect the name.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre>module.<span class="hljs-built_in">exports</span>.VERSION = CoffeeScript.VERSION
|
||||
module.<span class="hljs-built_in">exports</span>.FILE_EXTENSIONS = CoffeeScript.FILE_EXTENSIONS
|
||||
module.<span class="hljs-built_in">exports</span>.helpers = CoffeeScript.helpers
|
||||
module.<span class="hljs-built_in">exports</span>.registerCompiled = CoffeeScript.registerCompiled
|
||||
module.<span class="hljs-built_in">exports</span>.compile = CoffeeScript.compile
|
||||
module.<span class="hljs-built_in">exports</span>.tokens = CoffeeScript.tokens
|
||||
module.<span class="hljs-built_in">exports</span>.nodes = CoffeeScript.nodes
|
||||
module.<span class="hljs-built_in">exports</span>.register = CoffeeScript.register
|
||||
module.<span class="hljs-built_in">exports</span>.<span class="hljs-built_in">eval</span> = CoffeeScript.<span class="hljs-built_in">eval</span>
|
||||
module.<span class="hljs-built_in">exports</span>.run = CoffeeScript.run
|
||||
module.<span class="hljs-built_in">exports</span>.transpile = CoffeeScript.transpile
|
||||
module.<span class="hljs-built_in">exports</span>.patchStackTrace = CoffeeScript.patchStackTrace
|
||||
module.<span class="hljs-built_in">exports</span>._compileRawFileContent = CoffeeScript._compileRawFileContent
|
||||
module.<span class="hljs-built_in">exports</span>._compileFile = CoffeeScript._compileFile</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -112,13 +112,13 @@
|
||||
<li id="section-1">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-1">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-1">§</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre>{repeat} = <span class="hljs-built_in">require</span> <span class="hljs-string">'./helpers'</span></pre></div></div>
|
||||
<div class="content"><div class='highlight'><pre>{repeat} = <span class="hljs-built_in">require</span> <span class="hljs-string">'./helpers'</span></pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -126,21 +126,22 @@
|
||||
<li id="section-2">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-2">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-2">§</a>
|
||||
</div>
|
||||
<p>A simple <strong>OptionParser</strong> class to parse option flags from the command-line.
|
||||
Use it like so:</p>
|
||||
<pre><code>parser = <span class="hljs-keyword">new</span> OptionParser switches, helpBanner
|
||||
options = parser.parse process.argv
|
||||
</code></pre><p>The first non-option is considered to be the start of the file (and file
|
||||
</code></pre>
|
||||
<p>The first non-option is considered to be the start of the file (and file
|
||||
option) list, and all subsequent arguments are left unparsed.</p>
|
||||
<p>The <code>coffee</code> command uses an instance of <strong>OptionParser</strong> to parse its
|
||||
command-line arguments in <code>src/command.coffee</code>.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre>exports.OptionParser = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">OptionParser</span></span></pre></div></div>
|
||||
<div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.OptionParser = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">OptionParser</span></span></pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -148,12 +149,13 @@ command-line arguments in <code>src/command.coffee</code>.</p>
|
||||
<li id="section-3">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-3">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-3">§</a>
|
||||
</div>
|
||||
<p>Initialize with a list of valid options, in the form:</p>
|
||||
<pre><code>[short-flag, long-flag, description]
|
||||
</code></pre><p>Along with an optional banner for the usage help.</p>
|
||||
</code></pre>
|
||||
<p>Along with an optional banner for the usage help.</p>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -166,8 +168,8 @@ command-line arguments in <code>src/command.coffee</code>.</p>
|
||||
<li id="section-4">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-4">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-4">§</a>
|
||||
</div>
|
||||
<p>Parse the list of arguments, populating an <code>options</code> object with all of the
|
||||
specified options, and return it. Options after the first non-option
|
||||
@@ -186,8 +188,8 @@ you’re responsible for interpreting the options object.</p>
|
||||
<li id="section-5">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-5">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-5">§</a>
|
||||
</div>
|
||||
<p>The CoffeeScript option parser is a little odd; options after the first
|
||||
non-option argument are treated as non-option arguments themselves.
|
||||
@@ -208,8 +210,8 @@ line <code>#!/usr/bin/env coffee</code>, or <code>#!/absolute/path/to/coffee</co
|
||||
<li id="section-6">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-6">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-6">§</a>
|
||||
</div>
|
||||
<p>The <code>argument</code> field is added to the rule instance non-destructively by
|
||||
<code>normalizeArguments</code>.</p>
|
||||
@@ -226,7 +228,7 @@ line <code>#!/usr/bin/env coffee</code>, or <code>#!/absolute/path/to/coffee</co
|
||||
<span class="hljs-keyword">else</span>
|
||||
options[name] = <span class="hljs-literal">true</span>
|
||||
|
||||
<span class="hljs-keyword">if</span> positional[<span class="hljs-number">0</span>] <span class="hljs-keyword">is</span> <span class="hljs-string">'--'</span>
|
||||
<span class="hljs-keyword">if</span> positional[<span class="hljs-number">0</span>] <span class="hljs-keyword">is</span> <span class="hljs-string">'--'</span>
|
||||
options.doubleDashed = <span class="hljs-literal">yes</span>
|
||||
positional = positional[<span class="hljs-number">1.</span>.]
|
||||
|
||||
@@ -239,8 +241,8 @@ line <code>#!/usr/bin/env coffee</code>, or <code>#!/absolute/path/to/coffee</co
|
||||
<li id="section-7">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-7">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-7">§</a>
|
||||
</div>
|
||||
<p>Return the help text for this <strong>OptionParser</strong>, listing and describing all
|
||||
of the valid options, for <code>--help</code> and such.</p>
|
||||
@@ -249,13 +251,13 @@ of the valid options, for <code>--help</code> and such.</p>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> help: <span class="hljs-function">-></span>
|
||||
lines = []
|
||||
lines.unshift <span class="hljs-string">"<span class="hljs-subst">#{@banner}</span>\n"</span> <span class="hljs-keyword">if</span> @banner
|
||||
lines.unshift <span class="hljs-string">"<span class="hljs-subst">#{@banner}</span>\n"</span> <span class="hljs-keyword">if</span> @banner
|
||||
<span class="hljs-keyword">for</span> rule <span class="hljs-keyword">in</span> @rules.ruleList
|
||||
spaces = <span class="hljs-number">15</span> - rule.longFlag.length
|
||||
spaces = <span class="hljs-keyword">if</span> spaces > <span class="hljs-number">0</span> <span class="hljs-keyword">then</span> repeat <span class="hljs-string">' '</span>, spaces <span class="hljs-keyword">else</span> <span class="hljs-string">''</span>
|
||||
letPart = <span class="hljs-keyword">if</span> rule.shortFlag <span class="hljs-keyword">then</span> rule.shortFlag + <span class="hljs-string">', '</span> <span class="hljs-keyword">else</span> <span class="hljs-string">' '</span>
|
||||
lines.push <span class="hljs-string">' '</span> + letPart + rule.longFlag + spaces + rule.description
|
||||
<span class="hljs-string">"\n<span class="hljs-subst">#{ lines.join(<span class="hljs-string">'\n'</span>) }</span>\n"</span></pre></div></div>
|
||||
spaces = <span class="hljs-keyword">if</span> spaces > <span class="hljs-number">0</span> <span class="hljs-keyword">then</span> repeat <span class="hljs-string">' '</span>, spaces <span class="hljs-keyword">else</span> <span class="hljs-string">''</span>
|
||||
letPart = <span class="hljs-keyword">if</span> rule.shortFlag <span class="hljs-keyword">then</span> rule.shortFlag + <span class="hljs-string">', '</span> <span class="hljs-keyword">else</span> <span class="hljs-string">' '</span>
|
||||
lines.push <span class="hljs-string">' '</span> + letPart + rule.longFlag + spaces + rule.description
|
||||
<span class="hljs-string">"\n<span class="hljs-subst">#{ lines.join(<span class="hljs-string">'\n'</span>) }</span>\n"</span></pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -263,8 +265,8 @@ of the valid options, for <code>--help</code> and such.</p>
|
||||
<li id="section-8">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-8">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-8">§</a>
|
||||
</div>
|
||||
<h2 id="helpers">Helpers</h2>
|
||||
|
||||
@@ -276,8 +278,8 @@ of the valid options, for <code>--help</code> and such.</p>
|
||||
<li id="section-9">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-9">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-9">§</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -288,8 +290,8 @@ of the valid options, for <code>--help</code> and such.</p>
|
||||
<li id="section-10">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-10">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-10">§</a>
|
||||
</div>
|
||||
<p>Regex matchers for option flags on the command line and their rules.</p>
|
||||
|
||||
@@ -305,8 +307,8 @@ MULTI_FLAG = <span class="hljs-regexp">/^-(\w{2,})/</span></pre></div></div>
|
||||
<li id="section-11">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-11">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-11">§</a>
|
||||
</div>
|
||||
<p>Matches the long flag part of a rule for an option with an argument. Not
|
||||
applied to anything in process.argv.</p>
|
||||
@@ -321,8 +323,8 @@ applied to anything in process.argv.</p>
|
||||
<li id="section-12">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-12">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-12">§</a>
|
||||
</div>
|
||||
<p>Build and return the list of option rules. If the optional <em>short-flag</em> is
|
||||
unspecified, leave it out by padding with <code>null</code>.</p>
|
||||
@@ -342,8 +344,8 @@ unspecified, leave it out by padding with <code>null</code>.</p>
|
||||
<li id="section-13">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-13">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-13">§</a>
|
||||
</div>
|
||||
<p><code>shortFlag</code> is null if not provided in the rule.</p>
|
||||
|
||||
@@ -351,8 +353,8 @@ unspecified, leave it out by padding with <code>null</code>.</p>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">for</span> flag <span class="hljs-keyword">in</span> [rule.shortFlag, rule.longFlag] <span class="hljs-keyword">when</span> flag?
|
||||
<span class="hljs-keyword">if</span> flagDict[flag]?
|
||||
<span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> Error <span class="hljs-string">"flag <span class="hljs-subst">#{flag}</span> for switch <span class="hljs-subst">#{rule.name}</span>
|
||||
was already declared for switch <span class="hljs-subst">#{flagDict[flag].name}</span>"</span>
|
||||
<span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span> <span class="hljs-string">"flag <span class="hljs-subst">#{flag}</span> for switch <span class="hljs-subst">#{rule.name}</span>
|
||||
was already declared for switch <span class="hljs-subst">#{flagDict[flag].name}</span>"</span>
|
||||
flagDict[flag] = rule
|
||||
|
||||
{ruleList, flagDict}</pre></div></div>
|
||||
@@ -363,8 +365,8 @@ unspecified, leave it out by padding with <code>null</code>.</p>
|
||||
<li id="section-14">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-14">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-14">§</a>
|
||||
</div>
|
||||
<p>Build a rule from a <code>-o</code> short flag, a <code>--output [DIR]</code> long flag, and the
|
||||
description of what the option does.</p>
|
||||
@@ -376,7 +378,7 @@ description of what the option does.</p>
|
||||
shortFlag = shortFlag?.match(SHORT_FLAG)[<span class="hljs-number">1</span>]
|
||||
longFlag = longFlag.match(LONG_FLAG)[<span class="hljs-number">1</span>]
|
||||
{
|
||||
name: longFlag.replace <span class="hljs-regexp">/^--/</span>, <span class="hljs-string">''</span>
|
||||
name: longFlag.replace <span class="hljs-regexp">/^--/</span>, <span class="hljs-string">''</span>
|
||||
shortFlag: shortFlag
|
||||
longFlag: longFlag
|
||||
description: description
|
||||
@@ -396,8 +398,8 @@ description of what the option does.</p>
|
||||
<li id="section-15">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-15">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-15">§</a>
|
||||
</div>
|
||||
<p>If the previous argument given to the script was an option that uses the
|
||||
next command-line argument as its argument, create copy of the option’s
|
||||
@@ -406,19 +408,19 @@ rule with an <code>argument</code> field.</p>
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> needsArgOpt?
|
||||
withArg = Object.assign {}, needsArgOpt.rule, {argument: arg}
|
||||
withArg = <span class="hljs-built_in">Object</span>.assign {}, needsArgOpt.rule, {argument: arg}
|
||||
rules.push withArg
|
||||
needsArgOpt = <span class="hljs-literal">null</span>
|
||||
<span class="hljs-keyword">continue</span>
|
||||
|
||||
multiFlags = arg.match(MULTI_FLAG)?[<span class="hljs-number">1</span>]
|
||||
.split(<span class="hljs-string">''</span>)
|
||||
.map (flagName) -> <span class="hljs-string">"-<span class="hljs-subst">#{flagName}</span>"</span>
|
||||
.split(<span class="hljs-string">''</span>)
|
||||
.map (flagName) -> <span class="hljs-string">"-<span class="hljs-subst">#{flagName}</span>"</span>
|
||||
<span class="hljs-keyword">if</span> multiFlags?
|
||||
multiOpts = multiFlags.map (flag) ->
|
||||
rule = flagDict[flag]
|
||||
<span class="hljs-keyword">unless</span> rule?
|
||||
<span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> Error <span class="hljs-string">"unrecognized option <span class="hljs-subst">#{flag}</span> in multi-flag <span class="hljs-subst">#{arg}</span>"</span>
|
||||
<span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span> <span class="hljs-string">"unrecognized option <span class="hljs-subst">#{flag}</span> in multi-flag <span class="hljs-subst">#{arg}</span>"</span>
|
||||
{rule, flag}</pre></div></div>
|
||||
|
||||
</li>
|
||||
@@ -427,8 +429,8 @@ rule with an <code>argument</code> field.</p>
|
||||
<li id="section-16">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-16">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-16">§</a>
|
||||
</div>
|
||||
<p>Only the last flag in a multi-flag may have an argument.</p>
|
||||
|
||||
@@ -437,8 +439,8 @@ rule with an <code>argument</code> field.</p>
|
||||
<div class="content"><div class='highlight'><pre> [innerOpts..., lastOpt] = multiOpts
|
||||
<span class="hljs-keyword">for</span> {rule, flag} <span class="hljs-keyword">in</span> innerOpts
|
||||
<span class="hljs-keyword">if</span> rule.hasArgument
|
||||
<span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> Error <span class="hljs-string">"cannot use option <span class="hljs-subst">#{flag}</span> in multi-flag <span class="hljs-subst">#{arg}</span> except
|
||||
as the last option, because it needs an argument"</span>
|
||||
<span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span> <span class="hljs-string">"cannot use option <span class="hljs-subst">#{flag}</span> in multi-flag <span class="hljs-subst">#{arg}</span> except
|
||||
as the last option, because it needs an argument"</span>
|
||||
rules.push rule
|
||||
<span class="hljs-keyword">if</span> lastOpt.rule.hasArgument
|
||||
needsArgOpt = lastOpt
|
||||
@@ -447,7 +449,7 @@ rule with an <code>argument</code> field.</p>
|
||||
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> ([LONG_FLAG, SHORT_FLAG].some (pat) -> arg.match(pat)?)
|
||||
singleRule = flagDict[arg]
|
||||
<span class="hljs-keyword">unless</span> singleRule?
|
||||
<span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> Error <span class="hljs-string">"unrecognized option <span class="hljs-subst">#{arg}</span>"</span>
|
||||
<span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span> <span class="hljs-string">"unrecognized option <span class="hljs-subst">#{arg}</span>"</span>
|
||||
<span class="hljs-keyword">if</span> singleRule.hasArgument
|
||||
needsArgOpt = {rule: singleRule, flag: arg}
|
||||
<span class="hljs-keyword">else</span>
|
||||
@@ -460,8 +462,8 @@ rule with an <code>argument</code> field.</p>
|
||||
<li id="section-17">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-17">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-17">§</a>
|
||||
</div>
|
||||
<p>This is a positional argument.</p>
|
||||
|
||||
@@ -471,8 +473,8 @@ rule with an <code>argument</code> field.</p>
|
||||
<span class="hljs-keyword">break</span>
|
||||
|
||||
<span class="hljs-keyword">if</span> needsArgOpt?
|
||||
<span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> Error <span class="hljs-string">"value required for <span class="hljs-subst">#{needsArgOpt.flag}</span>, but it was the last
|
||||
argument provided"</span>
|
||||
<span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span> <span class="hljs-string">"value required for <span class="hljs-subst">#{needsArgOpt.flag}</span>, but it was the last
|
||||
argument provided"</span>
|
||||
{rules, positional}</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
0
docs/v2/annotated-source/public/fonts/roboto-black.eot
Executable file → Normal file
0
docs/v2/annotated-source/public/fonts/roboto-black.eot
Executable file → Normal file
0
docs/v2/annotated-source/public/fonts/roboto-black.ttf
Executable file → Normal file
0
docs/v2/annotated-source/public/fonts/roboto-black.ttf
Executable file → Normal file
0
docs/v2/annotated-source/public/fonts/roboto-black.woff
Executable file → Normal file
0
docs/v2/annotated-source/public/fonts/roboto-black.woff
Executable file → Normal file
@@ -112,16 +112,18 @@
|
||||
<li id="section-1">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-1">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-1">§</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre>CoffeeScript = <span class="hljs-built_in">require</span> <span class="hljs-string">'./'</span>
|
||||
child_process = <span class="hljs-built_in">require</span> <span class="hljs-string">'child_process'</span>
|
||||
helpers = <span class="hljs-built_in">require</span> <span class="hljs-string">'./helpers'</span>
|
||||
path = <span class="hljs-built_in">require</span> <span class="hljs-string">'path'</span></pre></div></div>
|
||||
<div class="content"><div class='highlight'><pre>CoffeeScript = <span class="hljs-built_in">require</span> <span class="hljs-string">'./'</span>
|
||||
child_process = <span class="hljs-built_in">require</span> <span class="hljs-string">'child_process'</span>
|
||||
helpers = <span class="hljs-built_in">require</span> <span class="hljs-string">'./helpers'</span>
|
||||
path = <span class="hljs-built_in">require</span> <span class="hljs-string">'path'</span>
|
||||
|
||||
{patchStackTrace} = CoffeeScript</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -129,17 +131,21 @@ path = <span class="hljs-built_in">require</span> <span class="hljs-str
|
||||
<li id="section-2">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-2">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-2">§</a>
|
||||
</div>
|
||||
<p>Load and run a CoffeeScript file for Node, stripping any <code>BOM</code>s.</p>
|
||||
<p>Check if Node’s built-in source map stack trace transformations are enabled.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">loadFile</span> = <span class="hljs-params">(<span class="hljs-built_in">module</span>, filename)</span> -></span>
|
||||
options = <span class="hljs-built_in">module</span>.options <span class="hljs-keyword">or</span> getRootModule(<span class="hljs-built_in">module</span>).options
|
||||
answer = CoffeeScript._compileFile filename, options
|
||||
<span class="hljs-built_in">module</span>._compile answer, filename</pre></div></div>
|
||||
<div class="content"><div class='highlight'><pre>nodeSourceMapsSupportEnabled = process? <span class="hljs-keyword">and</span> (
|
||||
process.execArgv.includes(<span class="hljs-string">'--enable-source-maps'</span>) <span class="hljs-keyword">or</span>
|
||||
process.env.NODE_OPTIONS?.includes(<span class="hljs-string">'--enable-source-maps'</span>)
|
||||
)
|
||||
|
||||
<span class="hljs-keyword">unless</span> <span class="hljs-built_in">Error</span>.prepareStackTrace <span class="hljs-keyword">or</span> nodeSourceMapsSupportEnabled
|
||||
cacheSourceMaps = <span class="hljs-literal">true</span>
|
||||
patchStackTrace()</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -147,8 +153,44 @@ path = <span class="hljs-built_in">require</span> <span class="hljs-str
|
||||
<li id="section-3">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-3">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-3">§</a>
|
||||
</div>
|
||||
<p>Load and run a CoffeeScript file for Node, stripping any <code>BOM</code>s.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">loadFile</span> = <span class="hljs-params">(module, filename)</span> -></span>
|
||||
options = module.options <span class="hljs-keyword">or</span> getRootModule(module).options <span class="hljs-keyword">or</span> {}</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-4">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-4">§</a>
|
||||
</div>
|
||||
<p>Currently <code>CoffeeScript.compile</code> caches all source maps if present. They
|
||||
are available in <code>getSourceMap</code> retrieved by <code>filename</code>.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> cacheSourceMaps <span class="hljs-keyword">or</span> nodeSourceMapsSupportEnabled
|
||||
options.inlineMap = <span class="hljs-literal">true</span>
|
||||
js = CoffeeScript._compileFile filename, options
|
||||
|
||||
module._compile js, filename</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-5">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-5">§</a>
|
||||
</div>
|
||||
<p>If the installed version of Node supports <code>require.extensions</code>, register
|
||||
CoffeeScript as an extension.</p>
|
||||
@@ -162,61 +204,21 @@ CoffeeScript as an extension.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-4">
|
||||
<li id="section-6">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-4">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-6">§</a>
|
||||
</div>
|
||||
<p>Patch Node’s module loader to be able to handle multi-dot extensions.
|
||||
This is a horrible thing that should not be required.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> Module = <span class="hljs-built_in">require</span> <span class="hljs-string">'module'</span>
|
||||
<div class="content"><div class='highlight'><pre> Module = <span class="hljs-built_in">require</span> <span class="hljs-string">'module'</span>
|
||||
<span class="hljs-function">
|
||||
<span class="hljs-title">findExtension</span> = <span class="hljs-params">(filename)</span> -></span>
|
||||
extensions = path.basename(filename).split <span class="hljs-string">'.'</span></pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-5">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-5">¶</a>
|
||||
</div>
|
||||
<p>Remove the initial dot from dotfiles.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> extensions.shift() <span class="hljs-keyword">if</span> extensions[<span class="hljs-number">0</span>] <span class="hljs-keyword">is</span> <span class="hljs-string">''</span></pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-6">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-6">¶</a>
|
||||
</div>
|
||||
<p>Start with the longest possible extension and work our way shortwards.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">while</span> extensions.shift()
|
||||
curExtension = <span class="hljs-string">'.'</span> + extensions.join <span class="hljs-string">'.'</span>
|
||||
<span class="hljs-keyword">return</span> curExtension <span class="hljs-keyword">if</span> Module._extensions[curExtension]
|
||||
<span class="hljs-string">'.js'</span>
|
||||
|
||||
Module::load = <span class="hljs-function"><span class="hljs-params">(filename)</span> -></span>
|
||||
@filename = filename
|
||||
@paths = Module._nodeModulePaths path.dirname filename
|
||||
extension = findExtension filename
|
||||
Module._extensions[extension](<span class="hljs-keyword">this</span>, filename)
|
||||
@loaded = <span class="hljs-literal">true</span></pre></div></div>
|
||||
extensions = path.basename(filename).split <span class="hljs-string">'.'</span></pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -224,8 +226,48 @@ This is a horrible thing that should not be required.</p>
|
||||
<li id="section-7">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-7">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-7">§</a>
|
||||
</div>
|
||||
<p>Remove the initial dot from dotfiles.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> extensions.shift() <span class="hljs-keyword">if</span> extensions[<span class="hljs-number">0</span>] <span class="hljs-keyword">is</span> <span class="hljs-string">''</span></pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-8">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-8">§</a>
|
||||
</div>
|
||||
<p>Start with the longest possible extension and work our way shortwards.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">while</span> extensions.shift()
|
||||
curExtension = <span class="hljs-string">'.'</span> + extensions.join <span class="hljs-string">'.'</span>
|
||||
<span class="hljs-keyword">return</span> curExtension <span class="hljs-keyword">if</span> Module._extensions[curExtension]
|
||||
<span class="hljs-string">'.js'</span>
|
||||
|
||||
Module::load = <span class="hljs-function"><span class="hljs-params">(filename)</span> -></span>
|
||||
@filename = filename
|
||||
@paths = Module._nodeModulePaths path.dirname filename
|
||||
extension = findExtension filename
|
||||
Module._extensions[extension](this, filename)
|
||||
@loaded = <span class="hljs-literal">true</span></pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-9">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-9">§</a>
|
||||
</div>
|
||||
<p>If we’re on Node, patch <code>child_process.fork</code> so that Coffee scripts are able
|
||||
to fork both CoffeeScript files, and JavaScript files, directly.</p>
|
||||
@@ -234,10 +276,10 @@ to fork both CoffeeScript files, and JavaScript files, directly.</p>
|
||||
|
||||
<div class="content"><div class='highlight'><pre><span class="hljs-keyword">if</span> child_process
|
||||
{fork} = child_process
|
||||
binary = <span class="hljs-built_in">require</span>.resolve <span class="hljs-string">'../../bin/coffee'</span>
|
||||
binary = <span class="hljs-built_in">require</span>.resolve <span class="hljs-string">'../../bin/coffee'</span>
|
||||
child_process.fork = <span class="hljs-function"><span class="hljs-params">(path, args, options)</span> -></span>
|
||||
<span class="hljs-keyword">if</span> helpers.isCoffee path
|
||||
<span class="hljs-keyword">unless</span> Array.isArray args
|
||||
<span class="hljs-keyword">unless</span> <span class="hljs-built_in">Array</span>.isArray args
|
||||
options = args <span class="hljs-keyword">or</span> {}
|
||||
args = []
|
||||
args = [path].concat args
|
||||
@@ -247,18 +289,18 @@ to fork both CoffeeScript files, and JavaScript files, directly.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-8">
|
||||
<li id="section-10">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-8">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-10">§</a>
|
||||
</div>
|
||||
<p>Utility function to find the <code>options</code> object attached to the topmost module.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">getRootModule</span> = <span class="hljs-params">(<span class="hljs-built_in">module</span>)</span> -></span>
|
||||
<span class="hljs-keyword">if</span> <span class="hljs-built_in">module</span>.parent <span class="hljs-keyword">then</span> getRootModule <span class="hljs-built_in">module</span>.parent <span class="hljs-keyword">else</span> <span class="hljs-built_in">module</span></pre></div></div>
|
||||
<div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">getRootModule</span> = <span class="hljs-params">(module)</span> -></span>
|
||||
<span class="hljs-keyword">if</span> module.parent <span class="hljs-keyword">then</span> getRootModule module.parent <span class="hljs-keyword">else</span> module</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
@@ -112,27 +112,27 @@
|
||||
<li id="section-1">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-1">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-1">§</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre>fs = <span class="hljs-built_in">require</span> <span class="hljs-string">'fs'</span>
|
||||
path = <span class="hljs-built_in">require</span> <span class="hljs-string">'path'</span>
|
||||
vm = <span class="hljs-built_in">require</span> <span class="hljs-string">'vm'</span>
|
||||
nodeREPL = <span class="hljs-built_in">require</span> <span class="hljs-string">'repl'</span>
|
||||
CoffeeScript = <span class="hljs-built_in">require</span> <span class="hljs-string">'./'</span>
|
||||
{merge, updateSyntaxError} = <span class="hljs-built_in">require</span> <span class="hljs-string">'./helpers'</span>
|
||||
<div class="content"><div class='highlight'><pre>fs = <span class="hljs-built_in">require</span> <span class="hljs-string">'fs'</span>
|
||||
path = <span class="hljs-built_in">require</span> <span class="hljs-string">'path'</span>
|
||||
vm = <span class="hljs-built_in">require</span> <span class="hljs-string">'vm'</span>
|
||||
nodeREPL = <span class="hljs-built_in">require</span> <span class="hljs-string">'repl'</span>
|
||||
CoffeeScript = <span class="hljs-built_in">require</span> <span class="hljs-string">'./'</span>
|
||||
{merge, updateSyntaxError} = <span class="hljs-built_in">require</span> <span class="hljs-string">'./helpers'</span>
|
||||
|
||||
sawSIGINT = <span class="hljs-literal">no</span>
|
||||
transpile = <span class="hljs-literal">no</span>
|
||||
|
||||
replDefaults =
|
||||
prompt: <span class="hljs-string">'coffee> '</span>,
|
||||
prompt: <span class="hljs-string">'coffee> '</span>,
|
||||
historyFile: <span class="hljs-keyword">do</span> ->
|
||||
historyPath = process.env.XDG_CACHE_HOME <span class="hljs-keyword">or</span> process.env.HOME
|
||||
path.join historyPath, <span class="hljs-string">'.coffee_history'</span> <span class="hljs-keyword">if</span> historyPath
|
||||
path.join historyPath, <span class="hljs-string">'.coffee_history'</span> <span class="hljs-keyword">if</span> historyPath
|
||||
historyMaxInputSize: <span class="hljs-number">10240</span>
|
||||
eval: <span class="hljs-function"><span class="hljs-params">(input, context, filename, cb)</span> -></span></pre></div></div>
|
||||
|
||||
@@ -142,14 +142,14 @@ replDefaults =
|
||||
<li id="section-2">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-2">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-2">§</a>
|
||||
</div>
|
||||
<p>XXX: multiline hack.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> input = input.replace <span class="hljs-regexp">/\uFF00/g</span>, <span class="hljs-string">'\n'</span></pre></div></div>
|
||||
<div class="content"><div class='highlight'><pre> input = input.replace <span class="hljs-regexp">/\uFF00/g</span>, <span class="hljs-string">'\n'</span></pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -157,15 +157,15 @@ replDefaults =
|
||||
<li id="section-3">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-3">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-3">§</a>
|
||||
</div>
|
||||
<p>Node’s REPL sends the input ending with a newline and then wrapped in
|
||||
parens. Unwrap all that.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> input = input.replace <span class="hljs-regexp">/^\(([\s\S]*)\n\)$/m</span>, <span class="hljs-string">'$1'</span></pre></div></div>
|
||||
<div class="content"><div class='highlight'><pre> input = input.replace <span class="hljs-regexp">/^\(([\s\S]*)\n\)$/m</span>, <span class="hljs-string">'$1'</span></pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -173,15 +173,15 @@ parens. Unwrap all that.</p>
|
||||
<li id="section-4">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-4">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-4">§</a>
|
||||
</div>
|
||||
<p>Node’s REPL v6.9.1+ sends the input wrapped in a try/catch statement.
|
||||
Unwrap that too.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> input = input.replace <span class="hljs-regexp">/^\s*try\s*{([\s\S]*)}\s*catch.*$/m</span>, <span class="hljs-string">'$1'</span></pre></div></div>
|
||||
<div class="content"><div class='highlight'><pre> input = input.replace <span class="hljs-regexp">/^\s*try\s*{([\s\S]*)}\s*catch.*$/m</span>, <span class="hljs-string">'$1'</span></pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -189,14 +189,14 @@ Unwrap that too.</p>
|
||||
<li id="section-5">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-5">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-5">§</a>
|
||||
</div>
|
||||
<p>Require AST nodes to do some AST manipulation.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> {Block, Assign, Value, Literal, Call, Code} = <span class="hljs-built_in">require</span> <span class="hljs-string">'./nodes'</span>
|
||||
<div class="content"><div class='highlight'><pre> {Block, Assign, Value, Literal, Call, Code, Root} = <span class="hljs-built_in">require</span> <span class="hljs-string">'./nodes'</span>
|
||||
|
||||
<span class="hljs-keyword">try</span></pre></div></div>
|
||||
|
||||
@@ -206,8 +206,8 @@ Unwrap that too.</p>
|
||||
<li id="section-6">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-6">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-6">§</a>
|
||||
</div>
|
||||
<p>Tokenize the clean input.</p>
|
||||
|
||||
@@ -221,19 +221,19 @@ Unwrap that too.</p>
|
||||
<li id="section-7">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-7">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-7">§</a>
|
||||
</div>
|
||||
<p>Filter out tokens generated just to hold comments.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> tokens.length >= <span class="hljs-number">2</span> <span class="hljs-keyword">and</span> tokens[<span class="hljs-number">0</span>].generated <span class="hljs-keyword">and</span>
|
||||
tokens[<span class="hljs-number">0</span>].comments?.length <span class="hljs-keyword">isnt</span> <span class="hljs-number">0</span> <span class="hljs-keyword">and</span> tokens[<span class="hljs-number">0</span>][<span class="hljs-number">1</span>] <span class="hljs-keyword">is</span> <span class="hljs-string">''</span> <span class="hljs-keyword">and</span>
|
||||
tokens[<span class="hljs-number">1</span>][<span class="hljs-number">0</span>] <span class="hljs-keyword">is</span> <span class="hljs-string">'TERMINATOR'</span>
|
||||
tokens[<span class="hljs-number">0</span>].comments?.length <span class="hljs-keyword">isnt</span> <span class="hljs-number">0</span> <span class="hljs-keyword">and</span> <span class="hljs-string">"<span class="hljs-subst">#{tokens[<span class="hljs-number">0</span>][<span class="hljs-number">1</span>]}</span>"</span> <span class="hljs-keyword">is</span> <span class="hljs-string">''</span> <span class="hljs-keyword">and</span>
|
||||
tokens[<span class="hljs-number">1</span>][<span class="hljs-number">0</span>] <span class="hljs-keyword">is</span> <span class="hljs-string">'TERMINATOR'</span>
|
||||
tokens = tokens[<span class="hljs-number">2.</span>..]
|
||||
<span class="hljs-keyword">if</span> tokens.length >= <span class="hljs-number">1</span> <span class="hljs-keyword">and</span> tokens[tokens.length - <span class="hljs-number">1</span>].generated <span class="hljs-keyword">and</span>
|
||||
tokens[tokens.length - <span class="hljs-number">1</span>].comments?.length <span class="hljs-keyword">isnt</span> <span class="hljs-number">0</span> <span class="hljs-keyword">and</span> tokens[tokens.length - <span class="hljs-number">1</span>][<span class="hljs-number">1</span>] <span class="hljs-keyword">is</span> <span class="hljs-string">''</span>
|
||||
tokens[tokens.length - <span class="hljs-number">1</span>].comments?.length <span class="hljs-keyword">isnt</span> <span class="hljs-number">0</span> <span class="hljs-keyword">and</span> <span class="hljs-string">"<span class="hljs-subst">#{tokens[tokens.length - <span class="hljs-number">1</span>][<span class="hljs-number">1</span>]}</span>"</span> <span class="hljs-keyword">is</span> <span class="hljs-string">''</span>
|
||||
tokens.pop()</pre></div></div>
|
||||
|
||||
</li>
|
||||
@@ -242,14 +242,14 @@ Unwrap that too.</p>
|
||||
<li id="section-8">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-8">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-8">§</a>
|
||||
</div>
|
||||
<p>Collect referenced variable names just like in <code>CoffeeScript.compile</code>.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> referencedVars = (token[<span class="hljs-number">1</span>] <span class="hljs-keyword">for</span> token <span class="hljs-keyword">in</span> tokens <span class="hljs-keyword">when</span> token[<span class="hljs-number">0</span>] <span class="hljs-keyword">is</span> <span class="hljs-string">'IDENTIFIER'</span>)</pre></div></div>
|
||||
<div class="content"><div class='highlight'><pre> referencedVars = (token[<span class="hljs-number">1</span>] <span class="hljs-keyword">for</span> token <span class="hljs-keyword">in</span> tokens <span class="hljs-keyword">when</span> token[<span class="hljs-number">0</span>] <span class="hljs-keyword">is</span> <span class="hljs-string">'IDENTIFIER'</span>)</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -257,14 +257,14 @@ Unwrap that too.</p>
|
||||
<li id="section-9">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-9">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-9">§</a>
|
||||
</div>
|
||||
<p>Generate the AST of the tokens.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> ast = CoffeeScript.nodes tokens</pre></div></div>
|
||||
<div class="content"><div class='highlight'><pre> ast = CoffeeScript.nodes(tokens).body</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -272,14 +272,14 @@ Unwrap that too.</p>
|
||||
<li id="section-10">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-10">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-10">§</a>
|
||||
</div>
|
||||
<p>Add assignment to <code>__</code> variable to force the input to be an expression.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> ast = <span class="hljs-keyword">new</span> Block [<span class="hljs-keyword">new</span> Assign (<span class="hljs-keyword">new</span> Value <span class="hljs-keyword">new</span> Literal <span class="hljs-string">'__'</span>), ast, <span class="hljs-string">'='</span>]</pre></div></div>
|
||||
<div class="content"><div class='highlight'><pre> ast = <span class="hljs-keyword">new</span> Block [<span class="hljs-keyword">new</span> Assign (<span class="hljs-keyword">new</span> Value <span class="hljs-keyword">new</span> Literal <span class="hljs-string">'__'</span>), ast, <span class="hljs-string">'='</span>]</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -287,8 +287,8 @@ Unwrap that too.</p>
|
||||
<li id="section-11">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-11">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-11">§</a>
|
||||
</div>
|
||||
<p>Wrap the expression in a closure to support top-level <code>await</code>.</p>
|
||||
|
||||
@@ -303,15 +303,15 @@ Unwrap that too.</p>
|
||||
<li id="section-12">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-12">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-12">§</a>
|
||||
</div>
|
||||
<p>Invoke the wrapping closure.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> ast = <span class="hljs-keyword">new</span> Block [<span class="hljs-keyword">new</span> Call ast]
|
||||
js = ast.compile {bare: <span class="hljs-literal">yes</span>, locals: Object.keys(context), referencedVars, sharedScope: <span class="hljs-literal">yes</span>}
|
||||
<div class="content"><div class='highlight'><pre> ast = <span class="hljs-keyword">new</span> Root <span class="hljs-keyword">new</span> Block [<span class="hljs-keyword">new</span> Call ast]
|
||||
js = ast.compile {bare: <span class="hljs-literal">yes</span>, locals: <span class="hljs-built_in">Object</span>.keys(context), referencedVars, sharedScope: <span class="hljs-literal">yes</span>}
|
||||
<span class="hljs-keyword">if</span> transpile
|
||||
js = transpile.transpile(js, transpile.options).code</pre></div></div>
|
||||
|
||||
@@ -321,15 +321,15 @@ Unwrap that too.</p>
|
||||
<li id="section-13">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-13">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-13">§</a>
|
||||
</div>
|
||||
<p>Strip <code>"use strict"</code>, to avoid an exception on assigning to
|
||||
undeclared variable <code>__</code>.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> js = js.replace <span class="hljs-regexp">/^"use strict"|^'use strict'/</span>, <span class="hljs-string">''</span>
|
||||
<div class="content"><div class='highlight'><pre> js = js.replace <span class="hljs-regexp">/^"use strict"|^'use strict'/</span>, <span class="hljs-string">''</span>
|
||||
result = runInContext js, context, filename</pre></div></div>
|
||||
|
||||
</li>
|
||||
@@ -338,8 +338,8 @@ undeclared variable <code>__</code>.</p>
|
||||
<li id="section-14">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-14">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-14">§</a>
|
||||
</div>
|
||||
<p>Await an async result, if necessary.</p>
|
||||
|
||||
@@ -359,8 +359,8 @@ undeclared variable <code>__</code>.</p>
|
||||
<li id="section-15">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-15">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-15">§</a>
|
||||
</div>
|
||||
<p>AST’s <code>compile</code> does not add source code information to syntax errors.</p>
|
||||
|
||||
@@ -370,13 +370,13 @@ undeclared variable <code>__</code>.</p>
|
||||
cb err
|
||||
<span class="hljs-function">
|
||||
<span class="hljs-title">runInContext</span> = <span class="hljs-params">(js, context, filename)</span> -></span>
|
||||
<span class="hljs-keyword">if</span> context <span class="hljs-keyword">is</span> <span class="hljs-built_in">global</span>
|
||||
<span class="hljs-keyword">if</span> context <span class="hljs-keyword">is</span> global
|
||||
vm.runInThisContext js, filename
|
||||
<span class="hljs-keyword">else</span>
|
||||
vm.runInContext js, context, filename
|
||||
<span class="hljs-function">
|
||||
<span class="hljs-title">addMultilineHandler</span> = <span class="hljs-params">(repl)</span> -></span>
|
||||
{rli, inputStream, outputStream} = repl</pre></div></div>
|
||||
{inputStream, outputStream} = repl</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -384,8 +384,8 @@ undeclared variable <code>__</code>.</p>
|
||||
<li id="section-16">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-16">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-16">§</a>
|
||||
</div>
|
||||
<p>Node 0.11.12 changed API, prompt is now _prompt.</p>
|
||||
|
||||
@@ -395,9 +395,9 @@ undeclared variable <code>__</code>.</p>
|
||||
|
||||
multiline =
|
||||
enabled: <span class="hljs-literal">off</span>
|
||||
initialPrompt: origPrompt.replace <span class="hljs-regexp">/^[^> ]*/</span>, <span class="hljs-function"><span class="hljs-params">(x)</span> -></span> x.replace <span class="hljs-regexp">/./g</span>, <span class="hljs-string">'-'</span>
|
||||
prompt: origPrompt.replace <span class="hljs-regexp">/^[^> ]*>?/</span>, <span class="hljs-function"><span class="hljs-params">(x)</span> -></span> x.replace <span class="hljs-regexp">/./g</span>, <span class="hljs-string">'.'</span>
|
||||
buffer: <span class="hljs-string">''</span></pre></div></div>
|
||||
initialPrompt: origPrompt.replace <span class="hljs-regexp">/^[^> ]*/</span>, <span class="hljs-function"><span class="hljs-params">(x)</span> -></span> x.replace <span class="hljs-regexp">/./g</span>, <span class="hljs-string">'-'</span>
|
||||
prompt: origPrompt.replace <span class="hljs-regexp">/^[^> ]*>?/</span>, <span class="hljs-function"><span class="hljs-params">(x)</span> -></span> x.replace <span class="hljs-regexp">/./g</span>, <span class="hljs-string">'.'</span>
|
||||
buffer: <span class="hljs-string">''</span></pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -405,22 +405,22 @@ undeclared variable <code>__</code>.</p>
|
||||
<li id="section-17">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-17">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-17">§</a>
|
||||
</div>
|
||||
<p>Proxy node’s line listener</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> nodeLineListener = rli.listeners(<span class="hljs-string">'line'</span>)[<span class="hljs-number">0</span>]
|
||||
rli.removeListener <span class="hljs-string">'line'</span>, nodeLineListener
|
||||
rli.<span class="hljs-literal">on</span> <span class="hljs-string">'line'</span>, <span class="hljs-function"><span class="hljs-params">(cmd)</span> -></span>
|
||||
<div class="content"><div class='highlight'><pre> nodeLineListener = repl.listeners(<span class="hljs-string">'line'</span>)[<span class="hljs-number">0</span>]
|
||||
repl.removeListener <span class="hljs-string">'line'</span>, nodeLineListener
|
||||
repl.<span class="hljs-literal">on</span> <span class="hljs-string">'line'</span>, <span class="hljs-function"><span class="hljs-params">(cmd)</span> -></span>
|
||||
<span class="hljs-keyword">if</span> multiline.enabled
|
||||
multiline.buffer += <span class="hljs-string">"<span class="hljs-subst">#{cmd}</span>\n"</span>
|
||||
rli.setPrompt multiline.prompt
|
||||
rli.prompt <span class="hljs-literal">true</span>
|
||||
multiline.buffer += <span class="hljs-string">"<span class="hljs-subst">#{cmd}</span>\n"</span>
|
||||
repl.setPrompt multiline.prompt
|
||||
repl.prompt <span class="hljs-literal">true</span>
|
||||
<span class="hljs-keyword">else</span>
|
||||
rli.setPrompt origPrompt
|
||||
repl.setPrompt origPrompt
|
||||
nodeLineListener cmd
|
||||
<span class="hljs-keyword">return</span></pre></div></div>
|
||||
|
||||
@@ -430,15 +430,15 @@ undeclared variable <code>__</code>.</p>
|
||||
<li id="section-18">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-18">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-18">§</a>
|
||||
</div>
|
||||
<p>Handle Ctrl-v</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> inputStream.<span class="hljs-literal">on</span> <span class="hljs-string">'keypress'</span>, <span class="hljs-function"><span class="hljs-params">(char, key)</span> -></span>
|
||||
<span class="hljs-keyword">return</span> <span class="hljs-keyword">unless</span> key <span class="hljs-keyword">and</span> key.ctrl <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> key.meta <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> key.shift <span class="hljs-keyword">and</span> key.name <span class="hljs-keyword">is</span> <span class="hljs-string">'v'</span>
|
||||
<div class="content"><div class='highlight'><pre> inputStream.<span class="hljs-literal">on</span> <span class="hljs-string">'keypress'</span>, <span class="hljs-function"><span class="hljs-params">(char, key)</span> -></span>
|
||||
<span class="hljs-keyword">return</span> <span class="hljs-keyword">unless</span> key <span class="hljs-keyword">and</span> key.ctrl <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> key.meta <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> key.shift <span class="hljs-keyword">and</span> key.name <span class="hljs-keyword">is</span> <span class="hljs-string">'v'</span>
|
||||
<span class="hljs-keyword">if</span> multiline.enabled</pre></div></div>
|
||||
|
||||
</li>
|
||||
@@ -447,8 +447,8 @@ undeclared variable <code>__</code>.</p>
|
||||
<li id="section-19">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-19">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-19">§</a>
|
||||
</div>
|
||||
<p>allow arbitrarily switching between modes any time before multiple lines are entered</p>
|
||||
|
||||
@@ -456,8 +456,8 @@ undeclared variable <code>__</code>.</p>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">unless</span> multiline.buffer.match <span class="hljs-regexp">/\n/</span>
|
||||
multiline.enabled = <span class="hljs-keyword">not</span> multiline.enabled
|
||||
rli.setPrompt origPrompt
|
||||
rli.prompt <span class="hljs-literal">true</span>
|
||||
repl.setPrompt origPrompt
|
||||
repl.prompt <span class="hljs-literal">true</span>
|
||||
<span class="hljs-keyword">return</span></pre></div></div>
|
||||
|
||||
</li>
|
||||
@@ -466,14 +466,14 @@ undeclared variable <code>__</code>.</p>
|
||||
<li id="section-20">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-20">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-20">§</a>
|
||||
</div>
|
||||
<p>no-op unless the current line is empty</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">return</span> <span class="hljs-keyword">if</span> rli.line? <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> rli.line.match <span class="hljs-regexp">/^\s*$/</span></pre></div></div>
|
||||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">return</span> <span class="hljs-keyword">if</span> repl.line? <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> repl.line.match <span class="hljs-regexp">/^\s*$/</span></pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -481,18 +481,18 @@ undeclared variable <code>__</code>.</p>
|
||||
<li id="section-21">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-21">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-21">§</a>
|
||||
</div>
|
||||
<p>eval, print, loop</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> multiline.enabled = <span class="hljs-keyword">not</span> multiline.enabled
|
||||
rli.line = <span class="hljs-string">''</span>
|
||||
rli.cursor = <span class="hljs-number">0</span>
|
||||
rli.output.cursorTo <span class="hljs-number">0</span>
|
||||
rli.output.clearLine <span class="hljs-number">1</span></pre></div></div>
|
||||
repl.line = <span class="hljs-string">''</span>
|
||||
repl.cursor = <span class="hljs-number">0</span>
|
||||
repl.output.cursorTo <span class="hljs-number">0</span>
|
||||
repl.output.clearLine <span class="hljs-number">1</span></pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -500,20 +500,20 @@ undeclared variable <code>__</code>.</p>
|
||||
<li id="section-22">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-22">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-22">§</a>
|
||||
</div>
|
||||
<p>XXX: multiline hack</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> multiline.buffer = multiline.buffer.replace <span class="hljs-regexp">/\n/g</span>, <span class="hljs-string">'\uFF00'</span>
|
||||
rli.emit <span class="hljs-string">'line'</span>, multiline.buffer
|
||||
multiline.buffer = <span class="hljs-string">''</span>
|
||||
<div class="content"><div class='highlight'><pre> multiline.buffer = multiline.buffer.replace <span class="hljs-regexp">/\n/g</span>, <span class="hljs-string">'\uFF00'</span>
|
||||
repl.emit <span class="hljs-string">'line'</span>, multiline.buffer
|
||||
multiline.buffer = <span class="hljs-string">''</span>
|
||||
<span class="hljs-keyword">else</span>
|
||||
multiline.enabled = <span class="hljs-keyword">not</span> multiline.enabled
|
||||
rli.setPrompt multiline.initialPrompt
|
||||
rli.prompt <span class="hljs-literal">true</span>
|
||||
repl.setPrompt multiline.initialPrompt
|
||||
repl.prompt <span class="hljs-literal">true</span>
|
||||
<span class="hljs-keyword">return</span></pre></div></div>
|
||||
|
||||
</li>
|
||||
@@ -522,8 +522,8 @@ undeclared variable <code>__</code>.</p>
|
||||
<li id="section-23">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-23">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-23">§</a>
|
||||
</div>
|
||||
<p>Store and load command history from a file</p>
|
||||
|
||||
@@ -539,15 +539,15 @@ undeclared variable <code>__</code>.</p>
|
||||
<li id="section-24">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-24">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-24">§</a>
|
||||
</div>
|
||||
<p>Get file info and at most maxSize of command history</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> stat = fs.statSync filename
|
||||
size = Math.min maxSize, stat.size</pre></div></div>
|
||||
size = <span class="hljs-built_in">Math</span>.min maxSize, stat.size</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -555,14 +555,14 @@ undeclared variable <code>__</code>.</p>
|
||||
<li id="section-25">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-25">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-25">§</a>
|
||||
</div>
|
||||
<p>Read last <code>size</code> bytes from the file</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> readFd = fs.openSync filename, <span class="hljs-string">'r'</span>
|
||||
<div class="content"><div class='highlight'><pre> readFd = fs.openSync filename, <span class="hljs-string">'r'</span>
|
||||
buffer = Buffer.alloc size
|
||||
fs.readSync readFd, buffer, <span class="hljs-number">0</span>, size, stat.size - size
|
||||
fs.closeSync readFd</pre></div></div>
|
||||
@@ -573,14 +573,14 @@ undeclared variable <code>__</code>.</p>
|
||||
<li id="section-26">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-26">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-26">§</a>
|
||||
</div>
|
||||
<p>Set the history on the interpreter</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> repl.rli.history = buffer.toString().split(<span class="hljs-string">'\n'</span>).reverse()</pre></div></div>
|
||||
<div class="content"><div class='highlight'><pre> repl.history = buffer.toString().split(<span class="hljs-string">'\n'</span>).reverse()</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -588,14 +588,14 @@ undeclared variable <code>__</code>.</p>
|
||||
<li id="section-27">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-27">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-27">§</a>
|
||||
</div>
|
||||
<p>If the history file was truncated we should pop off a potential partial line</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> repl.rli.history.pop() <span class="hljs-keyword">if</span> stat.size > maxSize</pre></div></div>
|
||||
<div class="content"><div class='highlight'><pre> repl.history.pop() <span class="hljs-keyword">if</span> stat.size > maxSize</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -603,21 +603,21 @@ undeclared variable <code>__</code>.</p>
|
||||
<li id="section-28">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-28">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-28">§</a>
|
||||
</div>
|
||||
<p>Shift off the final blank newline</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> repl.rli.history.shift() <span class="hljs-keyword">if</span> repl.rli.history[<span class="hljs-number">0</span>] <span class="hljs-keyword">is</span> <span class="hljs-string">''</span>
|
||||
repl.rli.historyIndex = <span class="hljs-number">-1</span>
|
||||
lastLine = repl.rli.history[<span class="hljs-number">0</span>]
|
||||
<div class="content"><div class='highlight'><pre> repl.history.shift() <span class="hljs-keyword">if</span> repl.history[<span class="hljs-number">0</span>] <span class="hljs-keyword">is</span> <span class="hljs-string">''</span>
|
||||
repl.historyIndex = <span class="hljs-number">-1</span>
|
||||
lastLine = repl.history[<span class="hljs-number">0</span>]
|
||||
|
||||
fd = fs.openSync filename, <span class="hljs-string">'a'</span>
|
||||
fd = fs.openSync filename, <span class="hljs-string">'a'</span>
|
||||
|
||||
repl.rli.addListener <span class="hljs-string">'line'</span>, <span class="hljs-function"><span class="hljs-params">(code)</span> -></span>
|
||||
<span class="hljs-keyword">if</span> code <span class="hljs-keyword">and</span> code.length <span class="hljs-keyword">and</span> code <span class="hljs-keyword">isnt</span> <span class="hljs-string">'.history'</span> <span class="hljs-keyword">and</span> code <span class="hljs-keyword">isnt</span> <span class="hljs-string">'.exit'</span> <span class="hljs-keyword">and</span> lastLine <span class="hljs-keyword">isnt</span> code</pre></div></div>
|
||||
repl.addListener <span class="hljs-string">'line'</span>, <span class="hljs-function"><span class="hljs-params">(code)</span> -></span>
|
||||
<span class="hljs-keyword">if</span> code <span class="hljs-keyword">and</span> code.length <span class="hljs-keyword">and</span> code <span class="hljs-keyword">isnt</span> <span class="hljs-string">'.history'</span> <span class="hljs-keyword">and</span> code <span class="hljs-keyword">isnt</span> <span class="hljs-string">'.exit'</span> <span class="hljs-keyword">and</span> lastLine <span class="hljs-keyword">isnt</span> code</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -625,14 +625,14 @@ undeclared variable <code>__</code>.</p>
|
||||
<li id="section-29">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-29">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-29">§</a>
|
||||
</div>
|
||||
<p>Save the latest command in the file</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> fs.writeSync fd, <span class="hljs-string">"<span class="hljs-subst">#{code}</span>\n"</span>
|
||||
<div class="content"><div class='highlight'><pre> fs.writeSync fd, <span class="hljs-string">"<span class="hljs-subst">#{code}</span>\n"</span>
|
||||
lastLine = code</pre></div></div>
|
||||
|
||||
</li>
|
||||
@@ -641,15 +641,15 @@ undeclared variable <code>__</code>.</p>
|
||||
<li id="section-30">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-30">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-30">§</a>
|
||||
</div>
|
||||
<p>XXX: The SIGINT event from REPLServer is undocumented, so this is a bit fragile</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> repl.<span class="hljs-literal">on</span> <span class="hljs-string">'SIGINT'</span>, <span class="hljs-function">-></span> sawSIGINT = <span class="hljs-literal">yes</span>
|
||||
repl.<span class="hljs-literal">on</span> <span class="hljs-string">'exit'</span>, <span class="hljs-function">-></span> fs.closeSync fd</pre></div></div>
|
||||
<div class="content"><div class='highlight'><pre> repl.<span class="hljs-literal">on</span> <span class="hljs-string">'SIGINT'</span>, <span class="hljs-function">-></span> sawSIGINT = <span class="hljs-literal">yes</span>
|
||||
repl.<span class="hljs-literal">on</span> <span class="hljs-string">'exit'</span>, <span class="hljs-function">-></span> fs.closeSync fd</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -657,17 +657,17 @@ undeclared variable <code>__</code>.</p>
|
||||
<li id="section-31">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-31">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-31">§</a>
|
||||
</div>
|
||||
<p>Add a command to show the history stack</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> repl.commands[getCommandId(repl, <span class="hljs-string">'history'</span>)] =
|
||||
help: <span class="hljs-string">'Show command history'</span>
|
||||
<div class="content"><div class='highlight'><pre> repl.commands[getCommandId(repl, <span class="hljs-string">'history'</span>)] =
|
||||
help: <span class="hljs-string">'Show command history'</span>
|
||||
action: <span class="hljs-function">-></span>
|
||||
repl.outputStream.write <span class="hljs-string">"<span class="hljs-subst">#{repl.rli.history[..].reverse().join <span class="hljs-string">'\n'</span>}</span>\n"</span>
|
||||
repl.outputStream.write <span class="hljs-string">"<span class="hljs-subst">#{repl.history[..].reverse().join <span class="hljs-string">'\n'</span>}</span>\n"</span>
|
||||
repl.displayPrompt()
|
||||
<span class="hljs-function">
|
||||
<span class="hljs-title">getCommandId</span> = <span class="hljs-params">(repl, commandName)</span> -></span></pre></div></div>
|
||||
@@ -678,45 +678,45 @@ undeclared variable <code>__</code>.</p>
|
||||
<li id="section-32">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-32">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-32">§</a>
|
||||
</div>
|
||||
<p>Node 0.11 changed API, a command such as ‘.help’ is now stored as ‘help’</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> commandsHaveLeadingDot = repl.commands[<span class="hljs-string">'.help'</span>]?
|
||||
<span class="hljs-keyword">if</span> commandsHaveLeadingDot <span class="hljs-keyword">then</span> <span class="hljs-string">".<span class="hljs-subst">#{commandName}</span>"</span> <span class="hljs-keyword">else</span> commandName
|
||||
<div class="content"><div class='highlight'><pre> commandsHaveLeadingDot = repl.commands[<span class="hljs-string">'.help'</span>]?
|
||||
<span class="hljs-keyword">if</span> commandsHaveLeadingDot <span class="hljs-keyword">then</span> <span class="hljs-string">".<span class="hljs-subst">#{commandName}</span>"</span> <span class="hljs-keyword">else</span> commandName
|
||||
|
||||
<span class="hljs-built_in">module</span>.exports =
|
||||
module.<span class="hljs-built_in">exports</span> =
|
||||
start: <span class="hljs-function"><span class="hljs-params">(opts = {})</span> -></span>
|
||||
[major, minor, build] = process.versions.node.split(<span class="hljs-string">'.'</span>).map (n) -> parseInt(n, <span class="hljs-number">10</span>)
|
||||
[major, minor, build] = process.versions.node.split(<span class="hljs-string">'.'</span>).map (n) -> <span class="hljs-built_in">parseInt</span>(n, <span class="hljs-number">10</span>)
|
||||
|
||||
<span class="hljs-keyword">if</span> major < <span class="hljs-number">6</span>
|
||||
<span class="hljs-built_in">console</span>.warn <span class="hljs-string">"Node 6+ required for CoffeeScript REPL"</span>
|
||||
console.warn <span class="hljs-string">"Node 6+ required for CoffeeScript REPL"</span>
|
||||
process.exit <span class="hljs-number">1</span>
|
||||
|
||||
CoffeeScript.register()
|
||||
process.argv = [<span class="hljs-string">'coffee'</span>].concat process.argv[<span class="hljs-number">2.</span>.]
|
||||
process.argv = [<span class="hljs-string">'coffee'</span>].concat process.argv[<span class="hljs-number">2.</span>.]
|
||||
<span class="hljs-keyword">if</span> opts.transpile
|
||||
transpile = {}
|
||||
<span class="hljs-keyword">try</span>
|
||||
transpile.transpile = <span class="hljs-built_in">require</span>(<span class="hljs-string">'@babel/core'</span>).transform
|
||||
transpile.transpile = <span class="hljs-built_in">require</span>(<span class="hljs-string">'@babel/core'</span>).transform
|
||||
<span class="hljs-keyword">catch</span>
|
||||
<span class="hljs-keyword">try</span>
|
||||
transpile.transpile = <span class="hljs-built_in">require</span>(<span class="hljs-string">'babel-core'</span>).transform
|
||||
transpile.transpile = <span class="hljs-built_in">require</span>(<span class="hljs-string">'babel-core'</span>).transform
|
||||
<span class="hljs-keyword">catch</span>
|
||||
<span class="hljs-built_in">console</span>.error <span class="hljs-string">'''
|
||||
console.error <span class="hljs-string">'''
|
||||
To use --transpile with an interactive REPL, @babel/core must be installed either in the current folder or globally:
|
||||
npm install --save-dev @babel/core
|
||||
or
|
||||
npm install --global @babel/core
|
||||
And you must save options to configure Babel in one of the places it looks to find its options.
|
||||
See https://coffeescript.org/#transpilation
|
||||
'''</span>
|
||||
'''</span>
|
||||
process.exit <span class="hljs-number">1</span>
|
||||
transpile.options =
|
||||
filename: path.resolve process.cwd(), <span class="hljs-string">'<repl>'</span></pre></div></div>
|
||||
filename: path.resolve process.cwd(), <span class="hljs-string">'<repl>'</span></pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -724,8 +724,8 @@ undeclared variable <code>__</code>.</p>
|
||||
<li id="section-33">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-33">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-33">§</a>
|
||||
</div>
|
||||
<p>Since the REPL compilation path is unique (in <code>eval</code> above), we need
|
||||
another way to get the <code>options</code> object attached to a module so that
|
||||
@@ -734,15 +734,15 @@ the REPL, the only applicable option is <code>transpile</code>.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> Module = <span class="hljs-built_in">require</span> <span class="hljs-string">'module'</span>
|
||||
<div class="content"><div class='highlight'><pre> Module = <span class="hljs-built_in">require</span> <span class="hljs-string">'module'</span>
|
||||
originalModuleLoad = Module::load
|
||||
Module::load = <span class="hljs-function"><span class="hljs-params">(filename)</span> -></span>
|
||||
@options = transpile: transpile.options
|
||||
originalModuleLoad.call @, filename
|
||||
opts = merge replDefaults, opts
|
||||
repl = nodeREPL.start opts
|
||||
runInContext opts.prelude, repl.context, <span class="hljs-string">'prelude'</span> <span class="hljs-keyword">if</span> opts.prelude
|
||||
repl.<span class="hljs-literal">on</span> <span class="hljs-string">'exit'</span>, <span class="hljs-function">-></span> repl.outputStream.write <span class="hljs-string">'\n'</span> <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> repl.rli.closed
|
||||
runInContext opts.prelude, repl.context, <span class="hljs-string">'prelude'</span> <span class="hljs-keyword">if</span> opts.prelude
|
||||
repl.<span class="hljs-literal">on</span> <span class="hljs-string">'exit'</span>, <span class="hljs-function">-></span> repl.outputStream.write <span class="hljs-string">'\n'</span> <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> repl.closed
|
||||
addMultilineHandler repl
|
||||
addHistory repl, opts.historyFile, opts.historyMaxInputSize <span class="hljs-keyword">if</span> opts.historyFile</pre></div></div>
|
||||
|
||||
@@ -752,14 +752,14 @@ the REPL, the only applicable option is <code>transpile</code>.</p>
|
||||
<li id="section-34">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-34">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-34">§</a>
|
||||
</div>
|
||||
<p>Adapt help inherited from the node REPL</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> repl.commands[getCommandId(repl, <span class="hljs-string">'load'</span>)].help = <span class="hljs-string">'Load code from a file into this REPL session'</span>
|
||||
<div class="content"><div class='highlight'><pre> repl.commands[getCommandId(repl, <span class="hljs-string">'load'</span>)].help = <span class="hljs-string">'Load code from a file into this REPL session'</span>
|
||||
repl</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -112,8 +112,8 @@
|
||||
<li id="section-1">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-1">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-1">§</a>
|
||||
</div>
|
||||
<p>The <strong>Scope</strong> class regulates lexical scoping within CoffeeScript. As you
|
||||
generate code, you create a tree of scopes in the same shape as the nested
|
||||
@@ -124,7 +124,7 @@ with external scopes.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre>exports.Scope = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Scope</span></span></pre></div></div>
|
||||
<div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.Scope = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Scope</span></span></pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -132,8 +132,8 @@ with external scopes.</p>
|
||||
<li id="section-2">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-2">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-2">§</a>
|
||||
</div>
|
||||
<p>Initialize a scope with its parent, for lookups up the chain,
|
||||
as well as a reference to the <strong>Block</strong> node it belongs to, which is
|
||||
@@ -145,7 +145,7 @@ that should be output as part of variable declarations.</p>
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> constructor: <span class="hljs-function"><span class="hljs-params">(@parent, @expressions, @method, @referencedVars)</span> -></span>
|
||||
@variables = [{name: <span class="hljs-string">'arguments'</span>, type: <span class="hljs-string">'arguments'</span>}]
|
||||
@variables = [{name: <span class="hljs-string">'arguments'</span>, type: <span class="hljs-string">'arguments'</span>}]
|
||||
@comments = {}
|
||||
@positions = {}
|
||||
@utilities = {} <span class="hljs-keyword">unless</span> @parent</pre></div></div>
|
||||
@@ -156,14 +156,14 @@ that should be output as part of variable declarations.</p>
|
||||
<li id="section-3">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-3">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-3">§</a>
|
||||
</div>
|
||||
<p>The <code>@root</code> is the top-level <strong>Scope</strong> object for a given file.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> @root = @parent?.root ? <span class="hljs-keyword">this</span></pre></div></div>
|
||||
<div class="content"><div class='highlight'><pre> @root = @parent?.root ? this</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -171,8 +171,8 @@ that should be output as part of variable declarations.</p>
|
||||
<li id="section-4">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-4">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-4">§</a>
|
||||
</div>
|
||||
<p>Adds a new variable or overrides an existing one.</p>
|
||||
|
||||
@@ -191,8 +191,8 @@ that should be output as part of variable declarations.</p>
|
||||
<li id="section-5">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-5">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-5">§</a>
|
||||
</div>
|
||||
<p>When <code>super</code> is called, we need to find the name of the current method we’re
|
||||
in, so that we know how to invoke the same method of the parent class. This
|
||||
@@ -212,15 +212,15 @@ function object that has a name filled in, or bottoms out.</p>
|
||||
<li id="section-6">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-6">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-6">§</a>
|
||||
</div>
|
||||
<p>Look up a variable name in lexical scope, and declare it if it does not
|
||||
already exist.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> find: <span class="hljs-function"><span class="hljs-params">(name, type = <span class="hljs-string">'var'</span>)</span> -></span>
|
||||
<div class="content"><div class='highlight'><pre> find: <span class="hljs-function"><span class="hljs-params">(name, type = <span class="hljs-string">'var'</span>)</span> -></span>
|
||||
<span class="hljs-keyword">return</span> <span class="hljs-literal">yes</span> <span class="hljs-keyword">if</span> @check name
|
||||
@add name, type
|
||||
<span class="hljs-literal">no</span></pre></div></div>
|
||||
@@ -231,8 +231,8 @@ already exist.</p>
|
||||
<li id="section-7">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-7">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-7">§</a>
|
||||
</div>
|
||||
<p>Reserve a variable name as originating from a function parameter for this
|
||||
scope. No <code>var</code> required for internal references.</p>
|
||||
@@ -241,7 +241,7 @@ scope. No <code>var</code> required for internal references.</p>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> parameter: <span class="hljs-function"><span class="hljs-params">(name)</span> -></span>
|
||||
<span class="hljs-keyword">return</span> <span class="hljs-keyword">if</span> @shared <span class="hljs-keyword">and</span> @parent.check name, <span class="hljs-literal">yes</span>
|
||||
@add name, <span class="hljs-string">'param'</span></pre></div></div>
|
||||
@add name, <span class="hljs-string">'param'</span></pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -249,8 +249,8 @@ scope. No <code>var</code> required for internal references.</p>
|
||||
<li id="section-8">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-8">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-8">§</a>
|
||||
</div>
|
||||
<p>Just check to see if a variable has already been declared, without reserving,
|
||||
walks up to the root scope.</p>
|
||||
@@ -266,8 +266,8 @@ walks up to the root scope.</p>
|
||||
<li id="section-9">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-9">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-9">§</a>
|
||||
</div>
|
||||
<p>Generate a temporary variable name at the given index.</p>
|
||||
|
||||
@@ -276,14 +276,14 @@ walks up to the root scope.</p>
|
||||
<div class="content"><div class='highlight'><pre> temporary: <span class="hljs-function"><span class="hljs-params">(name, index, single=<span class="hljs-literal">false</span>)</span> -></span>
|
||||
<span class="hljs-keyword">if</span> single
|
||||
startCode = name.charCodeAt(<span class="hljs-number">0</span>)
|
||||
endCode = <span class="hljs-string">'z'</span>.charCodeAt(<span class="hljs-number">0</span>)
|
||||
endCode = <span class="hljs-string">'z'</span>.charCodeAt(<span class="hljs-number">0</span>)
|
||||
diff = endCode - startCode
|
||||
newCode = startCode + index % (diff + <span class="hljs-number">1</span>)
|
||||
letter = String.fromCharCode(newCode)
|
||||
letter = <span class="hljs-built_in">String</span>.fromCharCode(newCode)
|
||||
num = index <span class="hljs-regexp">//</span> (diff + <span class="hljs-number">1</span>)
|
||||
<span class="hljs-string">"<span class="hljs-subst">#{letter}</span><span class="hljs-subst">#{num <span class="hljs-keyword">or</span> <span class="hljs-string">''</span>}</span>"</span>
|
||||
<span class="hljs-string">"<span class="hljs-subst">#{letter}</span><span class="hljs-subst">#{num <span class="hljs-keyword">or</span> <span class="hljs-string">''</span>}</span>"</span>
|
||||
<span class="hljs-keyword">else</span>
|
||||
<span class="hljs-string">"<span class="hljs-subst">#{name}</span><span class="hljs-subst">#{index <span class="hljs-keyword">or</span> <span class="hljs-string">''</span>}</span>"</span></pre></div></div>
|
||||
<span class="hljs-string">"<span class="hljs-subst">#{name}</span><span class="hljs-subst">#{index <span class="hljs-keyword">or</span> <span class="hljs-string">''</span>}</span>"</span></pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -291,8 +291,8 @@ walks up to the root scope.</p>
|
||||
<li id="section-10">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-10">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-10">§</a>
|
||||
</div>
|
||||
<p>Gets the type of a variable.</p>
|
||||
|
||||
@@ -308,8 +308,8 @@ walks up to the root scope.</p>
|
||||
<li id="section-11">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-11">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-11">§</a>
|
||||
</div>
|
||||
<p>If we need to store an intermediate result, find an available name for a
|
||||
compiler-generated variable. <code>_var</code>, <code>_var2</code>, and so on…</p>
|
||||
@@ -322,7 +322,7 @@ compiler-generated variable. <code>_var</code>, <code>_var2</code>, and so on…
|
||||
temp = @temporary name, index, options.single
|
||||
<span class="hljs-keyword">break</span> <span class="hljs-keyword">unless</span> @check(temp) <span class="hljs-keyword">or</span> temp <span class="hljs-keyword">in</span> @root.referencedVars
|
||||
index++
|
||||
@add temp, <span class="hljs-string">'var'</span>, <span class="hljs-literal">yes</span> <span class="hljs-keyword">if</span> options.reserve ? <span class="hljs-literal">true</span>
|
||||
@add temp, <span class="hljs-string">'var'</span>, <span class="hljs-literal">yes</span> <span class="hljs-keyword">if</span> options.reserve ? <span class="hljs-literal">true</span>
|
||||
temp</pre></div></div>
|
||||
|
||||
</li>
|
||||
@@ -331,8 +331,8 @@ compiler-generated variable. <code>_var</code>, <code>_var2</code>, and so on…
|
||||
<li id="section-12">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-12">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-12">§</a>
|
||||
</div>
|
||||
<p>Ensure that an assignment is made at the top of this scope
|
||||
(or at the top-level scope, if requested).</p>
|
||||
@@ -349,8 +349,8 @@ compiler-generated variable. <code>_var</code>, <code>_var2</code>, and so on…
|
||||
<li id="section-13">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-13">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-13">§</a>
|
||||
</div>
|
||||
<p>Does this scope have any declared variables?</p>
|
||||
|
||||
@@ -365,15 +365,15 @@ compiler-generated variable. <code>_var</code>, <code>_var2</code>, and so on…
|
||||
<li id="section-14">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-14">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-14">§</a>
|
||||
</div>
|
||||
<p>Return the list of variables first declared in this scope.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> declaredVariables: <span class="hljs-function">-></span>
|
||||
(v.name <span class="hljs-keyword">for</span> v <span class="hljs-keyword">in</span> @variables <span class="hljs-keyword">when</span> v.type <span class="hljs-keyword">is</span> <span class="hljs-string">'var'</span>).sort()</pre></div></div>
|
||||
(v.name <span class="hljs-keyword">for</span> v <span class="hljs-keyword">in</span> @variables <span class="hljs-keyword">when</span> v.type <span class="hljs-keyword">is</span> <span class="hljs-string">'var'</span>).sort()</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -381,8 +381,8 @@ compiler-generated variable. <code>_var</code>, <code>_var2</code>, and so on…
|
||||
<li id="section-15">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-15">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-15">§</a>
|
||||
</div>
|
||||
<p>Return the list of assignments that are supposed to be made at the top
|
||||
of this scope.</p>
|
||||
@@ -390,7 +390,7 @@ of this scope.</p>
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> assignedVariables: <span class="hljs-function">-></span>
|
||||
<span class="hljs-string">"<span class="hljs-subst">#{v.name}</span> = <span class="hljs-subst">#{v.type.value}</span>"</span> <span class="hljs-keyword">for</span> v <span class="hljs-keyword">in</span> @variables <span class="hljs-keyword">when</span> v.type.assigned</pre></div></div>
|
||||
<span class="hljs-string">"<span class="hljs-subst">#{v.name}</span> = <span class="hljs-subst">#{v.type.value}</span>"</span> <span class="hljs-keyword">for</span> v <span class="hljs-keyword">in</span> @variables <span class="hljs-keyword">when</span> v.type.assigned</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
@@ -112,8 +112,8 @@
|
||||
<li id="section-1">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-1">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-1">§</a>
|
||||
</div>
|
||||
<p>Source maps allow JavaScript runtimes to match running JavaScript back to
|
||||
the original source code that corresponds to it. This can be minified
|
||||
@@ -134,8 +134,8 @@ of this information — to write out alongside the generated JavaScript.</p>
|
||||
<li id="section-2">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-2">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-2">§</a>
|
||||
</div>
|
||||
<p>A <strong>LineMap</strong> object keeps track of information about original line and column
|
||||
positions for a single line of output JavaScript code.
|
||||
@@ -161,8 +161,8 @@ positions for a single line of output JavaScript code.
|
||||
<li id="section-3">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-3">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-3">§</a>
|
||||
</div>
|
||||
<h2 id="sourcemap">SourceMap</h2>
|
||||
|
||||
@@ -174,8 +174,8 @@ positions for a single line of output JavaScript code.
|
||||
<li id="section-4">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-4">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-4">§</a>
|
||||
</div>
|
||||
<p>Maps locations in a single generated JavaScript file back to locations in
|
||||
the original CoffeeScript source file.</p>
|
||||
@@ -195,8 +195,8 @@ through the arrays of line and column buffer to produce it.</p>
|
||||
<li id="section-5">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-5">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-5">§</a>
|
||||
</div>
|
||||
<p>Adds a mapping to this SourceMap. <code>sourceLocation</code> and <code>generatedLocation</code>
|
||||
are both <code>[line, column]</code> arrays. If <code>options.noReplace</code> is true, then if there
|
||||
@@ -216,8 +216,8 @@ effect.</p>
|
||||
<li id="section-6">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-6">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-6">§</a>
|
||||
</div>
|
||||
<p>Look up the original position of a given <code>line</code> and <code>column</code> in the generated
|
||||
code.</p>
|
||||
@@ -234,10 +234,10 @@ code.</p>
|
||||
<li id="section-7">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-7">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-7">§</a>
|
||||
</div>
|
||||
<h2 id="v3-sourcemap-generation">V3 SourceMap Generation</h2>
|
||||
<h2 id="caching">Caching</h2>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -247,8 +247,45 @@ code.</p>
|
||||
<li id="section-8">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-8">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-8">§</a>
|
||||
</div>
|
||||
<p>A static source maps cache <code>filename</code>: <code>map</code>. These are used for transforming
|
||||
stack traces and are currently set in <code>CoffeeScript.compile</code> for all files
|
||||
compiled with the source maps option.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> @sourceMaps: <span class="hljs-built_in">Object</span>.create <span class="hljs-literal">null</span>
|
||||
|
||||
@registerCompiled: <span class="hljs-function"><span class="hljs-params">(filename, source, sourcemap)</span> =></span>
|
||||
<span class="hljs-keyword">if</span> sourcemap?
|
||||
@sourceMaps[filename] = sourcemap
|
||||
|
||||
@getSourceMap: <span class="hljs-function"><span class="hljs-params">(filename)</span> =></span>
|
||||
@sourceMaps[filename]</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-9">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-9">§</a>
|
||||
</div>
|
||||
<h2 id="v3-sourcemap-generation">V3 SourceMap Generation</h2>
|
||||
|
||||
</div>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-10">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-10">§</a>
|
||||
</div>
|
||||
<p>Builds up a V3 source map, returning the generated JSON as a string.
|
||||
<code>options.sourceRoot</code> may be used to specify the sourceRoot written to the source
|
||||
@@ -263,41 +300,41 @@ set “sources” and “file”, respectively.</p>
|
||||
lastSourceLine = <span class="hljs-number">0</span>
|
||||
lastSourceColumn = <span class="hljs-number">0</span>
|
||||
needComma = <span class="hljs-literal">no</span>
|
||||
buffer = <span class="hljs-string">""</span>
|
||||
buffer = <span class="hljs-string">""</span>
|
||||
|
||||
<span class="hljs-keyword">for</span> lineMap, lineNumber <span class="hljs-keyword">in</span> @lines <span class="hljs-keyword">when</span> lineMap
|
||||
<span class="hljs-keyword">for</span> mapping <span class="hljs-keyword">in</span> lineMap.columns <span class="hljs-keyword">when</span> mapping
|
||||
<span class="hljs-keyword">while</span> writingline < mapping.line
|
||||
lastColumn = <span class="hljs-number">0</span>
|
||||
needComma = <span class="hljs-literal">no</span>
|
||||
buffer += <span class="hljs-string">";"</span>
|
||||
buffer += <span class="hljs-string">";"</span>
|
||||
writingline++</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-9">
|
||||
<li id="section-11">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-9">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-11">§</a>
|
||||
</div>
|
||||
<p>Write a comma if we’ve already written a segment on this line.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> needComma
|
||||
buffer += <span class="hljs-string">","</span>
|
||||
buffer += <span class="hljs-string">","</span>
|
||||
needComma = <span class="hljs-literal">no</span></pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-10">
|
||||
<li id="section-12">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-10">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-12">§</a>
|
||||
</div>
|
||||
<p>Write the next segment. Segments can be 1, 4, or 5 values. If just one, then it
|
||||
is a generated column which doesn’t match anything in the source code.</p>
|
||||
@@ -312,11 +349,11 @@ column for the current line:</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-11">
|
||||
<li id="section-13">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-11">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-13">§</a>
|
||||
</div>
|
||||
<p>The index into the list of sources:</p>
|
||||
|
||||
@@ -327,11 +364,11 @@ column for the current line:</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-12">
|
||||
<li id="section-14">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-12">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-14">§</a>
|
||||
</div>
|
||||
<p>The starting line in the original source, relative to the previous source line.</p>
|
||||
|
||||
@@ -343,11 +380,11 @@ column for the current line:</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-13">
|
||||
<li id="section-15">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-13">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-15">§</a>
|
||||
</div>
|
||||
<p>The starting column in the original source, relative to the previous column.</p>
|
||||
|
||||
@@ -360,11 +397,11 @@ column for the current line:</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-14">
|
||||
<li id="section-16">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-14">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-16">§</a>
|
||||
</div>
|
||||
<p>Produce the canonical JSON object format for a “v3” source map.</p>
|
||||
|
||||
@@ -375,12 +412,12 @@ column for the current line:</p>
|
||||
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> options.filename
|
||||
[options.filename]
|
||||
<span class="hljs-keyword">else</span>
|
||||
[<span class="hljs-string">'<anonymous>'</span>]
|
||||
[<span class="hljs-string">'<anonymous>'</span>]
|
||||
|
||||
v3 =
|
||||
version: <span class="hljs-number">3</span>
|
||||
file: options.generatedFile <span class="hljs-keyword">or</span> <span class="hljs-string">''</span>
|
||||
sourceRoot: options.sourceRoot <span class="hljs-keyword">or</span> <span class="hljs-string">''</span>
|
||||
file: options.generatedFile <span class="hljs-keyword">or</span> <span class="hljs-string">''</span>
|
||||
sourceRoot: options.sourceRoot <span class="hljs-keyword">or</span> <span class="hljs-string">''</span>
|
||||
sources: sources
|
||||
names: []
|
||||
mappings: buffer
|
||||
@@ -392,11 +429,11 @@ column for the current line:</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-15">
|
||||
<li id="section-17">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-15">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-17">§</a>
|
||||
</div>
|
||||
<h2 id="base64-vlq-encoding">Base64 VLQ Encoding</h2>
|
||||
|
||||
@@ -405,11 +442,11 @@ column for the current line:</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-16">
|
||||
<li id="section-18">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-16">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-18">§</a>
|
||||
</div>
|
||||
<p>Note that SourceMap VLQ encoding is “backwards”. MIDI-style VLQ encoding puts
|
||||
the most-significant-bit (MSB) from the original value into the MSB of the VLQ
|
||||
@@ -424,16 +461,16 @@ bits of the original value encoded into the first byte of the VLQ encoded value.
|
||||
VLQ_VALUE_MASK = VLQ_CONTINUATION_BIT - <span class="hljs-number">1</span> <span class="hljs-comment"># 0001 1111</span>
|
||||
|
||||
encodeVlq: <span class="hljs-function"><span class="hljs-params">(value)</span> -></span>
|
||||
answer = <span class="hljs-string">''</span></pre></div></div>
|
||||
answer = <span class="hljs-string">''</span></pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-17">
|
||||
<li id="section-19">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-17">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-19">§</a>
|
||||
</div>
|
||||
<p>Least significant bit represents the sign.</p>
|
||||
|
||||
@@ -444,26 +481,26 @@ bits of the original value encoded into the first byte of the VLQ encoded value.
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-18">
|
||||
<li id="section-20">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-18">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-20">§</a>
|
||||
</div>
|
||||
<p>The next bits are the actual value.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> valueToEncode = (Math.abs(value) << <span class="hljs-number">1</span>) + signBit</pre></div></div>
|
||||
<div class="content"><div class='highlight'><pre> valueToEncode = (<span class="hljs-built_in">Math</span>.abs(value) << <span class="hljs-number">1</span>) + signBit</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-19">
|
||||
<li id="section-21">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-19">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-21">§</a>
|
||||
</div>
|
||||
<p>Make sure we encode at least one character, even if valueToEncode is 0.</p>
|
||||
|
||||
@@ -480,11 +517,11 @@ bits of the original value encoded into the first byte of the VLQ encoded value.
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-20">
|
||||
<li id="section-22">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-20">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-22">§</a>
|
||||
</div>
|
||||
<h2 id="regular-base64-encoding">Regular Base64 Encoding</h2>
|
||||
|
||||
@@ -493,34 +530,34 @@ bits of the original value encoded into the first byte of the VLQ encoded value.
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-21">
|
||||
<li id="section-23">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-21">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-23">§</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> BASE64_CHARS = <span class="hljs-string">'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'</span>
|
||||
<div class="content"><div class='highlight'><pre> BASE64_CHARS = <span class="hljs-string">'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'</span>
|
||||
|
||||
encodeBase64: <span class="hljs-function"><span class="hljs-params">(value)</span> -></span>
|
||||
BASE64_CHARS[value] <span class="hljs-keyword">or</span> <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> Error <span class="hljs-string">"Cannot Base64 encode value: <span class="hljs-subst">#{value}</span>"</span></pre></div></div>
|
||||
BASE64_CHARS[value] <span class="hljs-keyword">or</span> <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span> <span class="hljs-string">"Cannot Base64 encode value: <span class="hljs-subst">#{value}</span>"</span></pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-22">
|
||||
<li id="section-24">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-22">¶</a>
|
||||
<div class="sswrap ">
|
||||
<a class="ss" href="#section-24">§</a>
|
||||
</div>
|
||||
<p>Our API for source maps is just the <code>SourceMap</code> class.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre><span class="hljs-built_in">module</span>.exports = SourceMap</pre></div></div>
|
||||
<div class="content"><div class='highlight'><pre>module.<span class="hljs-built_in">exports</span> = SourceMap</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
8
docs/v2/browser-compiler-legacy/coffeescript.js
Normal file
8
docs/v2/browser-compiler-legacy/coffeescript.js
Normal file
File diff suppressed because one or more lines are too long
8
docs/v2/browser-compiler-modern/coffeescript.js
Normal file
8
docs/v2/browser-compiler-modern/coffeescript.js
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
17437
docs/v2/test.html
17437
docs/v2/test.html
File diff suppressed because it is too large
Load Diff
10
documentation/examples/dynamic_import.coffee
Normal file
10
documentation/examples/dynamic_import.coffee
Normal file
@@ -0,0 +1,10 @@
|
||||
# Your browser must support dynamic import to run this example.
|
||||
|
||||
do ->
|
||||
{ run } = await import('./browser-compiler-modern/coffeescript.js')
|
||||
run '''
|
||||
if 5 < new Date().getHours() < 9
|
||||
alert 'Time to make the coffee!'
|
||||
else
|
||||
alert 'Time to get some work done.'
|
||||
'''
|
||||
@@ -1,5 +1,5 @@
|
||||
import 'local-file.coffee'
|
||||
import 'coffeescript'
|
||||
import './local-file.js' # Must be the filename of the generated file
|
||||
import 'package'
|
||||
|
||||
import _ from 'underscore'
|
||||
import * as underscore from 'underscore'
|
||||
@@ -9,6 +9,8 @@ import { now as currentTimestamp } from 'underscore'
|
||||
import { first, last } from 'underscore'
|
||||
import utilityBelt, { each } from 'underscore'
|
||||
|
||||
import dates from './calendar.json' assert { type: 'json' }
|
||||
|
||||
export default Math
|
||||
export square = (x) -> x * x
|
||||
export class Mathematics
|
||||
@@ -20,3 +22,4 @@ export { Mathematics as default, sqrt as squareRoot }
|
||||
|
||||
export * from 'underscore'
|
||||
export { max, min } from 'underscore'
|
||||
export { version } from './package.json' assert { type: 'json' }
|
||||
|
||||
@@ -3,4 +3,4 @@ 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/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.
|
||||
`/v<%= majorVersion %>/browser-compiler-legacy/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.
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
releaseHeader('2017-09-02', '2.0.0-beta5', '2.0.0-beta4')
|
||||
```
|
||||
|
||||
* Node 6 is now supported, and we will try to maintain that as the minimum required version for CoffeeScript 2 via the `coffee` command or Node API. Older versions of Node, or non-evergreen browsers, can compile via the [browser compiler](./browser-compiler/coffeescript.js).
|
||||
* Node 6 is now supported, and we will try to maintain that as the minimum required version for CoffeeScript 2 via the `coffee` command or Node API. Older versions of Node, or non-evergreen browsers, can compile via the [legacy browser compiler](./browser-compiler-legacy/coffeescript.js).
|
||||
* The command line `--output` flag now allows you to specify an output filename, not just an output folder.
|
||||
* The command line `--require` flag now properly handles filenames or module names that are invalid identifiers (like an NPM module with a hyphen in the name).
|
||||
* `Object.assign`, output when object destructuring is used, is polyfilled using the same polyfill that Babel outputs. This means that polyfills shouldn’t be required unless support for Internet Explorer 8 or below is desired (or your own code uses a feature that requires a polyfill). See [ES2015+ Output](#es2015plus-output).
|
||||
|
||||
8
documentation/sections/changelog/2.4.0.md
Normal file
8
documentation/sections/changelog/2.4.0.md
Normal file
@@ -0,0 +1,8 @@
|
||||
```
|
||||
releaseHeader('2019-03-29', '2.4.0', '2.3.2')
|
||||
```
|
||||
|
||||
* Dynamic `import()` expressions are now supported. The parentheses are always required, to distinguish from `import` statements. See [Modules](#dynamic-import). Note that as of this writing, the JavaScript feature itself is still Stage 3; if it changes before being fully standardized, it may change in CoffeeScript too. Using `import()` before its upstream [ECMAScript proposal](https://github.com/tc39/proposal-dynamic-import) is finalized should be considered provisional, subject to breaking changes if the proposal changes or is rejected. We have also revised our [policy](#contributing) on Stage 3 ECMAScript features, to support them when the features are [shipped](https://caniuse.com/#feat=es6-module-dynamic-import) in significant runtimes such as major browsers or Node.js.
|
||||
* There are now two browser versions of the CoffeeScript compiler: the traditional one that’s been published for years, and a new [ES module version](/browser-compiler-modern/coffeescript.js) that can be used via `import`. If your browser supports it, it is in effect on this page. A reference to the ES module browser compiler is in the `package.json` `"module"` field.
|
||||
* The Node API now exposes the previously private `registerCompiled` method, to allow plugins that use the `coffeescript` package to take advantage of CoffeeScript’s internal caching.
|
||||
* Bugfixes for commas in strings in block arrays, a reference to `@` not being maintained in a `do` block in a class, and function default parameters should no longer be wrapped by extraneous parentheses.
|
||||
5
documentation/sections/changelog/2.4.1.md
Normal file
5
documentation/sections/changelog/2.4.1.md
Normal file
@@ -0,0 +1,5 @@
|
||||
```
|
||||
releaseHeader('2019-04-08', '2.4.1', '2.4.0')
|
||||
```
|
||||
|
||||
* Both the [traditional ES5](/browser-compiler-legacy/coffeescript.js) and [modern ES module](/browser-compiler-modern/coffeescript.js) versions of the CoffeeScript browser compiler are now published to NPM, enabling the browser compilers’ use via services that provide NPM modules’ code available via public CDN. The traditional version is referenced via the `package.json` `"browser"` field, and the ES module version via the `"module"` field.
|
||||
11
documentation/sections/changelog/2.5.0.md
Normal file
11
documentation/sections/changelog/2.5.0.md
Normal file
@@ -0,0 +1,11 @@
|
||||
```
|
||||
releaseHeader('2019-12-31', '2.5.0', '2.4.1')
|
||||
```
|
||||
|
||||
* The compiler now supports a new `ast` option, available via `--ast` on the command line or `ast` via the Node API. This option outputs an “abstract syntax tree,” or a JSON-like representation of the input CoffeeScript source code. This AST follows [Babel’s spec](https://github.com/babel/babel/blob/master/packages/babel-parser/ast/spec.md) as closely as possible, for compatibility with tools that work with JavaScript source code. Two tools that use this new AST output are [`eslint-plugin-coffee`](https://github.com/helixbass/eslint-plugin-coffee), a plugin to lint CoffeeScript via [ESLint](https://eslint.org/); and [`prettier-plugin-coffeescript`](https://github.com/helixbass/prettier-plugin-coffeescript), a plugin to reformat CoffeeScript source code via [Prettier](https://prettier.io/). _The structure and properties of CoffeeScript’s AST are not final and may undergo breaking changes between CoffeeScript versions; please [open an issue](https://github.com/jashkenas/coffeescript/issues) if you are interested in creating new integrations._
|
||||
* [Numeric separators](https://github.com/tc39/proposal-numeric-separator) are now supported in CoffeeScript, following the same syntax as JavaScript: `1_234_567`.
|
||||
* [`BigInt` numbers](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt) are now supported in CoffeeScript, following the same syntax as JavaScript: `42n`.
|
||||
* `'''` and `"""` strings are now output as more readable JavaScript template literals, or backtick (`` ` ``) strings, with actual newlines rather than `\n` escape sequences.
|
||||
* Classes can now contain computed properties, e.g. `[someVar]: ->` or `@[anotherVar]: ->`.
|
||||
* JSX tags can now contain XML-style namespaces, e.g. `<image xlink:href="data:image/png" />` or `<Something:Tag></Something:Tag>`.
|
||||
* Bugfixes for comments after colons not appearing the output; reserved words mistakenly being disallowed as JSX attributes; indented leading elisions in multiline arrays; and invalid location data in source maps.
|
||||
7
documentation/sections/changelog/2.5.1.md
Normal file
7
documentation/sections/changelog/2.5.1.md
Normal file
@@ -0,0 +1,7 @@
|
||||
```
|
||||
releaseHeader('2020-01-31', '2.5.1', '2.5.0')
|
||||
```
|
||||
|
||||
* Object splats can now include prototype shorthands, such as `a = {b::c...}`; and soaks, such as `a = {b?.c..., d?()...}`.
|
||||
* Bugfix for regression in 2.5.0 where compilation became much slower for files with Windows-style line endings.
|
||||
* Bugfix for an implicit object after a line continuation keyword like `or` inside a larger implicit object.
|
||||
7
documentation/sections/changelog/2.6.0.md
Normal file
7
documentation/sections/changelog/2.6.0.md
Normal file
@@ -0,0 +1,7 @@
|
||||
```
|
||||
releaseHeader('2021-09-19', '2.6.0', '2.5.1')
|
||||
```
|
||||
|
||||
* The syntax `import.meta`, including `import.meta.url`, is now supported.
|
||||
* The `await` keyword is now supported outside of functions (in other words, at the top level). [Note that JavaScript runtimes only support this for ES modules.](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await#top_level_await)
|
||||
* Bugfix for a `for` comprehension at the end of an `unless` or `until` line.
|
||||
6
documentation/sections/changelog/2.6.1.md
Normal file
6
documentation/sections/changelog/2.6.1.md
Normal file
@@ -0,0 +1,6 @@
|
||||
```
|
||||
releaseHeader('2021-10-03', '2.6.1', '2.6.0')
|
||||
```
|
||||
|
||||
* The `coffeescript` package itself now supports named exports when used by ES modules in Node.js; or in other words, `import { compile } from 'coffeescript'` now works, rather than only `import CoffeeScript from 'coffeescript'`.
|
||||
* Bugfix for a stack overflow error when compiling large files in non-bare mode.
|
||||
8
documentation/sections/changelog/2.7.0.md
Normal file
8
documentation/sections/changelog/2.7.0.md
Normal file
@@ -0,0 +1,8 @@
|
||||
```
|
||||
releaseHeader('2022-04-23', '2.7.0', '2.6.1')
|
||||
```
|
||||
|
||||
* The [import assertions syntax](https://github.com/tc39/proposal-import-assertions) is now supported. This allows statements like `export { version } from './package.json' assert { type: 'json' }` or expressions like `import('./calendar.json', { assert { type: 'json' } })`.
|
||||
* CoffeeScript no longer always patches Node’s error stack traces. This patching, where the line and column numbers are adjusted to match the source CoffeeScript rather than the generated JavaScript, caused conflicts with other libraries and is unnecessary when Node’s new [`--enable-source-maps` flag](https://nodejs.org/docs/latest/api/cli.html#--enable-source-maps) is passed. The patching will now occur only when `--enable-source-maps` is not set, no other library has already patched the stack traces, and `require('coffeescript/register')` is used. The patching can be enabled explicitly via `require('coffeescript').patchStackTrace()` or `import { patchStackTrace } from 'coffeescript'; patchStackTrace()`.
|
||||
* Bugfix for an issue where block (triple-quoted) strings weren’t getting transpiled correctly into a JSX expression container wrapping the template literal (such as ``<div a={`...`} />``).
|
||||
* Bugfixes for line continuations not behaving as expected for a nonempty first line of an explicit `[` array or `{` object literal.
|
||||
@@ -12,13 +12,14 @@ Once installed, you should have access to the `coffee` command, which can execut
|
||||
| `-o, --output [DIR]` | Write out all compiled JavaScript files into the specified directory. Use in conjunction with `--compile` or `--watch`. |
|
||||
| `-w, --watch` | Watch files for changes, rerunning the specified command when any file is updated. |
|
||||
| `-p, --print` | Instead of writing out the JavaScript as a file, print it directly to **stdout**. |
|
||||
| `-s, --stdio` | Pipe in CoffeeScript to STDIN and get back JavaScript over STDOUT. Good for use with processes written in other languages. An example:<br>`cat src/cake.coffee | coffee -sc` |
|
||||
| `-s, --stdio` | Pipe in CoffeeScript to STDIN and get back JavaScript over STDOUT. Good for use with processes written in other languages. An example:<br><code>cat src/cake.coffee | coffee -sc</code> |
|
||||
| `-l, --literate` | Parses the code as Literate CoffeeScript. You only need to specify this when passing in code directly over **stdio**, or using some sort of extension-less file name. |
|
||||
| `-e, --eval` | Compile and print a little snippet of CoffeeScript directly from the command line. For example:<br>`coffee -e "console.log num for num in [10..1]"` |
|
||||
| `-r, --require [MODULE]`  | `require()` the given module before starting the REPL or evaluating the code given with the `--eval` flag. |
|
||||
| `-b, --bare` | Compile the JavaScript without the [top-level function safety wrapper](#lexical-scope). |
|
||||
| `--no-header` | Suppress the “Generated by CoffeeScript” header. |
|
||||
| `--nodejs` | The `node` executable has some useful options you can set, such as `--debug`, `--debug-brk`, `--max-stack-size`, and `--expose-gc`. Use this flag to forward options directly to Node.js. To pass multiple flags, use `--nodejs` multiple times. |
|
||||
| `--ast` | Generate an abstract syntax tree of nodes of the CoffeeScript. Used for integrating with JavaScript build tools. |
|
||||
| `--tokens` | Instead of parsing the CoffeeScript, just lex it, and print out the token stream. Used for debugging the compiler. |
|
||||
| `-n, --nodes` | Instead of compiling the CoffeeScript, just lex and parse it, and print out the parse tree. Used for debugging the compiler. |
|
||||
|
||||
|
||||
@@ -2,9 +2,12 @@
|
||||
|
||||
Most modern JavaScript features that CoffeeScript supports can run natively in Node 7.6+, meaning that Node can run CoffeeScript’s output without any further processing required. Here are some notable exceptions:
|
||||
|
||||
* [Modules](#modules) and [JSX](#jsx) always require transpilation.
|
||||
* [JSX](#jsx) always requires transpilation.
|
||||
* [Splats, a.k.a. object rest/spread syntax, for objects](https://coffeescript.org/#splats) are supported by Node 8.6+.
|
||||
* The [regular expression `s` (dotall) flag](https://github.com/tc39/proposal-regexp-dotall-flag) is supported by Node 9+.
|
||||
* [Async generator functions](https://github.com/tc39/proposal-async-iteration) are supported by Node 10+.
|
||||
* [Modules](#modules) are supported by Node 12+ with `"type": "module"` in your project’s `package.json`.
|
||||
|
||||
This list may be incomplete, and excludes versions of Node that support newer features behind flags; please refer to [node.green](http://node.green/) for full details. You can [run the tests in your browser](test.html) to see what your browser supports. It is your responsibility to ensure that your runtime supports the modern features you use; or that you [transpile](#transpilation) your code. When in doubt, transpile.
|
||||
|
||||
For compatibility with other JavaScript frameworks and tools, see [Integrations](#integrations).
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
Contributions are welcome! Feel free to fork [the repo](https://github.com/jashkenas/coffeescript) and submit a pull request.
|
||||
|
||||
[Some features of ECMAScript are intentionally unsupported](#unsupported). Please review both the open and closed [issues on GitHub](https://github.com/jashkenas/coffeescript/issues) to see if the feature you’re looking for has already been discussed. As a general rule, we don’t support ECMAScript syntax for features that aren’t yet finalized (at Stage 4 in the proposal approval process).
|
||||
[Some features of ECMAScript are intentionally unsupported](#unsupported). Please review both the open and closed [issues on GitHub](https://github.com/jashkenas/coffeescript/issues) to see if the feature you’re looking for has already been discussed. As a general rule, we don’t support ECMAScript syntax for features that aren’t yet finalized (at Stage 4 in the [proposal approval process](https://github.com/tc39/proposals)) or implemented in major browsers and/or Node (which can sometimes happen for features in Stage 3). Any Stage 3 features that CoffeeScript chooses to support should be considered experimental, subject to breaking changes or removal until the feature reaches Stage 4.
|
||||
|
||||
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).
|
||||
|
||||
@@ -10,7 +10,7 @@ There are several things you can do to increase your odds of having your pull re
|
||||
|
||||
* 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.
|
||||
* Ensure any ECMAScript syntax is mature (at Stage 4, or at Stage 3 with support in major browsers or runtimes).
|
||||
* 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,6 +1,6 @@
|
||||
## Installation
|
||||
|
||||
The command-line version of `coffee` is available as a [Node.js](https://nodejs.org/) utility, requiring Node 6 or later. The [core compiler](/v<%= majorVersion %>/browser-compiler/coffeescript.js) however, does not depend on Node, and can be run in any JavaScript environment, or in the browser (see [Try CoffeeScript](#try)).
|
||||
The command-line version of `coffee` is available as a [Node.js](https://nodejs.org/) utility, requiring Node 6 or later. The [core compiler](/v<%= majorVersion %>/browser-compiler-modern/coffeescript.js) however, does not depend on Node, and can be run in any JavaScript environment, or in the browser (see [Try CoffeeScript](#try)).
|
||||
|
||||
To install, first make sure you have a working copy of the latest stable version of [Node.js](https://nodejs.org/). You can then install CoffeeScript globally with [npm](https://www.npmjs.com/):
|
||||
|
||||
|
||||
3
documentation/sections/integrations.md
Normal file
3
documentation/sections/integrations.md
Normal file
@@ -0,0 +1,3 @@
|
||||
## Integrations
|
||||
|
||||
CoffeeScript is part of the vast JavaScript ecosystem, and many libraries help integrate CoffeeScript with JavaScript. Major projects, especially projects updated to work with CoffeeScript 2, are listed here; more can be found in the [wiki pages](https://github.com/jashkenas/coffeescript/wiki). If there’s a project that you feel should be added to this section, please open an issue or [pull request](https://github.com/jashkenas/coffeescript/wiki/%5BHowTo%5D-Update-the-docs). Projects are listed in alphabetical order by category.
|
||||
13
documentation/sections/integrations_build_tools.md
Normal file
13
documentation/sections/integrations_build_tools.md
Normal file
@@ -0,0 +1,13 @@
|
||||
### Build Tools
|
||||
|
||||
* [Browserify](http://browserify.org) with [coffeeify](https://github.com/jnordberg/coffeeify)
|
||||
|
||||
* [Grunt](https://gruntjs.com) with [grunt-contrib-coffee](https://github.com/gruntjs/grunt-contrib-coffee)
|
||||
|
||||
* [Gulp](https://gulpjs.com) with [gulp-coffee](https://github.com/gulp-community/gulp-coffee)
|
||||
|
||||
* [Parcel](https://parceljs.org) with [transformer-coffeescript](https://github.com/parcel-bundler/parcel/tree/v2/packages/transformers/coffeescript)
|
||||
|
||||
* [Rollup](https://rollupjs.org) with [rollup-plugin-coffee-script](https://github.com/lautis/rollup-plugin-coffee-script)
|
||||
|
||||
* [Webpack](https://webpack.js.org) with [coffee-loader](https://github.com/webpack-contrib/coffee-loader)
|
||||
7
documentation/sections/integrations_code_editors.md
Normal file
7
documentation/sections/integrations_code_editors.md
Normal file
@@ -0,0 +1,7 @@
|
||||
### Code Editors
|
||||
|
||||
* [Atom](https://atom.io) [packages](https://atom.io/packages/search?q=coffeescript)
|
||||
|
||||
* [Sublime Text](https://sublimetext.com) [packages](https://packagecontrol.io/search/coffeescript)
|
||||
|
||||
* [Visual Studio Code](https://code.visualstudio.com) [extensions](https://marketplace.visualstudio.com/search?target=VSCode&term=coffeescript)
|
||||
6
documentation/sections/integrations_frameworks.md
Normal file
6
documentation/sections/integrations_frameworks.md
Normal file
@@ -0,0 +1,6 @@
|
||||
### Frameworks
|
||||
|
||||
* [Ember](https://emberjs.com)
|
||||
with [ember-cli-coffeescript](https://github.com/kimroen/ember-cli-coffeescript)
|
||||
|
||||
* [Meteor](https://meteor.com) with [coffeescript-compiler](https://atmospherejs.com/meteor/coffeescript-compiler)
|
||||
@@ -0,0 +1,7 @@
|
||||
### Linters and Formatting
|
||||
|
||||
* [CoffeeLint](https://coffeelint.github.io/)
|
||||
|
||||
* [ESLint](https://eslint.org) with [eslint-plugin-coffee](https://github.com/helixbass/eslint-plugin-coffee)
|
||||
|
||||
* [Prettier](https://prettier.io) with [prettier-plugin-coffeescript](https://github.com/helixbass/prettier-plugin-coffeescript)
|
||||
3
documentation/sections/integrations_testing.md
Normal file
3
documentation/sections/integrations_testing.md
Normal file
@@ -0,0 +1,3 @@
|
||||
### Testing
|
||||
|
||||
* [Jest](https://jestjs.io) with [jest-preset-coffeescript](https://github.com/danielbayley/jest-preset-coffeescript)
|
||||
@@ -4,7 +4,7 @@ _This reference is structured so that it can be read from top to bottom, if you
|
||||
|
||||
_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.
|
||||
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-catch), use indentation.
|
||||
|
||||
You don’t need to use parentheses to invoke a function if you’re passing arguments. The implicit call wraps forward to the end of the line or block expression.<br>
|
||||
`console.log sys.inspect object` → `console.log(sys.inspect(object));`
|
||||
|
||||
@@ -1,13 +1,21 @@
|
||||
## Modules
|
||||
|
||||
ES2015 modules are supported in CoffeeScript, with very similar `import` and `export` syntax:
|
||||
[ES2015 modules](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules) are supported in CoffeeScript, with very similar `import` and `export` syntax:
|
||||
|
||||
```
|
||||
codeFor('modules')
|
||||
```
|
||||
|
||||
<div id="dynamic-import" class="bookmark"></div>
|
||||
|
||||
[Dynamic import](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import#Dynamic_Imports) is also supported, with mandatory parentheses:
|
||||
|
||||
```
|
||||
codeFor('dynamic_import', true)
|
||||
```
|
||||
|
||||
<div id="modules-note" class="bookmark"></div>
|
||||
|
||||
Note that the CoffeeScript compiler **does not resolve modules**; writing an `import` or `export` statement in CoffeeScript will produce an `import` or `export` statement in the resulting output. It is your responsibility to [transpile](#transpilation) this ES2015 syntax into code that will work in your target runtimes.
|
||||
Note that the CoffeeScript compiler **does not resolve modules**; writing an `import` or `export` statement in CoffeeScript will produce an `import` or `export` statement in the resulting output. Such statements can be run by all modern browsers (when the script is referenced via `<script type="module">`) and [by Node.js](https://nodejs.org/api/esm.html#esm_enabling) when the output `.js` files are in a folder where the nearest parent `package.json` file contains `"type": "module"`. Because the runtime is evaluating the generated output, the `import` statements must reference the output files; so if `file.coffee` is output as `file.js`, it needs to be referenced as `file.js` in the `import` statement, with the `.js` extension included.
|
||||
|
||||
Also note that any file with an `import` or `export` statement will be output without a [top-level function safety wrapper](#lexical-scope); in other words, importing or exporting modules will automatically trigger [bare](#usage) mode for that file. This is because per the ES2015 spec, `import` or `export` statements must occur at the topmost scope.
|
||||
Also, any file with an `import` or `export` statement will be output without a [top-level function safety wrapper](#lexical-scope); in other words, importing or exporting modules will automatically trigger [bare](#usage) mode for that file. This is because per the ES2015 spec, `import` or `export` statements must occur at the topmost scope.
|
||||
|
||||
@@ -23,4 +23,5 @@ The `compile` method has the signature `compile(code, options)` where `code` is
|
||||
* `options.filename`, string: the filename to use for the source map. It can include a path (relative or absolute).
|
||||
* `options.bare`, boolean: if true, output without the [top-level function safety wrapper](#lexical-scope).
|
||||
* `options.header`, boolean: if true, output the `Generated by CoffeeScript` header.
|
||||
* `options.transpile`, **object**: if set, this must be an object with the [options to pass to Babel](http://babeljs.io/docs/usage/api/#options). See [Transpilation](#transpilation).
|
||||
* `options.transpile`, **object**: if set, this must be an object with the [options to pass to Babel](http://babeljs.io/docs/usage/api/#options). See [Transpilation](#transpilation).
|
||||
* `options.ast`, boolean: if true, return an abstract syntax tree of the input CoffeeScript source code.
|
||||
|
||||
@@ -6,7 +6,7 @@ The CoffeeScript literals for objects and arrays look very similar to their Java
|
||||
codeFor('objects_and_arrays', 'song.join(" … ")')
|
||||
```
|
||||
|
||||
CoffeeScript has a shortcut for creating objects when you want the key to be set with a variable of the same name.
|
||||
CoffeeScript has a shortcut for creating objects when you want the key to be set with a variable of the same name. Note that the `{` and `}` are required for this shorthand.
|
||||
|
||||
```
|
||||
codeFor('objects_shorthand')
|
||||
|
||||
@@ -32,7 +32,7 @@ All together now:
|
||||
| `isnt` | `!==` |
|
||||
| `not` | `!` |
|
||||
| `and` | `&&` |
|
||||
| `or` | `||` |
|
||||
| `or` | <code>||</code> |
|
||||
| `true`, `yes`, `on` | `true` |
|
||||
| `false`, `no`, `off`  | `false` |
|
||||
| `@`, `this` | `this` |
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* [CoffeeScript Google Group](https://groups.google.com/forum/#!forum/coffeescript)<br>
|
||||
If you’d like to ask a question, the mailing list is a good place to get help.
|
||||
* [The CoffeeScript Wiki](https://github.com/jashkenas/coffeescript/wiki)<br>
|
||||
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](https://github.com/jashkenas/coffeescript/wiki/Text-editor-plugins), [web framework plugins](https://github.com/jashkenas/coffeescript/wiki/Web-framework-plugins), and general [CoffeeScript build tools](https://github.com/jashkenas/coffeescript/wiki/Build-tools).
|
||||
If you’ve ever learned a neat CoffeeScript tip or trick, or ran into a gotcha — share it on the wiki.
|
||||
* [The FAQ](https://github.com/jashkenas/coffeescript/wiki/FAQ)<br>
|
||||
Perhaps your CoffeeScript-related question has been asked before. Check the FAQ first.
|
||||
* [JS2Coffee](http://js2.coffee/)<br>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
## `"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/coffeescript.js)) as `docs/v<%= majorVersion %>/browser-compiler/coffeescript.js`. Include this file on a page with inline CoffeeScript tags, and it will compile and evaluate them in order.
|
||||
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, 77k when gzipped](/v<%= majorVersion %>/browser-compiler-legacy/coffeescript.js)) as `docs/v<%= majorVersion %>/browser-compiler-legacy/coffeescript.js`. Include this file on a page with inline CoffeeScript tags, and it will compile and evaluate them in order.
|
||||
|
||||
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,6 +1,6 @@
|
||||
### Transpilation
|
||||
|
||||
CoffeeScript 2 generates JavaScript that uses the latest, modern syntax. The runtime or browsers where you want your code to run [might not support all of that syntax](#compatibility). In that case, we want to convert modern JavaScript into older JavaScript that will run in older versions of Node or older browsers; for example, `{ a } = obj` into `a = obj.a`. This is done via transpilers like [Babel](http://babeljs.io/), [Bublé](https://buble.surge.sh/) or [Traceur Compiler](https://github.com/google/traceur-compiler).
|
||||
CoffeeScript 2 generates JavaScript that uses the latest, modern syntax. The runtime or browsers where you want your code to run [might not support all of that syntax](#compatibility). In that case, we want to convert modern JavaScript into older JavaScript that will run in older versions of Node or older browsers; for example, `{ a } = obj` into `a = obj.a`. This is done via transpilers like [Babel](http://babeljs.io/), [Bublé](https://buble.surge.sh/) or [Traceur Compiler](https://github.com/google/traceur-compiler). See [Build Tools](#build-tools).
|
||||
|
||||
#### Quickstart
|
||||
|
||||
|
||||
@@ -105,7 +105,7 @@
|
||||
<section id="switch">
|
||||
<%= htmlFor('switch') %>
|
||||
</section>
|
||||
<section id="try">
|
||||
<section id="try-catch">
|
||||
<%= htmlFor('try') %>
|
||||
</section>
|
||||
<section id="comparisons">
|
||||
@@ -142,6 +142,24 @@
|
||||
<section id="scripts">
|
||||
<%= htmlFor('scripts') %>
|
||||
</section>
|
||||
<section id="integrations">
|
||||
<%= htmlFor('integrations') %>
|
||||
<section id="build-tools">
|
||||
<%= htmlFor('integrations_build_tools') %>
|
||||
</section>
|
||||
<section id="code-editors">
|
||||
<%= htmlFor('integrations_code_editors') %>
|
||||
</section>
|
||||
<section id="frameworks">
|
||||
<%= htmlFor('integrations_frameworks') %>
|
||||
</section>
|
||||
<section id="linters-and-formatting">
|
||||
<%= htmlFor('integrations_linters_and_formatting') %>
|
||||
</section>
|
||||
<section id="testing">
|
||||
<%= htmlFor('integrations_testing') %>
|
||||
</section>
|
||||
</section>
|
||||
<section id="resources">
|
||||
<%= htmlFor('resources') %>
|
||||
<section id="books">
|
||||
@@ -207,6 +225,27 @@
|
||||
</section>
|
||||
<section id="changelog">
|
||||
<%= htmlFor('changelog') %>
|
||||
<section id="2.7.0">
|
||||
<%= htmlFor('changelog/2.7.0') %>
|
||||
</section>
|
||||
<section id="2.6.1">
|
||||
<%= htmlFor('changelog/2.6.1') %>
|
||||
</section>
|
||||
<section id="2.6.0">
|
||||
<%= htmlFor('changelog/2.6.0') %>
|
||||
</section>
|
||||
<section id="2.5.1">
|
||||
<%= htmlFor('changelog/2.5.1') %>
|
||||
</section>
|
||||
<section id="2.5.0">
|
||||
<%= htmlFor('changelog/2.5.0') %>
|
||||
</section>
|
||||
<section id="2.4.1">
|
||||
<%= htmlFor('changelog/2.4.1') %>
|
||||
</section>
|
||||
<section id="2.4.0">
|
||||
<%= htmlFor('changelog/2.4.0') %>
|
||||
</section>
|
||||
<section id="2.3.2">
|
||||
<%= htmlFor('changelog/2.3.2') %>
|
||||
</section>
|
||||
|
||||
@@ -14,6 +14,8 @@ window.gtag 'config', window.GA_TRACKING_ID
|
||||
|
||||
# Initialize the CoffeeScript docs interactions
|
||||
$(document).ready ->
|
||||
CoffeeScript.patchStackTrace()
|
||||
|
||||
# Format dates for the user’s locale, e.g. 'December 24, 2009' or '24 décembre 2009'
|
||||
$('time').each (index, el) ->
|
||||
date = el.dateTime or $(el).text()
|
||||
@@ -105,11 +107,17 @@ $(document).ready ->
|
||||
if window.localStorage?
|
||||
window.localStorage.setItem 'tryCoffeeScriptCode', coffee
|
||||
catch exception
|
||||
output = CoffeeScript.compile coffee, bare: yes
|
||||
|
||||
js = CoffeeScript.compile coffee, bare: yes, inlineMap: true
|
||||
# Inline map is added to adjust stack trace line numbers but we strip it from the displayed JS for visual clarity.
|
||||
output = js.replace /(\n\/\/# [^\n]*){2}$/, ""
|
||||
lastCompilationElapsedTime = Math.max(200, Date.now() - lastCompilationStartTime)
|
||||
catch exception
|
||||
output = "#{exception}"
|
||||
|
||||
editors[index + 1].js = js
|
||||
editors[index + 1].setValue output
|
||||
|
||||
gtag 'event', 'edit_code',
|
||||
event_category: 'engagement'
|
||||
event_label: $textarea.closest('[data-example]').data('example')
|
||||
@@ -149,7 +157,7 @@ $(document).ready ->
|
||||
run = $(@).data 'run'
|
||||
index = $("##{$(@).data('example')}-js").data 'index'
|
||||
js = if editors[index]?
|
||||
editors[index].getValue()
|
||||
editors[index].js
|
||||
else
|
||||
$(textareas[index]).val()
|
||||
js = "#{js}\nalert(#{unescape run});" unless run is yes
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
<div class="navbar-nav mr-auto d-none d-lg-flex">
|
||||
<a href="#try" id="try-link" class="nav-item nav-link" data-toggle="try">Try CoffeeScript</a>
|
||||
<a href="#language" class="nav-item nav-link" data-close="try">Language Reference</a>
|
||||
<a href="#integrations" class="nav-item nav-link" data-close="try">Integrations</a>
|
||||
<a href="#resources" class="nav-item nav-link" data-close="try">Resources</a>
|
||||
<a href="https://github.com/jashkenas/coffeescript/" class="nav-item nav-link" data-close="try">GitHub
|
||||
</a>
|
||||
|
||||
@@ -1,9 +1,14 @@
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js" integrity="sha384-xBuQ/xzmlsLoJpyjoggmTEz8OWUFM0/RC5BsqQBDX2v5cMvDHcMakNTNrHIW2I5f" crossorigin="anonymous"></script>
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js" integrity="sha384-tsQFqpEReu7ZLhBV2VZlAu7zcOV+rXbYlF2cqB8txI/8aZajjp4Bqd+V6D5IgvKT" crossorigin="anonymous"></script>
|
||||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/js/bootstrap.min.js" integrity="sha384-uefMccjFJAIv6A+rW+L4AHf99KvxDjWSu1z9VI8SKNVmz4sk7buKt/6v9KI65qnm" crossorigin="anonymous"></script>
|
||||
<script src="https://cdn.jsdelivr.net/combine/npm/codemirror@5.37.0/lib/codemirror.js,npm/codemirror@5.37.0/mode/coffeescript/coffeescript.js,npm/codemirror@5.37.0/addon/lint/coffeescript-lint.js,npm/codemirror@5.37.0/mode/javascript/javascript.js"></script>
|
||||
|
||||
<script src="browser-compiler/coffeescript.js"></script>
|
||||
<script>
|
||||
<script nomodule src="./browser-compiler-legacy/coffeescript.js"></script>
|
||||
<script nomodule>
|
||||
<%= includeScript('docs.coffee') %>
|
||||
</script>
|
||||
<script type="module">
|
||||
import CoffeeScript from './browser-compiler-modern/coffeescript.js';
|
||||
<%= includeScript('docs.coffee') %>
|
||||
</script>
|
||||
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-106156830-1"></script>
|
||||
|
||||
@@ -36,7 +36,8 @@
|
||||
<a href="#async-functions" class="nav-link" data-action="sidebar-nav">Async Functions</a>
|
||||
<a href="#classes" class="nav-link" data-action="sidebar-nav">Classes</a>
|
||||
<a href="#prototypal-inheritance" class="nav-link" data-action="sidebar-nav">Prototypal Inheritance</a>
|
||||
<a href="#switch" class="nav-link" data-action="sidebar-nav">Switch and Try/Catch</a>
|
||||
<a href="#switch" class="nav-link" data-action="sidebar-nav">Switch/When/Else</a>
|
||||
<a href="#try-catch" class="nav-link" data-action="sidebar-nav">Try/Catch/Finally</a>
|
||||
<a href="#comparisons" class="nav-link" data-action="sidebar-nav">Chained Comparisons</a>
|
||||
<a href="#regexes" class="nav-link" data-action="sidebar-nav">Block Regular Expressions</a>
|
||||
<a href="#tagged-template-literals" class="nav-link" data-action="sidebar-nav">Tagged Template Literals</a>
|
||||
@@ -49,7 +50,14 @@
|
||||
<a href="#source-maps" class="nav-link" data-action="sidebar-nav">Source Maps</a>
|
||||
<a href="#cake" class="nav-link" data-action="sidebar-nav">Cake, and Cakefiles</a>
|
||||
<a href="#scripts" class="nav-link" data-action="sidebar-nav"><code>"text/coffeescript"</code> Script Tags</a>
|
||||
<a href="test.html" class="nav-link" data-action="sidebar-nav">Browser-Based Tests</a>
|
||||
<a href="#integrations" class="nav-link" data-action="sidebar-nav">Integrations</a>
|
||||
<nav class="nav flex-column">
|
||||
<a href="#build-tools" class="nav-link" data-action="sidebar-nav">Build Tools</a>
|
||||
<a href="#code-editors" class="nav-link" data-action="sidebar-nav">Code Editors</a>
|
||||
<a href="#frameworks" class="nav-link" data-action="sidebar-nav">Frameworks</a>
|
||||
<a href="#linters-and-formatting" class="nav-link" data-action="sidebar-nav">Linters and Formatting</a>
|
||||
<a href="#testing" class="nav-link" data-action="sidebar-nav">Testing</a>
|
||||
</nav>
|
||||
<a href="#resources" class="nav-link" data-action="sidebar-nav">Resources</a>
|
||||
<nav class="nav flex-column">
|
||||
<a href="#books" class="nav-link" data-action="sidebar-nav">Books</a>
|
||||
@@ -79,6 +87,7 @@
|
||||
<a href="#breaking-changes-argument-parsing-and-shebang-lines" class="nav-link" data-action="sidebar-nav">Argument Parsing and <code>#!</code> Lines</a>
|
||||
</nav>
|
||||
<a href="#changelog" class="nav-link" data-action="sidebar-nav">Changelog</a>
|
||||
<a href="test.html" class="nav-link" data-action="sidebar-nav">Browser-Based Tests</a>
|
||||
<a href="/v1/" class="nav-link" data-action="sidebar-nav">Version 1.x Documentation</a>
|
||||
</nav>
|
||||
</nav>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-9gVQ4dYFwwWSjIDZnLEWnxCjeSWFphJiwGPXr1jddIhOegiu1FwO5qRGvFXOdJZ4" 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 href="https://cdn.jsdelivr.net/npm/codemirror@5.37.0/lib/codemirror.css" rel="stylesheet" crossorigin="anonymous">
|
||||
<link href="https://cdn.jsdelivr.net/npm/codemirror@5.62.3/lib/codemirror.css" rel="stylesheet" crossorigin="anonymous">
|
||||
<style>
|
||||
<%= include('code.css') %>
|
||||
<%= include('docs.css') %>
|
||||
|
||||
@@ -3,7 +3,12 @@
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
|
||||
<title>CoffeeScript Test Suite</title>
|
||||
<script src="browser-compiler/coffeescript.js"></script>
|
||||
<script nomodule src="browser-compiler-legacy/coffeescript.js"></script>
|
||||
<script type="module">
|
||||
import CoffeeScript from './browser-compiler-modern/coffeescript.js';
|
||||
window.CoffeeScript = CoffeeScript;
|
||||
window.addEventListener('DOMContentLoaded', CoffeeScript.runScripts, false);
|
||||
</script>
|
||||
<script src="https://cdn.jsdelivr.net/underscorejs/1.8.3/underscore-min.js"></script>
|
||||
<style>
|
||||
body, pre {
|
||||
@@ -39,15 +44,16 @@
|
||||
<script type="text/coffeescript">
|
||||
@testingBrowser = yes
|
||||
@global = window
|
||||
bold = red = green = reset = ''
|
||||
@bold = @red = @green = @reset = ''
|
||||
stdout = document.getElementById 'stdout'
|
||||
start = new Date
|
||||
@currentFile = ''
|
||||
@passedTests = failedTests = total = done = 0
|
||||
|
||||
say = (msg, className) ->
|
||||
say = (msg, className, id) ->
|
||||
div = document.createElement 'div'
|
||||
div.className = className if className?
|
||||
div.id = id if id?
|
||||
div.appendChild document.createTextNode msg
|
||||
stdout.appendChild div
|
||||
msg
|
||||
@@ -132,7 +138,7 @@ done = ->
|
||||
sec = (new Date - start) / 1000
|
||||
msg = "passed #{passedTests} tests in #{sec.toFixed 2} seconds"
|
||||
msg = "failed #{total - passedTests} tests and #{msg}" unless yay
|
||||
say msg, (if yay then 'good' else 'bad')
|
||||
say msg, (if yay then 'good' else 'bad'), 'result'
|
||||
|
||||
gtag 'event', 'tests_complete',
|
||||
event_category: 'tests'
|
||||
|
||||
8
lib/coffeescript-browser-compiler-legacy/coffeescript.js
Normal file
8
lib/coffeescript-browser-compiler-legacy/coffeescript.js
Normal file
File diff suppressed because one or more lines are too long
8
lib/coffeescript-browser-compiler-modern/coffeescript.js
Normal file
8
lib/coffeescript-browser-compiler-modern/coffeescript.js
Normal file
File diff suppressed because one or more lines are too long
@@ -1,10 +1,10 @@
|
||||
// Generated by CoffeeScript 2.3.2
|
||||
// Generated by CoffeeScript 2.7.0
|
||||
(function() {
|
||||
// This **Browser** compatibility layer extends core CoffeeScript functions
|
||||
// to make things work smoothly when compiling code directly in the browser.
|
||||
// We add support for loading remote Coffee scripts via **XHR**, and
|
||||
// `text/coffeescript` script tags, source maps via data-URLs, and so on.
|
||||
var CoffeeScript, compile, runScripts,
|
||||
var CoffeeScript, compile,
|
||||
indexOf = [].indexOf;
|
||||
|
||||
CoffeeScript = require('./coffeescript');
|
||||
@@ -81,7 +81,7 @@
|
||||
// Activate CoffeeScript in the browser by having it compile and evaluate
|
||||
// all script tags with a content-type of `text/coffeescript`.
|
||||
// This happens on page load.
|
||||
runScripts = function() {
|
||||
CoffeeScript.runScripts = function() {
|
||||
var coffees, coffeetypes, execute, i, index, j, len, s, script, scripts;
|
||||
scripts = window.document.getElementsByTagName('script');
|
||||
coffeetypes = ['text/coffeescript', 'text/literate-coffeescript'];
|
||||
@@ -126,7 +126,7 @@
|
||||
// filename; otherwise use `coffeescript`, or `coffeescript1` etc.,
|
||||
// leaving the first one unnumbered for the common case that there’s
|
||||
// only one CoffeeScript script block to parse.
|
||||
options.filename = script.id && script.id !== '' ? script.id : `coffeescript${(i !== 0 ? i : '')}`;
|
||||
options.filename = script.id && script.id !== '' ? script.id : `coffeescript${i !== 0 ? i : ''}`;
|
||||
options.sourceFiles = ['embedded'];
|
||||
return coffees[i] = [script.innerHTML, options];
|
||||
}
|
||||
@@ -136,10 +136,16 @@
|
||||
};
|
||||
|
||||
// Listen for window load, both in decent browsers and in IE.
|
||||
if (window.addEventListener) {
|
||||
window.addEventListener('DOMContentLoaded', runScripts, false);
|
||||
} else {
|
||||
window.attachEvent('onload', runScripts);
|
||||
// Only attach this event handler on startup for the
|
||||
// non-ES module version of the browser compiler, to preserve
|
||||
// backward compatibility while letting the ES module version
|
||||
// be importable without side effects.
|
||||
if (this === window) {
|
||||
if (window.addEventListener) {
|
||||
window.addEventListener('DOMContentLoaded', CoffeeScript.runScripts, false);
|
||||
} else {
|
||||
window.attachEvent('onload', CoffeeScript.runScripts);
|
||||
}
|
||||
}
|
||||
|
||||
}).call(this);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Generated by CoffeeScript 2.3.2
|
||||
// Generated by CoffeeScript 2.7.0
|
||||
(function() {
|
||||
// `cake` is a simplified version of [Make](http://www.gnu.org/software/make/)
|
||||
// ([Rake](http://rake.rubyforge.org/), [Jake](https://github.com/280north/jake))
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
// Generated by CoffeeScript 2.3.2
|
||||
// Generated by CoffeeScript 2.7.0
|
||||
(function() {
|
||||
// CoffeeScript can be used both on the server, as a command-line compiler based
|
||||
// on Node.js/V8, or to run CoffeeScript directly in the browser. This module
|
||||
// contains the main entry functions for tokenizing, parsing, and compiling
|
||||
// source CoffeeScript into JavaScript.
|
||||
var FILE_EXTENSIONS, Lexer, SourceMap, base64encode, checkShebangLine, compile, formatSourcePosition, getSourceMap, helpers, lexer, packageJson, parser, sourceMaps, sources, withPrettyErrors,
|
||||
indexOf = [].indexOf;
|
||||
var FILE_EXTENSIONS, Lexer, SourceMap, base64encode, checkShebangLine, compile, getSourceMap, helpers, lexer, packageJson, parser, registerCompiled, withPrettyErrors;
|
||||
|
||||
({Lexer} = require('./lexer'));
|
||||
|
||||
@@ -27,6 +26,13 @@
|
||||
// Expose helpers for testing.
|
||||
exports.helpers = helpers;
|
||||
|
||||
({getSourceMap, registerCompiled} = SourceMap);
|
||||
|
||||
// This is exported to enable an external module to implement caching of
|
||||
// sourcemaps. This is used only when `patchStackTrace` has been called to adjust
|
||||
// stack traces for files with cached source maps.
|
||||
exports.registerCompiled = registerCompiled;
|
||||
|
||||
// Function that allows for btoa in both nodejs and the browser.
|
||||
base64encode = function(src) {
|
||||
switch (false) {
|
||||
@@ -62,18 +68,6 @@
|
||||
};
|
||||
};
|
||||
|
||||
// For each compiled file, save its source in memory in case we need to
|
||||
// recompile it later. We might need to recompile if the first compilation
|
||||
// didn’t create a source map (faster) but something went wrong and we need
|
||||
// a stack trace. Assuming that most of the time, code isn’t throwing
|
||||
// exceptions, it’s probably more efficient to compile twice only when we
|
||||
// need a stack trace, rather than always generating a source map even when
|
||||
// it’s not likely to be used. Save in form of `filename`: [`(source)`]
|
||||
sources = {};
|
||||
|
||||
// Also save source maps if generated, in form of `(source)`: [`(source map)`].
|
||||
sourceMaps = {};
|
||||
|
||||
// Compile CoffeeScript code to JavaScript, using the Coffee/Jison compiler.
|
||||
|
||||
// If `options.sourceMap` is specified, then `options.filename` must also be
|
||||
@@ -85,21 +79,14 @@
|
||||
// object, where sourceMap is a sourcemap.coffee#SourceMap object, handy for
|
||||
// doing programmatic lookups.
|
||||
exports.compile = compile = withPrettyErrors(function(code, options = {}) {
|
||||
var currentColumn, currentLine, encoded, filename, fragment, fragments, generateSourceMap, header, i, j, js, len, len1, map, newLines, ref, ref1, sourceMapDataURI, sourceURL, token, tokens, transpiler, transpilerOptions, transpilerOutput, v3SourceMap;
|
||||
var ast, currentColumn, currentLine, encoded, filename, fragment, fragments, generateSourceMap, header, i, j, js, len, len1, map, newLines, nodes, range, ref, sourceCodeLastLine, sourceCodeNumberOfLines, sourceMapDataURI, sourceURL, token, tokens, transpiler, transpilerOptions, transpilerOutput, v3SourceMap;
|
||||
// Clone `options`, to avoid mutating the `options` object passed in.
|
||||
options = Object.assign({}, options);
|
||||
// Always generate a source map if no filename is passed in, since without a
|
||||
// a filename we have no way to retrieve this source later in the event that
|
||||
// we need to recompile it to get a source map for `prepareStackTrace`.
|
||||
generateSourceMap = options.sourceMap || options.inlineMap || (options.filename == null);
|
||||
filename = options.filename || '<anonymous>';
|
||||
filename = options.filename || helpers.anonymousFileName();
|
||||
checkShebangLine(filename, code);
|
||||
if (sources[filename] == null) {
|
||||
sources[filename] = [];
|
||||
}
|
||||
sources[filename].push(code);
|
||||
if (generateSourceMap) {
|
||||
map = new SourceMap;
|
||||
map = new SourceMap();
|
||||
}
|
||||
tokens = lexer.tokenize(code, options);
|
||||
// Pass a list of referenced variables, so that generated variables won’t get
|
||||
@@ -125,7 +112,31 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
fragments = parser.parse(tokens).compileToFragments(options);
|
||||
nodes = parser.parse(tokens);
|
||||
// If all that was requested was a POJO representation of the nodes, e.g.
|
||||
// the abstract syntax tree (AST), we can stop now and just return that
|
||||
// (after fixing the location data for the root/`File`»`Program` node,
|
||||
// which might’ve gotten misaligned from the original source due to the
|
||||
// `clean` function in the lexer).
|
||||
if (options.ast) {
|
||||
nodes.allCommentTokens = helpers.extractAllCommentTokens(tokens);
|
||||
sourceCodeNumberOfLines = (code.match(/\r?\n/g) || '').length + 1;
|
||||
sourceCodeLastLine = /.*$/.exec(code)[0];
|
||||
ast = nodes.ast(options);
|
||||
range = [0, code.length];
|
||||
ast.start = ast.program.start = range[0];
|
||||
ast.end = ast.program.end = range[1];
|
||||
ast.range = ast.program.range = range;
|
||||
ast.loc.start = ast.program.loc.start = {
|
||||
line: 1,
|
||||
column: 0
|
||||
};
|
||||
ast.loc.end.line = ast.program.loc.end.line = sourceCodeNumberOfLines;
|
||||
ast.loc.end.column = ast.program.loc.end.column = sourceCodeLastLine.length;
|
||||
ast.tokens = tokens;
|
||||
return ast;
|
||||
}
|
||||
fragments = nodes.compileToFragments(options);
|
||||
currentLine = 0;
|
||||
if (options.header) {
|
||||
currentLine += 1;
|
||||
@@ -162,10 +173,6 @@
|
||||
}
|
||||
if (generateSourceMap) {
|
||||
v3SourceMap = map.generate(options, code);
|
||||
if (sourceMaps[filename] == null) {
|
||||
sourceMaps[filename] = [];
|
||||
}
|
||||
sourceMaps[filename].push(map);
|
||||
}
|
||||
if (options.transpile) {
|
||||
if (typeof options.transpile !== 'object') {
|
||||
@@ -193,9 +200,10 @@
|
||||
if (options.inlineMap) {
|
||||
encoded = base64encode(JSON.stringify(v3SourceMap));
|
||||
sourceMapDataURI = `//# sourceMappingURL=data:application/json;base64,${encoded}`;
|
||||
sourceURL = `//# sourceURL=${(ref1 = options.filename) != null ? ref1 : 'coffeescript'}`;
|
||||
sourceURL = `//# sourceURL=${filename}`;
|
||||
js = `${js}\n${sourceMapDataURI}\n${sourceURL}`;
|
||||
}
|
||||
registerCompiled(filename, code, map);
|
||||
if (options.sourceMap) {
|
||||
return {
|
||||
js,
|
||||
@@ -217,10 +225,9 @@
|
||||
// or traverse it by using `.traverseChildren()` with a callback.
|
||||
exports.nodes = withPrettyErrors(function(source, options) {
|
||||
if (typeof source === 'string') {
|
||||
return parser.parse(lexer.tokenize(source, options));
|
||||
} else {
|
||||
return parser.parse(source);
|
||||
source = lexer.tokenize(source, options);
|
||||
}
|
||||
return parser.parse(source);
|
||||
});
|
||||
|
||||
// This file used to export these methods; leave stubs that throw warnings
|
||||
@@ -233,12 +240,18 @@
|
||||
};
|
||||
|
||||
// Instantiate a Lexer for our use here.
|
||||
lexer = new Lexer;
|
||||
lexer = new Lexer();
|
||||
|
||||
// The real Lexer produces a generic stream of tokens. This object provides a
|
||||
// thin wrapper around it, compatible with the Jison API. We can then pass it
|
||||
// directly as a “Jison lexer.”
|
||||
parser.lexer = {
|
||||
yylloc: {
|
||||
range: []
|
||||
},
|
||||
options: {
|
||||
ranges: true
|
||||
},
|
||||
lex: function() {
|
||||
var tag, token;
|
||||
token = parser.tokens[this.pos++];
|
||||
@@ -290,110 +303,58 @@
|
||||
return helpers.throwSyntaxError(`unexpected ${errorText}`, errorLoc);
|
||||
};
|
||||
|
||||
// Based on http://v8.googlecode.com/svn/branches/bleeding_edge/src/messages.js
|
||||
// Modified to handle sourceMap
|
||||
formatSourcePosition = function(frame, getSourceMapping) {
|
||||
var as, column, fileLocation, filename, functionName, isConstructor, isMethodCall, line, methodName, source, tp, typeName;
|
||||
filename = void 0;
|
||||
fileLocation = '';
|
||||
if (frame.isNative()) {
|
||||
fileLocation = "native";
|
||||
} else {
|
||||
if (frame.isEval()) {
|
||||
filename = frame.getScriptNameOrSourceURL();
|
||||
if (!filename) {
|
||||
fileLocation = `${frame.getEvalOrigin()}, `;
|
||||
}
|
||||
exports.patchStackTrace = function() {
|
||||
var formatSourcePosition, getSourceMapping;
|
||||
// Based on http://v8.googlecode.com/svn/branches/bleeding_edge/src/messages.js
|
||||
// Modified to handle sourceMap
|
||||
formatSourcePosition = function(frame, getSourceMapping) {
|
||||
var as, column, fileLocation, filename, functionName, isConstructor, isMethodCall, line, methodName, source, tp, typeName;
|
||||
filename = void 0;
|
||||
fileLocation = '';
|
||||
if (frame.isNative()) {
|
||||
fileLocation = "native";
|
||||
} else {
|
||||
filename = frame.getFileName();
|
||||
if (frame.isEval()) {
|
||||
filename = frame.getScriptNameOrSourceURL();
|
||||
if (!filename) {
|
||||
fileLocation = `${frame.getEvalOrigin()}, `;
|
||||
}
|
||||
} else {
|
||||
filename = frame.getFileName();
|
||||
}
|
||||
filename || (filename = "<anonymous>");
|
||||
line = frame.getLineNumber();
|
||||
column = frame.getColumnNumber();
|
||||
// Check for a sourceMap position
|
||||
source = getSourceMapping(filename, line, column);
|
||||
fileLocation = source ? `${filename}:${source[0]}:${source[1]}` : `${filename}:${line}:${column}`;
|
||||
}
|
||||
filename || (filename = "<anonymous>");
|
||||
line = frame.getLineNumber();
|
||||
column = frame.getColumnNumber();
|
||||
// Check for a sourceMap position
|
||||
source = getSourceMapping(filename, line, column);
|
||||
fileLocation = source ? `${filename}:${source[0]}:${source[1]}` : `${filename}:${line}:${column}`;
|
||||
}
|
||||
functionName = frame.getFunctionName();
|
||||
isConstructor = frame.isConstructor();
|
||||
isMethodCall = !(frame.isToplevel() || isConstructor);
|
||||
if (isMethodCall) {
|
||||
methodName = frame.getMethodName();
|
||||
typeName = frame.getTypeName();
|
||||
if (functionName) {
|
||||
tp = as = '';
|
||||
if (typeName && functionName.indexOf(typeName)) {
|
||||
tp = `${typeName}.`;
|
||||
functionName = frame.getFunctionName();
|
||||
isConstructor = frame.isConstructor();
|
||||
isMethodCall = !(frame.isToplevel() || isConstructor);
|
||||
if (isMethodCall) {
|
||||
methodName = frame.getMethodName();
|
||||
typeName = frame.getTypeName();
|
||||
if (functionName) {
|
||||
tp = as = '';
|
||||
if (typeName && functionName.indexOf(typeName)) {
|
||||
tp = `${typeName}.`;
|
||||
}
|
||||
if (methodName && functionName.indexOf(`.${methodName}`) !== functionName.length - methodName.length - 1) {
|
||||
as = ` [as ${methodName}]`;
|
||||
}
|
||||
return `${tp}${functionName}${as} (${fileLocation})`;
|
||||
} else {
|
||||
return `${typeName}.${methodName || '<anonymous>'} (${fileLocation})`;
|
||||
}
|
||||
if (methodName && functionName.indexOf(`.${methodName}`) !== functionName.length - methodName.length - 1) {
|
||||
as = ` [as ${methodName}]`;
|
||||
}
|
||||
return `${tp}${functionName}${as} (${fileLocation})`;
|
||||
} else if (isConstructor) {
|
||||
return `new ${functionName || '<anonymous>'} (${fileLocation})`;
|
||||
} else if (functionName) {
|
||||
return `${functionName} (${fileLocation})`;
|
||||
} else {
|
||||
return `${typeName}.${methodName || '<anonymous>'} (${fileLocation})`;
|
||||
return fileLocation;
|
||||
}
|
||||
} else if (isConstructor) {
|
||||
return `new ${functionName || '<anonymous>'} (${fileLocation})`;
|
||||
} else if (functionName) {
|
||||
return `${functionName} (${fileLocation})`;
|
||||
} else {
|
||||
return fileLocation;
|
||||
}
|
||||
};
|
||||
|
||||
getSourceMap = function(filename, line, column) {
|
||||
var answer, i, map, ref, ref1, sourceLocation;
|
||||
if (!(filename === '<anonymous>' || (ref = filename.slice(filename.lastIndexOf('.')), indexOf.call(FILE_EXTENSIONS, ref) >= 0))) {
|
||||
// Skip files that we didn’t compile, like Node system files that appear in
|
||||
// the stack trace, as they never have source maps.
|
||||
return null;
|
||||
}
|
||||
if (filename !== '<anonymous>' && (sourceMaps[filename] != null)) {
|
||||
return sourceMaps[filename][sourceMaps[filename].length - 1];
|
||||
// CoffeeScript compiled in a browser or via `CoffeeScript.compile` or `.run`
|
||||
// may get compiled with `options.filename` that’s missing, which becomes
|
||||
// `<anonymous>`; but the runtime might request the stack trace with the
|
||||
// filename of the script file. See if we have a source map cached under
|
||||
// `<anonymous>` that matches the error.
|
||||
} else if (sourceMaps['<anonymous>'] != null) {
|
||||
ref1 = sourceMaps['<anonymous>'];
|
||||
// Work backwards from the most recent anonymous source maps, until we find
|
||||
// one that works. This isn’t foolproof; there is a chance that multiple
|
||||
// source maps will have line/column pairs that match. But we have no other
|
||||
// way to match them. `frame.getFunction().toString()` doesn’t always work,
|
||||
// and it’s not foolproof either.
|
||||
for (i = ref1.length - 1; i >= 0; i += -1) {
|
||||
map = ref1[i];
|
||||
sourceLocation = map.sourceLocation([line - 1, column - 1]);
|
||||
if (((sourceLocation != null ? sourceLocation[0] : void 0) != null) && (sourceLocation[1] != null)) {
|
||||
return map;
|
||||
}
|
||||
}
|
||||
}
|
||||
// If all else fails, recompile this source to get a source map. We need the
|
||||
// previous section (for `<anonymous>`) despite this option, because after it
|
||||
// gets compiled we will still need to look it up from
|
||||
// `sourceMaps['<anonymous>']` in order to find and return it. That’s why we
|
||||
// start searching from the end in the previous block, because most of the
|
||||
// time the source map we want is the last one.
|
||||
if (sources[filename] != null) {
|
||||
answer = compile(sources[filename][sources[filename].length - 1], {
|
||||
filename: filename,
|
||||
sourceMap: true,
|
||||
literate: helpers.isLiterate(filename)
|
||||
});
|
||||
return answer.sourceMap;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
// Based on [michaelficarra/CoffeeScriptRedux](http://goo.gl/ZTx1p)
|
||||
// NodeJS / V8 have no support for transforming positions in stack traces using
|
||||
// sourceMap, so we must monkey-patch Error to display CoffeeScript source
|
||||
// positions.
|
||||
Error.prepareStackTrace = function(err, stack) {
|
||||
var frame, frames, getSourceMapping;
|
||||
};
|
||||
getSourceMapping = function(filename, line, column) {
|
||||
var answer, sourceMap;
|
||||
sourceMap = getSourceMap(filename, line, column);
|
||||
@@ -406,19 +367,27 @@
|
||||
return null;
|
||||
}
|
||||
};
|
||||
frames = (function() {
|
||||
var i, len, results;
|
||||
results = [];
|
||||
for (i = 0, len = stack.length; i < len; i++) {
|
||||
frame = stack[i];
|
||||
if (frame.getFunction() === exports.run) {
|
||||
break;
|
||||
// Based on [michaelficarra/CoffeeScriptRedux](http://goo.gl/ZTx1p)
|
||||
// NodeJS / V8 have no support for transforming positions in stack traces using
|
||||
// sourceMap, so we must monkey-patch Error to display CoffeeScript source
|
||||
// positions.
|
||||
return Error.prepareStackTrace = function(err, stack) {
|
||||
var frame, frames;
|
||||
frames = (function() {
|
||||
var i, len, results;
|
||||
results = [];
|
||||
for (i = 0, len = stack.length; i < len; i++) {
|
||||
frame = stack[i];
|
||||
if (frame.getFunction() === exports.run) {
|
||||
// Don’t display stack frames deeper than `CoffeeScript.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 results;
|
||||
})();
|
||||
return `${err.toString()}\n${frames.join('\n')}\n`;
|
||||
};
|
||||
};
|
||||
|
||||
checkShebangLine = function(file, input) {
|
||||
@@ -429,7 +398,9 @@
|
||||
return s !== '';
|
||||
}) : void 0 : void 0;
|
||||
if ((args != null ? args.length : void 0) > 1) {
|
||||
console.error('The script to be run begins with a shebang line with more than one\nargument. This script will fail on platforms such as Linux which only\nallow a single argument.');
|
||||
console.error(`The script to be run begins with a shebang line with more than one
|
||||
argument. This script will fail on platforms such as Linux which only
|
||||
allow a single argument.`);
|
||||
console.error(`The shebang line was: '${firstLine}' in file '${file}'`);
|
||||
return console.error(`The arguments were: ${JSON.stringify(args)}`);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Generated by CoffeeScript 2.3.2
|
||||
// Generated by CoffeeScript 2.7.0
|
||||
(function() {
|
||||
// The `coffee` utility. Handles command-line compilation of CoffeeScript
|
||||
// into various forms: saved into `.js` files or printed to stdout
|
||||
@@ -27,7 +27,7 @@
|
||||
useWinPathSep = path.sep === '\\';
|
||||
|
||||
// Allow CoffeeScript to emit Node.js events.
|
||||
helpers.extend(CoffeeScript, new EventEmitter);
|
||||
helpers.extend(CoffeeScript, new EventEmitter());
|
||||
|
||||
printLine = function(line) {
|
||||
return process.stdout.write(line + '\n');
|
||||
@@ -42,10 +42,12 @@
|
||||
};
|
||||
|
||||
// The help banner that is printed in conjunction with `-h`/`--help`.
|
||||
BANNER = 'Usage: coffee [options] path/to/script.coffee [args]\n\nIf called without options, `coffee` will run your script.';
|
||||
BANNER = `Usage: coffee [options] path/to/script.coffee [args]
|
||||
|
||||
If called without options, \`coffee\` will run your script.`;
|
||||
|
||||
// The list of all the valid option flags that `coffee` knows how to handle.
|
||||
SWITCHES = [['-b', '--bare', 'compile without a top-level function wrapper'], ['-c', '--compile', 'compile to JavaScript and save as .js files'], ['-e', '--eval', 'pass a string from the command line as input'], ['-h', '--help', 'display this help message'], ['-i', '--interactive', 'run an interactive CoffeeScript REPL'], ['-j', '--join [FILE]', 'concatenate the source CoffeeScript before compiling'], ['-m', '--map', 'generate source map and save as .js.map files'], ['-M', '--inline-map', 'generate source map and include it directly in output'], ['-n', '--nodes', 'print out the parse tree that the parser produces'], ['--nodejs [ARGS]', 'pass options directly to the "node" binary'], ['--no-header', 'suppress the "Generated by" header'], ['-o', '--output [PATH]', 'set the output path or path/filename for compiled JavaScript'], ['-p', '--print', 'print out the compiled JavaScript'], ['-r', '--require [MODULE*]', 'require the given module before eval or REPL'], ['-s', '--stdio', 'listen for and compile scripts over stdio'], ['-l', '--literate', 'treat stdio as literate style coffeescript'], ['-t', '--transpile', 'pipe generated JavaScript through Babel'], ['--tokens', 'print out the tokens that the lexer/rewriter produce'], ['-v', '--version', 'display the version number'], ['-w', '--watch', 'watch scripts for changes and rerun commands']];
|
||||
SWITCHES = [['--ast', 'generate an abstract syntax tree of nodes'], ['-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'], ['-l', '--literate', 'treat stdio as literate style coffeescript'], ['-m', '--map', 'generate source map and save as .js.map files'], ['-M', '--inline-map', 'generate source map and include it directly in output'], ['-n', '--nodes', 'print out the parse tree that the parser produces'], ['--nodejs [ARGS]', 'pass options directly to the "node" binary'], ['--no-header', 'suppress the "Generated by" header'], ['-o', '--output [PATH]', 'set the output path or path/filename for compiled JavaScript'], ['-p', '--print', 'print out the compiled JavaScript'], ['-r', '--require [MODULE*]', 'require the given module before eval or REPL'], ['-s', '--stdio', 'listen for and compile scripts over stdio'], ['-t', '--transpile', 'pipe generated JavaScript through Babel'], ['--tokens', 'print out the tokens that the lexer/rewriter produce'], ['-v', '--version', 'display the version number'], ['-w', '--watch', 'watch scripts for changes and rerun commands']];
|
||||
|
||||
// Top-level objects shared by all the functions.
|
||||
opts = {};
|
||||
@@ -78,7 +80,11 @@
|
||||
process.exit(1);
|
||||
}
|
||||
if ((!opts.doubleDashed) && (opts.arguments[1] === '--')) {
|
||||
printWarn('coffee was invoked with \'--\' as the second positional argument, which is\nnow deprecated. To pass \'--\' as an argument to a script to run, put an\nadditional \'--\' before the path to your script.\n\n\'--\' will be removed from the argument list.');
|
||||
printWarn(`coffee was invoked with '--' as the second positional argument, which is
|
||||
now deprecated. To pass '--' as an argument to a script to run, put an
|
||||
additional '--' before the path to your script.
|
||||
|
||||
'--' will be removed from the argument list.`);
|
||||
printWarn(`The positional arguments were: ${JSON.stringify(opts.arguments)}`);
|
||||
opts.arguments = [opts.arguments[0]].concat(opts.arguments.slice(2));
|
||||
}
|
||||
@@ -131,7 +137,18 @@
|
||||
}
|
||||
if (opts.join) {
|
||||
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');
|
||||
console.error(`
|
||||
The --join option is deprecated and will be removed in a future version.
|
||||
|
||||
If for some reason it's necessary to share local variables between files,
|
||||
replace...
|
||||
|
||||
$ coffee --compile --join bundle.js -- a.coffee b.coffee c.coffee
|
||||
|
||||
with...
|
||||
|
||||
$ cat a.coffee b.coffee c.coffee | coffee --compile --stdio > bundle.js
|
||||
`);
|
||||
}
|
||||
ref = opts.arguments;
|
||||
results = [];
|
||||
@@ -257,6 +274,9 @@
|
||||
return printTokens(CoffeeScript.tokens(task.input, task.options));
|
||||
} else if (opts.nodes) {
|
||||
return printLine(CoffeeScript.nodes(task.input, task.options).toString().trim());
|
||||
} else if (opts.ast) {
|
||||
compiled = CoffeeScript.compile(task.input, task.options);
|
||||
return printLine(JSON.stringify(compiled, null, 2));
|
||||
} else if (opts.run) {
|
||||
CoffeeScript.register();
|
||||
if (opts.prelude) {
|
||||
@@ -578,7 +598,7 @@
|
||||
|
||||
// When watching scripts, it's useful to log changes with the timestamp.
|
||||
timeLog = function(message) {
|
||||
return console.log(`${(new Date).toLocaleTimeString()} - ${message}`);
|
||||
return console.log(`${(new Date()).toLocaleTimeString()} - ${message}`);
|
||||
};
|
||||
|
||||
// Pretty-print a stream of tokens, sans location data.
|
||||
@@ -627,9 +647,15 @@
|
||||
// Give appropriate instructions depending on whether `coffee` was run
|
||||
// locally or globally.
|
||||
if (require.resolve('.').indexOf(process.cwd()) === 0) {
|
||||
console.error('To use --transpile, you must have @babel/core installed:\n npm install --save-dev @babel/core\nAnd you must save options to configure Babel in one of the places it looks to find its options.\nSee https://coffeescript.org/#transpilation');
|
||||
console.error(`To use --transpile, you must have @babel/core installed:
|
||||
npm install --save-dev @babel/core
|
||||
And you must save options to configure Babel in one of the places it looks to find its options.
|
||||
See https://coffeescript.org/#transpilation`);
|
||||
} else {
|
||||
console.error('To use --transpile with globally-installed CoffeeScript, you must have @babel/core installed globally:\n npm install --global @babel/core\nAnd you must save options to configure Babel in one of the places it looks to find its options, relative to the file being compiled or to the current folder.\nSee https://coffeescript.org/#transpilation');
|
||||
console.error(`To use --transpile with globally-installed CoffeeScript, you must have @babel/core installed globally:
|
||||
npm install --global @babel/core
|
||||
And you must save options to configure Babel in one of the places it looks to find its options, relative to the file being compiled or to the current folder.
|
||||
See https://coffeescript.org/#transpilation`);
|
||||
}
|
||||
process.exit(1);
|
||||
}
|
||||
@@ -659,7 +685,8 @@
|
||||
header: opts.compile && !opts['no-header'],
|
||||
transpile: opts.transpile,
|
||||
sourceMap: opts.map,
|
||||
inlineMap: opts['inline-map']
|
||||
inlineMap: opts['inline-map'],
|
||||
ast: opts.ast
|
||||
};
|
||||
if (filename) {
|
||||
if (base) {
|
||||
@@ -668,7 +695,7 @@
|
||||
jsDir = path.dirname(jsPath);
|
||||
answer = helpers.merge(answer, {
|
||||
jsPath,
|
||||
sourceRoot: path.relative(jsDir, cwd),
|
||||
sourceRoot: path.relative(jsDir, cwd) + path.sep,
|
||||
sourceFiles: [path.relative(cwd, filename)],
|
||||
generatedFile: helpers.baseFileName(jsPath, false, useWinPathSep)
|
||||
});
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,11 +1,12 @@
|
||||
// Generated by CoffeeScript 2.3.2
|
||||
// Generated by CoffeeScript 2.7.0
|
||||
(function() {
|
||||
// This file contains the common helper functions that we'd like to share among
|
||||
// the **Lexer**, **Rewriter**, and the **Nodes**. Merge objects, flatten
|
||||
// arrays, count characters, that sort of thing.
|
||||
|
||||
// Peek at the beginning of a given string to see if it matches a sequence.
|
||||
var attachCommentsToNode, buildLocationData, buildLocationHash, buildTokenDataDictionary, extend, flatten, ref, repeat, syntaxErrorToString;
|
||||
var UNICODE_CODE_POINT_ESCAPE, attachCommentsToNode, buildLocationData, buildLocationHash, buildTokenDataDictionary, extend, flatten, isBoolean, isNumber, isString, ref, repeat, syntaxErrorToString, unicodeCodePointToUnicodeEscapes,
|
||||
indexOf = [].indexOf;
|
||||
|
||||
exports.starts = function(string, literal, start) {
|
||||
return literal === string.substr(start, literal.length);
|
||||
@@ -156,23 +157,55 @@
|
||||
first_line: first.first_line,
|
||||
first_column: first.first_column,
|
||||
last_line: last.last_line,
|
||||
last_column: last.last_column
|
||||
last_column: last.last_column,
|
||||
last_line_exclusive: last.last_line_exclusive,
|
||||
last_column_exclusive: last.last_column_exclusive,
|
||||
range: [first.range[0], last.range[1]]
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
// Build a list of all comments attached to tokens.
|
||||
exports.extractAllCommentTokens = function(tokens) {
|
||||
var allCommentsObj, comment, commentKey, i, j, k, key, len1, len2, len3, ref1, results, sortedKeys, token;
|
||||
allCommentsObj = {};
|
||||
for (i = 0, len1 = tokens.length; i < len1; i++) {
|
||||
token = tokens[i];
|
||||
if (token.comments) {
|
||||
ref1 = token.comments;
|
||||
for (j = 0, len2 = ref1.length; j < len2; j++) {
|
||||
comment = ref1[j];
|
||||
commentKey = comment.locationData.range[0];
|
||||
allCommentsObj[commentKey] = comment;
|
||||
}
|
||||
}
|
||||
}
|
||||
sortedKeys = Object.keys(allCommentsObj).sort(function(a, b) {
|
||||
return a - b;
|
||||
});
|
||||
results = [];
|
||||
for (k = 0, len3 = sortedKeys.length; k < len3; k++) {
|
||||
key = sortedKeys[k];
|
||||
results.push(allCommentsObj[key]);
|
||||
}
|
||||
return results;
|
||||
};
|
||||
|
||||
// Get a lookup hash for a token based on its location data.
|
||||
// Multiple tokens might have the same location hash, but using exclusive
|
||||
// location data distinguishes e.g. zero-length generated tokens from
|
||||
// actual source tokens.
|
||||
buildLocationHash = function(loc) {
|
||||
return `${loc.first_line}x${loc.first_column}-${loc.last_line}x${loc.last_column}`;
|
||||
return `${loc.range[0]}-${loc.range[1]}`;
|
||||
};
|
||||
|
||||
// Build a dictionary of extra token properties organized by tokens’ locations
|
||||
// used as lookup hashes.
|
||||
buildTokenDataDictionary = function(parserState) {
|
||||
var base, i, len1, ref1, token, tokenData, tokenHash;
|
||||
exports.buildTokenDataDictionary = buildTokenDataDictionary = function(tokens) {
|
||||
var base1, i, len1, token, tokenData, tokenHash;
|
||||
tokenData = {};
|
||||
ref1 = parserState.parser.tokens;
|
||||
for (i = 0, len1 = ref1.length; i < len1; i++) {
|
||||
token = ref1[i];
|
||||
for (i = 0, len1 = tokens.length; i < len1; i++) {
|
||||
token = tokens[i];
|
||||
if (!token.comments) {
|
||||
continue;
|
||||
}
|
||||
@@ -188,7 +221,7 @@
|
||||
// and therefore matching `tokenHash`es, merge the comments from both/all
|
||||
// tokens together into one array, even if there are duplicate comments;
|
||||
// they will get sorted out later.
|
||||
((base = tokenData[tokenHash]).comments != null ? base.comments : base.comments = []).push(...token.comments);
|
||||
((base1 = tokenData[tokenHash]).comments != null ? base1.comments : base1.comments = []).push(...token.comments);
|
||||
}
|
||||
}
|
||||
return tokenData;
|
||||
@@ -197,21 +230,24 @@
|
||||
// This returns a function which takes an object as a parameter, and if that
|
||||
// object is an AST node, updates that object's locationData.
|
||||
// The object is returned either way.
|
||||
exports.addDataToNode = function(parserState, first, last) {
|
||||
exports.addDataToNode = function(parserState, firstLocationData, firstValue, lastLocationData, lastValue, forceUpdateLocation = true) {
|
||||
return function(obj) {
|
||||
var objHash, ref1;
|
||||
var locationData, objHash, ref1, ref2, ref3;
|
||||
// Add location data.
|
||||
if (((obj != null ? obj.updateLocationDataIfMissing : void 0) != null) && (first != null)) {
|
||||
obj.updateLocationDataIfMissing(buildLocationData(first, last));
|
||||
locationData = buildLocationData((ref1 = firstValue != null ? firstValue.locationData : void 0) != null ? ref1 : firstLocationData, (ref2 = lastValue != null ? lastValue.locationData : void 0) != null ? ref2 : lastLocationData);
|
||||
if (((obj != null ? obj.updateLocationDataIfMissing : void 0) != null) && (firstLocationData != null)) {
|
||||
obj.updateLocationDataIfMissing(locationData, forceUpdateLocation);
|
||||
} else {
|
||||
obj.locationData = locationData;
|
||||
}
|
||||
// Add comments, building the dictionary of token data if it hasn’t been
|
||||
// built yet.
|
||||
if (parserState.tokenData == null) {
|
||||
parserState.tokenData = buildTokenDataDictionary(parserState);
|
||||
parserState.tokenData = buildTokenDataDictionary(parserState.parser.tokens);
|
||||
}
|
||||
if (obj.locationData != null) {
|
||||
objHash = buildLocationHash(obj.locationData);
|
||||
if (((ref1 = parserState.tokenData[objHash]) != null ? ref1.comments : void 0) != null) {
|
||||
if (((ref3 = parserState.tokenData[objHash]) != null ? ref3.comments : void 0) != null) {
|
||||
attachCommentsToNode(parserState.tokenData[objHash].comments, obj);
|
||||
}
|
||||
}
|
||||
@@ -245,6 +281,16 @@
|
||||
}
|
||||
};
|
||||
|
||||
// Generate a unique anonymous file name so we can distinguish source map cache
|
||||
// entries for any number of anonymous scripts.
|
||||
exports.anonymousFileName = (function() {
|
||||
var n;
|
||||
n = 0;
|
||||
return function() {
|
||||
return `<anonymous-${n++}>`;
|
||||
};
|
||||
})();
|
||||
|
||||
// A `.coffee.md` compatible version of `basename`, that returns the file sans-extension.
|
||||
exports.baseFileName = function(file, stripExt = false, useWinPathSep = false) {
|
||||
var parts, pathSep;
|
||||
@@ -301,7 +347,7 @@
|
||||
};
|
||||
|
||||
syntaxErrorToString = function() {
|
||||
var codeLine, colorize, colorsEnabled, end, filename, first_column, first_line, last_column, last_line, marker, ref1, ref2, ref3, start;
|
||||
var codeLine, colorize, colorsEnabled, end, filename, first_column, first_line, last_column, last_line, marker, ref1, ref2, ref3, ref4, start;
|
||||
if (!(this.code && this.location)) {
|
||||
return Error.prototype.toString.call(this);
|
||||
}
|
||||
@@ -312,7 +358,11 @@
|
||||
if (last_column == null) {
|
||||
last_column = first_column;
|
||||
}
|
||||
filename = this.filename || '[stdin]';
|
||||
if ((ref1 = this.filename) != null ? ref1.startsWith('<anonymous') : void 0) {
|
||||
filename = '[stdin]';
|
||||
} else {
|
||||
filename = this.filename || '[stdin]';
|
||||
}
|
||||
codeLine = this.code.split('\n')[first_line];
|
||||
start = first_column;
|
||||
// Show only the first line on multi-line errors.
|
||||
@@ -320,16 +370,18 @@
|
||||
marker = codeLine.slice(0, start).replace(/[^\s]/g, ' ') + repeat('^', end - start);
|
||||
// Check to see if we're running on a color-enabled TTY.
|
||||
if (typeof process !== "undefined" && process !== null) {
|
||||
colorsEnabled = ((ref1 = process.stdout) != null ? ref1.isTTY : void 0) && !((ref2 = process.env) != null ? ref2.NODE_DISABLE_COLORS : void 0);
|
||||
colorsEnabled = ((ref2 = process.stdout) != null ? ref2.isTTY : void 0) && !((ref3 = process.env) != null ? ref3.NODE_DISABLE_COLORS : void 0);
|
||||
}
|
||||
if ((ref3 = this.colorful) != null ? ref3 : colorsEnabled) {
|
||||
if ((ref4 = this.colorful) != null ? ref4 : colorsEnabled) {
|
||||
colorize = function(str) {
|
||||
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}
|
||||
${codeLine}
|
||||
${marker}`;
|
||||
};
|
||||
|
||||
exports.nameWhitespaceCharacter = function(string) {
|
||||
@@ -347,4 +399,89 @@
|
||||
}
|
||||
};
|
||||
|
||||
exports.parseNumber = function(string) {
|
||||
var base;
|
||||
if (string == null) {
|
||||
return 0/0;
|
||||
}
|
||||
base = (function() {
|
||||
switch (string.charAt(1)) {
|
||||
case 'b':
|
||||
return 2;
|
||||
case 'o':
|
||||
return 8;
|
||||
case 'x':
|
||||
return 16;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
})();
|
||||
if (base != null) {
|
||||
return parseInt(string.slice(2).replace(/_/g, ''), base);
|
||||
} else {
|
||||
return parseFloat(string.replace(/_/g, ''));
|
||||
}
|
||||
};
|
||||
|
||||
exports.isFunction = function(obj) {
|
||||
return Object.prototype.toString.call(obj) === '[object Function]';
|
||||
};
|
||||
|
||||
exports.isNumber = isNumber = function(obj) {
|
||||
return Object.prototype.toString.call(obj) === '[object Number]';
|
||||
};
|
||||
|
||||
exports.isString = isString = function(obj) {
|
||||
return Object.prototype.toString.call(obj) === '[object String]';
|
||||
};
|
||||
|
||||
exports.isBoolean = isBoolean = function(obj) {
|
||||
return obj === true || obj === false || Object.prototype.toString.call(obj) === '[object Boolean]';
|
||||
};
|
||||
|
||||
exports.isPlainObject = function(obj) {
|
||||
return typeof obj === 'object' && !!obj && !Array.isArray(obj) && !isNumber(obj) && !isString(obj) && !isBoolean(obj);
|
||||
};
|
||||
|
||||
unicodeCodePointToUnicodeEscapes = function(codePoint) {
|
||||
var high, low, toUnicodeEscape;
|
||||
toUnicodeEscape = function(val) {
|
||||
var str;
|
||||
str = val.toString(16);
|
||||
return `\\u${repeat('0', 4 - str.length)}${str}`;
|
||||
};
|
||||
if (codePoint < 0x10000) {
|
||||
return toUnicodeEscape(codePoint);
|
||||
}
|
||||
// surrogate pair
|
||||
high = Math.floor((codePoint - 0x10000) / 0x400) + 0xD800;
|
||||
low = (codePoint - 0x10000) % 0x400 + 0xDC00;
|
||||
return `${toUnicodeEscape(high)}${toUnicodeEscape(low)}`;
|
||||
};
|
||||
|
||||
// Replace `\u{...}` with `\uxxxx[\uxxxx]` in regexes without `u` flag
|
||||
exports.replaceUnicodeCodePointEscapes = function(str, {flags, error, delimiter = ''} = {}) {
|
||||
var shouldReplace;
|
||||
shouldReplace = (flags != null) && indexOf.call(flags, 'u') < 0;
|
||||
return str.replace(UNICODE_CODE_POINT_ESCAPE, function(match, escapedBackslash, codePointHex, offset) {
|
||||
var codePointDecimal;
|
||||
if (escapedBackslash) {
|
||||
return escapedBackslash;
|
||||
}
|
||||
codePointDecimal = parseInt(codePointHex, 16);
|
||||
if (codePointDecimal > 0x10ffff) {
|
||||
error("unicode code point escapes greater than \\u{10ffff} are not allowed", {
|
||||
offset: offset + delimiter.length,
|
||||
length: codePointHex.length + 4
|
||||
});
|
||||
}
|
||||
if (!shouldReplace) {
|
||||
return match;
|
||||
}
|
||||
return unicodeCodePointToUnicodeEscapes(codePointDecimal);
|
||||
});
|
||||
};
|
||||
|
||||
UNICODE_CODE_POINT_ESCAPE = /(\\\\)|\\u\{([\da-fA-F]+)\}/g; // Make sure the escape isn’t escaped.
|
||||
|
||||
}).call(this);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Generated by CoffeeScript 2.3.2
|
||||
// Generated by CoffeeScript 2.7.0
|
||||
(function() {
|
||||
// Node.js Implementation
|
||||
var CoffeeScript, ext, fs, helpers, i, len, path, ref, universalCompile, vm,
|
||||
@@ -51,7 +51,7 @@
|
||||
var answer, dir, mainModule, ref;
|
||||
mainModule = require.main;
|
||||
// Set the filename.
|
||||
mainModule.filename = process.argv[1] = options.filename ? fs.realpathSync(options.filename) : '<anonymous>';
|
||||
mainModule.filename = process.argv[1] = options.filename ? fs.realpathSync(options.filename) : helpers.anonymousFileName();
|
||||
// Clear the module cache.
|
||||
mainModule.moduleCache && (mainModule.moduleCache = {});
|
||||
// Assign paths for node_modules loading
|
||||
@@ -59,11 +59,11 @@
|
||||
mainModule.paths = require('module')._nodeModulePaths(dir);
|
||||
// Save the options for compiling child imports.
|
||||
mainModule.options = options;
|
||||
options.filename = mainModule.filename;
|
||||
options.inlineMap = true;
|
||||
// Compile.
|
||||
if (!helpers.isCoffee(mainModule.filename) || require.extensions) {
|
||||
answer = CoffeeScript.compile(code, options);
|
||||
code = (ref = answer.js) != null ? ref : answer;
|
||||
}
|
||||
answer = CoffeeScript.compile(code, options);
|
||||
code = (ref = answer.js) != null ? ref : answer;
|
||||
return mainModule._compile(code, mainModule.filename);
|
||||
};
|
||||
|
||||
@@ -152,16 +152,14 @@
|
||||
}
|
||||
}
|
||||
|
||||
CoffeeScript._compileFile = function(filename, options = {}) {
|
||||
var answer, err, raw, stripped;
|
||||
raw = fs.readFileSync(filename, 'utf8');
|
||||
CoffeeScript._compileRawFileContent = function(raw, filename, options = {}) {
|
||||
var answer, err, stripped;
|
||||
// Strip the Unicode byte order mark, if this file begins with one.
|
||||
stripped = raw.charCodeAt(0) === 0xFEFF ? raw.substring(1) : raw;
|
||||
options = Object.assign({}, options, {
|
||||
filename: filename,
|
||||
literate: helpers.isLiterate(filename),
|
||||
sourceFiles: [filename],
|
||||
inlineMap: true // Always generate a source map, so that stack traces line up.
|
||||
sourceFiles: [filename]
|
||||
});
|
||||
try {
|
||||
answer = CoffeeScript.compile(stripped, options);
|
||||
@@ -175,6 +173,45 @@
|
||||
return answer;
|
||||
};
|
||||
|
||||
CoffeeScript._compileFile = function(filename, options = {}) {
|
||||
var raw;
|
||||
raw = fs.readFileSync(filename, 'utf8');
|
||||
return CoffeeScript._compileRawFileContent(raw, filename, options);
|
||||
};
|
||||
|
||||
module.exports = CoffeeScript;
|
||||
|
||||
// Explicitly define all named exports so that Node’s automatic detection of
|
||||
// named exports from CommonJS packages finds all of them. This enables consuming
|
||||
// packages to write code like `import { compile } from 'coffeescript'`.
|
||||
// Don’t simplify this into a loop or similar; the `module.exports.name` part is
|
||||
// essential for Node’s algorithm to successfully detect the name.
|
||||
module.exports.VERSION = CoffeeScript.VERSION;
|
||||
|
||||
module.exports.FILE_EXTENSIONS = CoffeeScript.FILE_EXTENSIONS;
|
||||
|
||||
module.exports.helpers = CoffeeScript.helpers;
|
||||
|
||||
module.exports.registerCompiled = CoffeeScript.registerCompiled;
|
||||
|
||||
module.exports.compile = CoffeeScript.compile;
|
||||
|
||||
module.exports.tokens = CoffeeScript.tokens;
|
||||
|
||||
module.exports.nodes = CoffeeScript.nodes;
|
||||
|
||||
module.exports.register = CoffeeScript.register;
|
||||
|
||||
module.exports.eval = CoffeeScript.eval;
|
||||
|
||||
module.exports.run = CoffeeScript.run;
|
||||
|
||||
module.exports.transpile = CoffeeScript.transpile;
|
||||
|
||||
module.exports.patchStackTrace = CoffeeScript.patchStackTrace;
|
||||
|
||||
module.exports._compileRawFileContent = CoffeeScript._compileRawFileContent;
|
||||
|
||||
module.exports._compileFile = CoffeeScript._compileFile;
|
||||
|
||||
}).call(this);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,4 @@
|
||||
// Generated by CoffeeScript 2.3.2
|
||||
// Generated by CoffeeScript 2.7.0
|
||||
(function() {
|
||||
var LONG_FLAG, MULTI_FLAG, OPTIONAL, OptionParser, SHORT_FLAG, buildRule, buildRules, normalizeArguments, repeat,
|
||||
splice = [].splice;
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1,6 +1,6 @@
|
||||
// Generated by CoffeeScript 2.3.2
|
||||
// Generated by CoffeeScript 2.7.0
|
||||
(function() {
|
||||
var CoffeeScript, Module, binary, child_process, ext, findExtension, fork, getRootModule, helpers, i, len, loadFile, path, ref;
|
||||
var CoffeeScript, Module, binary, cacheSourceMaps, child_process, ext, findExtension, fork, getRootModule, helpers, i, len, loadFile, nodeSourceMapsSupportEnabled, patchStackTrace, path, ref, ref1;
|
||||
|
||||
CoffeeScript = require('./');
|
||||
|
||||
@@ -10,20 +10,35 @@
|
||||
|
||||
path = require('path');
|
||||
|
||||
({patchStackTrace} = CoffeeScript);
|
||||
|
||||
// Check if Node's built-in source map stack trace transformations are enabled.
|
||||
nodeSourceMapsSupportEnabled = (typeof process !== "undefined" && process !== null) && (process.execArgv.includes('--enable-source-maps') || ((ref = process.env.NODE_OPTIONS) != null ? ref.includes('--enable-source-maps') : void 0));
|
||||
|
||||
if (!(Error.prepareStackTrace || nodeSourceMapsSupportEnabled)) {
|
||||
cacheSourceMaps = true;
|
||||
patchStackTrace();
|
||||
}
|
||||
|
||||
// Load and run a CoffeeScript file for Node, stripping any `BOM`s.
|
||||
loadFile = function(module, filename) {
|
||||
var answer, options;
|
||||
options = module.options || getRootModule(module).options;
|
||||
answer = CoffeeScript._compileFile(filename, options);
|
||||
return module._compile(answer, filename);
|
||||
var js, options;
|
||||
options = module.options || getRootModule(module).options || {};
|
||||
// Currently `CoffeeScript.compile` caches all source maps if present. They
|
||||
// are available in `getSourceMap` retrieved by `filename`.
|
||||
if (cacheSourceMaps || nodeSourceMapsSupportEnabled) {
|
||||
options.inlineMap = true;
|
||||
}
|
||||
js = CoffeeScript._compileFile(filename, options);
|
||||
return module._compile(js, filename);
|
||||
};
|
||||
|
||||
// If the installed version of Node supports `require.extensions`, register
|
||||
// CoffeeScript as an extension.
|
||||
if (require.extensions) {
|
||||
ref = CoffeeScript.FILE_EXTENSIONS;
|
||||
for (i = 0, len = ref.length; i < len; i++) {
|
||||
ext = ref[i];
|
||||
ref1 = CoffeeScript.FILE_EXTENSIONS;
|
||||
for (i = 0, len = ref1.length; i < len; i++) {
|
||||
ext = ref1[i];
|
||||
require.extensions[ext] = loadFile;
|
||||
}
|
||||
// Patch Node's module loader to be able to handle multi-dot extensions.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Generated by CoffeeScript 2.3.2
|
||||
// Generated by CoffeeScript 2.7.0
|
||||
(function() {
|
||||
var CoffeeScript, addHistory, addMultilineHandler, fs, getCommandId, merge, nodeREPL, path, replDefaults, runInContext, sawSIGINT, transpile, updateSyntaxError, vm;
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
})(),
|
||||
historyMaxInputSize: 10240,
|
||||
eval: function(input, context, filename, cb) {
|
||||
var Assign, Block, Call, Code, Literal, Value, ast, err, isAsync, js, ref, ref1, referencedVars, result, token, tokens;
|
||||
var Assign, Block, Call, Code, Literal, Root, Value, ast, err, isAsync, js, ref, ref1, referencedVars, result, token, tokens;
|
||||
// XXX: multiline hack.
|
||||
input = input.replace(/\uFF00/g, '\n');
|
||||
// Node's REPL sends the input ending with a newline and then wrapped in
|
||||
@@ -39,15 +39,15 @@
|
||||
// Unwrap that too.
|
||||
input = input.replace(/^\s*try\s*{([\s\S]*)}\s*catch.*$/m, '$1');
|
||||
// Require AST nodes to do some AST manipulation.
|
||||
({Block, Assign, Value, Literal, Call, Code} = require('./nodes'));
|
||||
({Block, Assign, Value, Literal, Call, Code, Root} = require('./nodes'));
|
||||
try {
|
||||
// Tokenize the clean input.
|
||||
tokens = CoffeeScript.tokens(input);
|
||||
// Filter out tokens generated just to hold comments.
|
||||
if (tokens.length >= 2 && tokens[0].generated && ((ref = tokens[0].comments) != null ? ref.length : void 0) !== 0 && tokens[0][1] === '' && tokens[1][0] === 'TERMINATOR') {
|
||||
if (tokens.length >= 2 && tokens[0].generated && ((ref = tokens[0].comments) != null ? ref.length : void 0) !== 0 && `${tokens[0][1]}` === '' && tokens[1][0] === 'TERMINATOR') {
|
||||
tokens = tokens.slice(2);
|
||||
}
|
||||
if (tokens.length >= 1 && tokens[tokens.length - 1].generated && ((ref1 = tokens[tokens.length - 1].comments) != null ? ref1.length : void 0) !== 0 && tokens[tokens.length - 1][1] === '') {
|
||||
if (tokens.length >= 1 && tokens[tokens.length - 1].generated && ((ref1 = tokens[tokens.length - 1].comments) != null ? ref1.length : void 0) !== 0 && `${tokens[tokens.length - 1][1]}` === '') {
|
||||
tokens.pop();
|
||||
}
|
||||
// Collect referenced variable names just like in `CoffeeScript.compile`.
|
||||
@@ -63,14 +63,14 @@
|
||||
return results;
|
||||
})();
|
||||
// Generate the AST of the tokens.
|
||||
ast = CoffeeScript.nodes(tokens);
|
||||
ast = CoffeeScript.nodes(tokens).body;
|
||||
// Add assignment to `__` variable to force the input to be an expression.
|
||||
ast = new Block([new Assign(new Value(new Literal('__')), ast, '=')]);
|
||||
// Wrap the expression in a closure to support top-level `await`.
|
||||
ast = new Code([], ast);
|
||||
isAsync = ast.isAsync;
|
||||
// Invoke the wrapping closure.
|
||||
ast = new Block([new Call(ast)]);
|
||||
ast = new Root(new Block([new Call(ast)]));
|
||||
js = ast.compile({
|
||||
bare: true,
|
||||
locals: Object.keys(context),
|
||||
@@ -113,8 +113,8 @@
|
||||
};
|
||||
|
||||
addMultilineHandler = function(repl) {
|
||||
var inputStream, multiline, nodeLineListener, origPrompt, outputStream, ref, rli;
|
||||
({rli, inputStream, outputStream} = repl);
|
||||
var inputStream, multiline, nodeLineListener, origPrompt, outputStream, ref;
|
||||
({inputStream, outputStream} = repl);
|
||||
// Node 0.11.12 changed API, prompt is now _prompt.
|
||||
origPrompt = (ref = repl._prompt) != null ? ref : repl.prompt;
|
||||
multiline = {
|
||||
@@ -128,15 +128,15 @@
|
||||
buffer: ''
|
||||
};
|
||||
// Proxy node's line listener
|
||||
nodeLineListener = rli.listeners('line')[0];
|
||||
rli.removeListener('line', nodeLineListener);
|
||||
rli.on('line', function(cmd) {
|
||||
nodeLineListener = repl.listeners('line')[0];
|
||||
repl.removeListener('line', nodeLineListener);
|
||||
repl.on('line', function(cmd) {
|
||||
if (multiline.enabled) {
|
||||
multiline.buffer += `${cmd}\n`;
|
||||
rli.setPrompt(multiline.prompt);
|
||||
rli.prompt(true);
|
||||
repl.setPrompt(multiline.prompt);
|
||||
repl.prompt(true);
|
||||
} else {
|
||||
rli.setPrompt(origPrompt);
|
||||
repl.setPrompt(origPrompt);
|
||||
nodeLineListener(cmd);
|
||||
}
|
||||
});
|
||||
@@ -149,28 +149,28 @@
|
||||
// allow arbitrarily switching between modes any time before multiple lines are entered
|
||||
if (!multiline.buffer.match(/\n/)) {
|
||||
multiline.enabled = !multiline.enabled;
|
||||
rli.setPrompt(origPrompt);
|
||||
rli.prompt(true);
|
||||
repl.setPrompt(origPrompt);
|
||||
repl.prompt(true);
|
||||
return;
|
||||
}
|
||||
// no-op unless the current line is empty
|
||||
if ((rli.line != null) && !rli.line.match(/^\s*$/)) {
|
||||
if ((repl.line != null) && !repl.line.match(/^\s*$/)) {
|
||||
return;
|
||||
}
|
||||
// eval, print, loop
|
||||
multiline.enabled = !multiline.enabled;
|
||||
rli.line = '';
|
||||
rli.cursor = 0;
|
||||
rli.output.cursorTo(0);
|
||||
rli.output.clearLine(1);
|
||||
repl.line = '';
|
||||
repl.cursor = 0;
|
||||
repl.output.cursorTo(0);
|
||||
repl.output.clearLine(1);
|
||||
// XXX: multiline hack
|
||||
multiline.buffer = multiline.buffer.replace(/\n/g, '\uFF00');
|
||||
rli.emit('line', multiline.buffer);
|
||||
repl.emit('line', multiline.buffer);
|
||||
multiline.buffer = '';
|
||||
} else {
|
||||
multiline.enabled = !multiline.enabled;
|
||||
rli.setPrompt(multiline.initialPrompt);
|
||||
rli.prompt(true);
|
||||
repl.setPrompt(multiline.initialPrompt);
|
||||
repl.prompt(true);
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -189,20 +189,20 @@
|
||||
fs.readSync(readFd, buffer, 0, size, stat.size - size);
|
||||
fs.closeSync(readFd);
|
||||
// Set the history on the interpreter
|
||||
repl.rli.history = buffer.toString().split('\n').reverse();
|
||||
repl.history = buffer.toString().split('\n').reverse();
|
||||
if (stat.size > maxSize) {
|
||||
// If the history file was truncated we should pop off a potential partial line
|
||||
repl.rli.history.pop();
|
||||
repl.history.pop();
|
||||
}
|
||||
if (repl.rli.history[0] === '') {
|
||||
if (repl.history[0] === '') {
|
||||
// Shift off the final blank newline
|
||||
repl.rli.history.shift();
|
||||
repl.history.shift();
|
||||
}
|
||||
repl.rli.historyIndex = -1;
|
||||
lastLine = repl.rli.history[0];
|
||||
repl.historyIndex = -1;
|
||||
lastLine = repl.history[0];
|
||||
} catch (error) {}
|
||||
fd = fs.openSync(filename, 'a');
|
||||
repl.rli.addListener('line', function(code) {
|
||||
repl.addListener('line', function(code) {
|
||||
if (code && code.length && code !== '.history' && code !== '.exit' && lastLine !== code) {
|
||||
// Save the latest command in the file
|
||||
fs.writeSync(fd, `${code}\n`);
|
||||
@@ -220,7 +220,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.history.slice(0).reverse().join('\n')}\n`);
|
||||
return repl.displayPrompt();
|
||||
}
|
||||
};
|
||||
@@ -257,7 +257,12 @@
|
||||
try {
|
||||
transpile.transpile = require('babel-core').transform;
|
||||
} catch (error) {
|
||||
console.error('To use --transpile with an interactive REPL, @babel/core must be installed either in the current folder or globally:\n npm install --save-dev @babel/core\nor\n npm install --global @babel/core\nAnd you must save options to configure Babel in one of the places it looks to find its options.\nSee https://coffeescript.org/#transpilation');
|
||||
console.error(`To use --transpile with an interactive REPL, @babel/core must be installed either in the current folder or globally:
|
||||
npm install --save-dev @babel/core
|
||||
or
|
||||
npm install --global @babel/core
|
||||
And you must save options to configure Babel in one of the places it looks to find its options.
|
||||
See https://coffeescript.org/#transpilation`);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
@@ -283,7 +288,7 @@
|
||||
runInContext(opts.prelude, repl.context, 'prelude');
|
||||
}
|
||||
repl.on('exit', function() {
|
||||
if (!repl.rli.closed) {
|
||||
if (!repl.closed) {
|
||||
return repl.outputStream.write('\n');
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Generated by CoffeeScript 2.3.2
|
||||
// Generated by CoffeeScript 2.7.0
|
||||
(function() {
|
||||
// The CoffeeScript language has a good deal of optional syntax, implicit syntax,
|
||||
// and shorthand syntax. This can greatly complicate a grammar and bloat
|
||||
@@ -6,10 +6,11 @@
|
||||
// a series of passes over the token stream, using this **Rewriter** to convert
|
||||
// shorthand into the unambiguous long form, add implicit indentation and
|
||||
// parentheses, and generally clean things up.
|
||||
var BALANCED_PAIRS, CALL_CLOSERS, CONTROL_IN_IMPLICIT, DISCARDED, EXPRESSION_CLOSE, EXPRESSION_END, EXPRESSION_START, IMPLICIT_CALL, IMPLICIT_END, IMPLICIT_FUNC, IMPLICIT_UNSPACED_CALL, INVERSES, LINEBREAKS, Rewriter, SINGLE_CLOSERS, SINGLE_LINERS, generate, k, left, len, moveComments, right, throwSyntaxError,
|
||||
indexOf = [].indexOf;
|
||||
var BALANCED_PAIRS, CALL_CLOSERS, CONTROL_IN_IMPLICIT, DISCARDED, EXPRESSION_CLOSE, EXPRESSION_END, EXPRESSION_START, IMPLICIT_CALL, IMPLICIT_END, IMPLICIT_FUNC, IMPLICIT_UNSPACED_CALL, INVERSES, LINEBREAKS, Rewriter, SINGLE_CLOSERS, SINGLE_LINERS, UNFINISHED, extractAllCommentTokens, generate, k, left, len, moveComments, right, throwSyntaxError,
|
||||
indexOf = [].indexOf,
|
||||
hasProp = {}.hasOwnProperty;
|
||||
|
||||
({throwSyntaxError} = require('./helpers'));
|
||||
({throwSyntaxError, extractAllCommentTokens} = require('./helpers'));
|
||||
|
||||
// Move attached comments from one token to another.
|
||||
moveComments = function(fromToken, toToken) {
|
||||
@@ -86,11 +87,11 @@
|
||||
this.normalizeLines();
|
||||
this.tagPostfixConditionals();
|
||||
this.addImplicitBracesAndParens();
|
||||
this.addParensToChainedDoIife();
|
||||
this.rescueStowawayComments();
|
||||
this.addLocationDataToGeneratedTokens();
|
||||
this.enforceValidCSXAttributes();
|
||||
this.fixOutdentLocationData();
|
||||
this.enforceValidJSXAttributes();
|
||||
this.fixIndentationLocationData();
|
||||
this.exposeTokenDataToGrammar();
|
||||
if (typeof process !== "undefined" && process !== null ? (ref1 = process.env) != null ? ref1.DEBUG_REWRITTEN_TOKEN_STREAM : void 0 : void 0) {
|
||||
if (process.env.DEBUG_TOKEN_STREAM) {
|
||||
console.log('Rewritten token stream:');
|
||||
@@ -196,16 +197,23 @@
|
||||
// The lexer has tagged the opening bracket of an indexing operation call.
|
||||
// Match it with its paired close.
|
||||
closeOpenIndexes() {
|
||||
var action, condition;
|
||||
var action, condition, startToken;
|
||||
startToken = null;
|
||||
condition = function(token, i) {
|
||||
var ref;
|
||||
return (ref = token[0]) === ']' || ref === 'INDEX_END';
|
||||
};
|
||||
action = function(token, i) {
|
||||
return token[0] = 'INDEX_END';
|
||||
if (this.tokens.length >= i && this.tokens[i + 1][0] === ':') {
|
||||
startToken[0] = '[';
|
||||
return token[0] = ']';
|
||||
} else {
|
||||
return token[0] = 'INDEX_END';
|
||||
}
|
||||
};
|
||||
return this.scanTokens(function(token, i) {
|
||||
if (token[0] === 'INDEX_START') {
|
||||
startToken = token;
|
||||
this.detectEnd(i + 1, condition, action);
|
||||
}
|
||||
return 1;
|
||||
@@ -281,7 +289,7 @@
|
||||
stack = [];
|
||||
start = null;
|
||||
return this.scanTokens(function(token, i, tokens) {
|
||||
var endImplicitCall, endImplicitObject, forward, implicitObjectContinues, inControlFlow, inImplicit, inImplicitCall, inImplicitControl, inImplicitObject, isImplicit, isImplicitCall, isImplicitObject, k, newLine, nextTag, nextToken, offset, prevTag, prevToken, ref, ref1, ref2, s, sameLine, stackIdx, stackItem, stackTag, stackTop, startIdx, startImplicitCall, startImplicitObject, startsLine, tag;
|
||||
var endImplicitCall, endImplicitObject, forward, implicitObjectContinues, implicitObjectIndent, inControlFlow, inImplicit, inImplicitCall, inImplicitControl, inImplicitObject, isImplicit, isImplicitCall, isImplicitObject, k, newLine, nextTag, nextToken, offset, preContinuationLineIndent, preObjectToken, prevTag, prevToken, ref, ref1, ref2, ref3, ref4, ref5, s, sameLine, stackIdx, stackItem, stackNext, stackTag, stackTop, startIdx, startImplicitCall, startImplicitObject, startIndex, startTag, startsLine, tag;
|
||||
[tag] = token;
|
||||
[prevTag] = prevToken = i > 0 ? tokens[i - 1] : [];
|
||||
[nextTag] = nextToken = i < tokens.length - 1 ? tokens[i + 1] : [];
|
||||
@@ -335,7 +343,7 @@
|
||||
tokens.splice(i, 0, generate('CALL_END', ')', ['', 'end of input', token[2]], prevToken));
|
||||
return i += 1;
|
||||
};
|
||||
startImplicitObject = function(idx, startsLine = true) {
|
||||
startImplicitObject = function(idx, {startsLine = true, continuationLineIndent} = {}) {
|
||||
var val;
|
||||
stack.push([
|
||||
'{',
|
||||
@@ -343,7 +351,8 @@
|
||||
{
|
||||
sameLine: true,
|
||||
startsLine: startsLine,
|
||||
ours: true
|
||||
ours: true,
|
||||
continuationLineIndent: continuationLineIndent
|
||||
}
|
||||
]);
|
||||
val = new String('{');
|
||||
@@ -467,9 +476,9 @@
|
||||
// if f(a: 1)
|
||||
|
||||
// which is probably always unintended.
|
||||
// Furthermore don’t allow this in literal arrays, as
|
||||
// that creates grammatical ambiguities.
|
||||
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'])) {
|
||||
// Furthermore don’t allow this in the first line of a literal array
|
||||
// or explicit object, as that creates grammatical ambiguities (#5368).
|
||||
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']) && !(((ref1 = (s = (ref2 = stackTop()) != null ? ref2[0] : void 0)) === '{' || ref1 === '[') && !isImplicit(stackTop()) && this.findTagsBackwards(i, s))) {
|
||||
startImplicitCall(i + 1);
|
||||
stack.push(['INDENT', i + 2]);
|
||||
return forward(3);
|
||||
@@ -478,25 +487,37 @@
|
||||
if (tag === ':') {
|
||||
// Go back to the (implicit) start of the object.
|
||||
s = (function() {
|
||||
var ref1;
|
||||
var ref3;
|
||||
switch (false) {
|
||||
case ref1 = this.tag(i - 1), indexOf.call(EXPRESSION_END, ref1) < 0:
|
||||
return start[1];
|
||||
case ref3 = this.tag(i - 1), indexOf.call(EXPRESSION_END, ref3) < 0:
|
||||
[startTag, startIndex] = start;
|
||||
if (startTag === '[' && startIndex > 0 && this.tag(startIndex - 1) === '@' && !tokens[startIndex - 1].spaced) {
|
||||
return startIndex - 1;
|
||||
} else {
|
||||
return startIndex;
|
||||
}
|
||||
break;
|
||||
case this.tag(i - 2) !== '@':
|
||||
return i - 2;
|
||||
default:
|
||||
return i - 1;
|
||||
}
|
||||
}).call(this);
|
||||
startsLine = s <= 0 || (ref1 = this.tag(s - 1), indexOf.call(LINEBREAKS, ref1) >= 0) || tokens[s - 1].newLine;
|
||||
startsLine = s <= 0 || (ref3 = this.tag(s - 1), indexOf.call(LINEBREAKS, ref3) >= 0) || tokens[s - 1].newLine;
|
||||
// Are we just continuing an already declared object?
|
||||
// Including the case where we indent on the line after an explicit '{'.
|
||||
if (stackTop()) {
|
||||
[stackTag, stackIdx] = stackTop();
|
||||
if ((stackTag === '{' || stackTag === 'INDENT' && this.tag(stackIdx - 1) === '{') && (startsLine || this.tag(s - 1) === ',' || this.tag(s - 1) === '{')) {
|
||||
stackNext = stack[stack.length - 2];
|
||||
if ((stackTag === '{' || stackTag === 'INDENT' && (stackNext != null ? stackNext[0] : void 0) === '{' && !isImplicit(stackNext) && this.findTagsBackwards(stackIdx - 1, ['{'])) && (startsLine || this.tag(s - 1) === ',' || this.tag(s - 1) === '{') && (ref4 = this.tag(s - 1), indexOf.call(UNFINISHED, ref4) < 0)) {
|
||||
return forward(1);
|
||||
}
|
||||
}
|
||||
startImplicitObject(s, !!startsLine);
|
||||
preObjectToken = i > 1 ? tokens[i - 2] : [];
|
||||
startImplicitObject(s, {
|
||||
startsLine: !!startsLine,
|
||||
continuationLineIndent: preObjectToken.continuationLineIndent
|
||||
});
|
||||
return forward(2);
|
||||
}
|
||||
// End implicit calls when chaining method calls
|
||||
@@ -526,6 +547,13 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
// End indented-continuation-line implicit objects once that indentation is over.
|
||||
if (tag === 'TERMINATOR' && token.endsContinuationLineIndentation) {
|
||||
({preContinuationLineIndent} = token.endsContinuationLineIndentation);
|
||||
while (inImplicitObject() && ((implicitObjectIndent = stackTop()[2].continuationLineIndent) != null) && implicitObjectIndent > preContinuationLineIndent) {
|
||||
endImplicitObject();
|
||||
}
|
||||
}
|
||||
newLine = prevTag === 'OUTDENT' || prevToken.newLine;
|
||||
if (indexOf.call(IMPLICIT_END, tag) >= 0 || (indexOf.call(CALL_CLOSERS, tag) >= 0 && newLine) || ((tag === '..' || tag === '...') && this.findTagsBackwards(i, ["INDEX_START"]))) {
|
||||
while (inImplicit()) {
|
||||
@@ -562,7 +590,7 @@
|
||||
|
||||
// f a, b: c, d: e, f, g: h: i, j
|
||||
|
||||
if (tag === ',' && !this.looksObjectish(i + 1) && inImplicitObject() && !((ref2 = this.tag(i + 2)) === 'FOROF' || ref2 === 'FORIN') && (nextTag !== 'TERMINATOR' || !this.looksObjectish(i + 2))) {
|
||||
if (tag === ',' && !this.looksObjectish(i + 1) && inImplicitObject() && !((ref5 = this.tag(i + 2)) === 'FOROF' || ref5 === 'FORIN') && (nextTag !== 'TERMINATOR' || !this.looksObjectish(i + 2))) {
|
||||
// When nextTag is OUTDENT the comma is insignificant and
|
||||
// should just be ignored so embed it in the implicit object.
|
||||
|
||||
@@ -577,11 +605,11 @@
|
||||
});
|
||||
}
|
||||
|
||||
// Make sure only strings and wrapped expressions are used in CSX attributes.
|
||||
enforceValidCSXAttributes() {
|
||||
// Make sure only strings and wrapped expressions are used in JSX attributes.
|
||||
enforceValidJSXAttributes() {
|
||||
return this.scanTokens(function(token, i, tokens) {
|
||||
var next, ref;
|
||||
if (token.csxColon) {
|
||||
if (token.jsxColon) {
|
||||
next = tokens[i + 1];
|
||||
if ((ref = next[0]) !== 'STRING_START' && ref !== 'STRING' && ref !== '(') {
|
||||
throwSyntaxError('expected wrapped or quoted JSX attribute', next[2]);
|
||||
@@ -595,13 +623,24 @@
|
||||
// lost into the ether, find comments attached to doomed tokens and move them
|
||||
// to a token that will make it to the other side.
|
||||
rescueStowawayComments() {
|
||||
var insertPlaceholder, shiftCommentsBackward, shiftCommentsForward;
|
||||
var dontShiftForward, insertPlaceholder, shiftCommentsBackward, shiftCommentsForward;
|
||||
insertPlaceholder = function(token, j, tokens, method) {
|
||||
if (tokens[j][0] !== 'TERMINATOR') {
|
||||
tokens[method](generate('TERMINATOR', '\n', tokens[j]));
|
||||
}
|
||||
return tokens[method](generate('JS', '', tokens[j], token));
|
||||
};
|
||||
dontShiftForward = function(i, tokens) {
|
||||
var j, ref;
|
||||
j = i + 1;
|
||||
while (j !== tokens.length && (ref = tokens[j][0], indexOf.call(DISCARDED, ref) >= 0)) {
|
||||
if (tokens[j][0] === 'INTERPOLATION_END') {
|
||||
return true;
|
||||
}
|
||||
j++;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
shiftCommentsForward = function(token, i, tokens) {
|
||||
var comment, j, k, len, ref, ref1, ref2;
|
||||
// Find the next surviving token and attach this token’s comments to it,
|
||||
@@ -671,7 +710,7 @@
|
||||
if (token.comments.length !== 0) {
|
||||
shiftCommentsForward(token, i, tokens);
|
||||
}
|
||||
} else {
|
||||
} else if (!dontShiftForward(i, tokens)) {
|
||||
// If any of this token’s comments start a line—there’s only
|
||||
// whitespace between the preceding newline and the start of the
|
||||
// comment—and this isn’t one of the special `JS` tokens, then
|
||||
@@ -708,31 +747,42 @@
|
||||
// Add location data to all tokens generated by the rewriter.
|
||||
addLocationDataToGeneratedTokens() {
|
||||
return this.scanTokens(function(token, i, tokens) {
|
||||
var column, line, nextLocation, prevLocation, ref, ref1;
|
||||
var column, line, nextLocation, prevLocation, rangeIndex, ref, ref1;
|
||||
if (token[2]) {
|
||||
return 1;
|
||||
}
|
||||
if (!(token.generated || token.explicit)) {
|
||||
return 1;
|
||||
}
|
||||
if (token.fromThen && token[0] === 'INDENT') {
|
||||
token[2] = token.origin[2];
|
||||
return 1;
|
||||
}
|
||||
if (token[0] === '{' && (nextLocation = (ref = tokens[i + 1]) != null ? ref[2] : void 0)) {
|
||||
({
|
||||
first_line: line,
|
||||
first_column: column
|
||||
first_column: column,
|
||||
range: [rangeIndex]
|
||||
} = nextLocation);
|
||||
} else if (prevLocation = (ref1 = tokens[i - 1]) != null ? ref1[2] : void 0) {
|
||||
({
|
||||
last_line: line,
|
||||
last_column: column
|
||||
last_column: column,
|
||||
range: [, rangeIndex]
|
||||
} = prevLocation);
|
||||
column += 1;
|
||||
} else {
|
||||
line = column = 0;
|
||||
rangeIndex = 0;
|
||||
}
|
||||
token[2] = {
|
||||
first_line: line,
|
||||
first_column: column,
|
||||
last_line: line,
|
||||
last_column: column
|
||||
last_column: column,
|
||||
last_line_exclusive: line,
|
||||
last_column_exclusive: column,
|
||||
range: [rangeIndex, rangeIndex]
|
||||
};
|
||||
return 1;
|
||||
});
|
||||
@@ -741,63 +791,104 @@
|
||||
// `OUTDENT` tokens should always be positioned at the last character of the
|
||||
// previous token, so that AST nodes ending in an `OUTDENT` token end up with a
|
||||
// location corresponding to the last “real” token under the node.
|
||||
fixOutdentLocationData() {
|
||||
fixIndentationLocationData() {
|
||||
var findPrecedingComment;
|
||||
if (this.allComments == null) {
|
||||
this.allComments = extractAllCommentTokens(this.tokens);
|
||||
}
|
||||
findPrecedingComment = (token, {afterPosition, indentSize, first, indented}) => {
|
||||
var comment, k, l, lastMatching, matches, ref, ref1, tokenStart;
|
||||
tokenStart = token[2].range[0];
|
||||
matches = function(comment) {
|
||||
if (comment.outdented) {
|
||||
if (!((indentSize != null) && comment.indentSize > indentSize)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (indented && !comment.indented) {
|
||||
return false;
|
||||
}
|
||||
if (!(comment.locationData.range[0] < tokenStart)) {
|
||||
return false;
|
||||
}
|
||||
if (!(comment.locationData.range[0] > afterPosition)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
if (first) {
|
||||
lastMatching = null;
|
||||
ref = this.allComments;
|
||||
for (k = ref.length - 1; k >= 0; k += -1) {
|
||||
comment = ref[k];
|
||||
if (matches(comment)) {
|
||||
lastMatching = comment;
|
||||
} else if (lastMatching) {
|
||||
return lastMatching;
|
||||
}
|
||||
}
|
||||
return lastMatching;
|
||||
}
|
||||
ref1 = this.allComments;
|
||||
for (l = ref1.length - 1; l >= 0; l += -1) {
|
||||
comment = ref1[l];
|
||||
if (matches(comment)) {
|
||||
return comment;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
return this.scanTokens(function(token, i, tokens) {
|
||||
var prevLocationData;
|
||||
if (!(token[0] === 'OUTDENT' || (token.generated && token[0] === 'CALL_END') || (token.generated && token[0] === '}'))) {
|
||||
var isIndent, nextToken, nextTokenIndex, precedingComment, prevLocationData, prevToken, ref, ref1, ref2, useNextToken;
|
||||
if (!(((ref = token[0]) === 'INDENT' || ref === 'OUTDENT') || (token.generated && token[0] === 'CALL_END' && !((ref1 = token.data) != null ? ref1.closingTagNameToken : void 0)) || (token.generated && token[0] === '}'))) {
|
||||
return 1;
|
||||
}
|
||||
prevLocationData = tokens[i - 1][2];
|
||||
isIndent = token[0] === 'INDENT';
|
||||
prevToken = (ref2 = token.prevToken) != null ? ref2 : tokens[i - 1];
|
||||
prevLocationData = prevToken[2];
|
||||
// addLocationDataToGeneratedTokens() set the outdent’s location data
|
||||
// to the preceding token’s, but in order to detect comments inside an
|
||||
// empty "block" we want to look for comments preceding the next token.
|
||||
useNextToken = token.explicit || token.generated;
|
||||
if (useNextToken) {
|
||||
nextToken = token;
|
||||
nextTokenIndex = i;
|
||||
while ((nextToken.explicit || nextToken.generated) && nextTokenIndex !== tokens.length - 1) {
|
||||
nextToken = tokens[nextTokenIndex++];
|
||||
}
|
||||
}
|
||||
precedingComment = findPrecedingComment(useNextToken ? nextToken : token, {
|
||||
afterPosition: prevLocationData.range[0],
|
||||
indentSize: token.indentSize,
|
||||
first: isIndent,
|
||||
indented: useNextToken
|
||||
});
|
||||
if (isIndent) {
|
||||
if (!(precedingComment != null ? precedingComment.newLine : void 0)) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (token.generated && token[0] === 'CALL_END' && (precedingComment != null ? precedingComment.indented : void 0)) {
|
||||
// We don’t want e.g. an implicit call at the end of an `if` condition to
|
||||
// include a following indented comment.
|
||||
return 1;
|
||||
}
|
||||
if (precedingComment != null) {
|
||||
prevLocationData = precedingComment.locationData;
|
||||
}
|
||||
token[2] = {
|
||||
first_line: prevLocationData.last_line,
|
||||
first_column: prevLocationData.last_column,
|
||||
first_line: precedingComment != null ? prevLocationData.first_line : prevLocationData.last_line,
|
||||
first_column: precedingComment != null ? isIndent ? 0 : prevLocationData.first_column : prevLocationData.last_column,
|
||||
last_line: prevLocationData.last_line,
|
||||
last_column: prevLocationData.last_column
|
||||
last_column: prevLocationData.last_column,
|
||||
last_line_exclusive: prevLocationData.last_line_exclusive,
|
||||
last_column_exclusive: prevLocationData.last_column_exclusive,
|
||||
range: isIndent && (precedingComment != null) ? [prevLocationData.range[0] - precedingComment.indentSize, prevLocationData.range[1]] : prevLocationData.range
|
||||
};
|
||||
return 1;
|
||||
});
|
||||
}
|
||||
|
||||
// Add parens around a `do` IIFE followed by a chained `.` so that the
|
||||
// chaining applies to the executed function rather than the function
|
||||
// object (see #3736)
|
||||
addParensToChainedDoIife() {
|
||||
var action, condition, doIndex;
|
||||
condition = function(token, i) {
|
||||
return this.tag(i - 1) === 'OUTDENT';
|
||||
};
|
||||
action = function(token, i) {
|
||||
var ref;
|
||||
if (ref = token[0], indexOf.call(CALL_CLOSERS, ref) < 0) {
|
||||
return;
|
||||
}
|
||||
this.tokens.splice(doIndex, 0, generate('(', '(', this.tokens[doIndex]));
|
||||
return this.tokens.splice(i + 1, 0, generate(')', ')', this.tokens[i]));
|
||||
};
|
||||
doIndex = null;
|
||||
return this.scanTokens(function(token, i, tokens) {
|
||||
var glyphIndex, ref;
|
||||
if (token[1] !== 'do') {
|
||||
return 1;
|
||||
}
|
||||
doIndex = i;
|
||||
glyphIndex = i + 1;
|
||||
if (this.tag(i + 1) === 'PARAM_START') {
|
||||
glyphIndex = null;
|
||||
this.detectEnd(i + 1, function(token, i) {
|
||||
return this.tag(i - 1) === 'PARAM_END';
|
||||
}, function(token, i) {
|
||||
return glyphIndex = i;
|
||||
});
|
||||
}
|
||||
if (!((glyphIndex != null) && ((ref = this.tag(glyphIndex)) === '->' || ref === '=>') && this.tag(glyphIndex + 1) === 'INDENT')) {
|
||||
return 1;
|
||||
}
|
||||
this.detectEnd(glyphIndex + 1, condition, action);
|
||||
return 2;
|
||||
});
|
||||
}
|
||||
|
||||
// Because our grammar is LALR(1), it can’t handle some single-line
|
||||
// expressions that lack ending delimiters. The **Rewriter** adds the implicit
|
||||
// blocks, so it doesn’t need to. To keep the grammar clean and tidy, trailing
|
||||
@@ -846,7 +937,7 @@
|
||||
return i + 2;
|
||||
};
|
||||
return this.scanTokens(function(token, i, tokens) {
|
||||
var conditionTag, j, k, ref, ref1, tag;
|
||||
var conditionTag, j, k, ref, ref1, ref2, tag;
|
||||
[tag] = token;
|
||||
conditionTag = (tag === '->' || tag === '=>') && this.findTagsBackwards(i, ['IF', 'WHILE', 'FOR', 'UNTIL', 'SWITCH', 'WHEN', 'LEADING_WHEN', '[', 'INDEX_START']) && !(this.findTagsBackwards(i, ['THEN', '..', '...']));
|
||||
if (tag === 'TERMINATOR') {
|
||||
@@ -855,6 +946,10 @@
|
||||
return 1;
|
||||
}
|
||||
if (ref = this.tag(i + 1), indexOf.call(EXPRESSION_CLOSE, ref) >= 0) {
|
||||
if (token[1] === ';' && this.tag(i + 1) === 'OUTDENT') {
|
||||
tokens[i + 1].prevToken = token;
|
||||
moveComments(token, tokens[i + 1]);
|
||||
}
|
||||
tokens.splice(i, 1);
|
||||
return 0;
|
||||
}
|
||||
@@ -868,7 +963,7 @@
|
||||
return 2 + j;
|
||||
}
|
||||
}
|
||||
if ((tag === '->' || tag === '=>') && (this.tag(i + 1) === ',' || this.tag(i + 1) === '.' && token.newLine)) {
|
||||
if ((tag === '->' || tag === '=>') && (((ref2 = this.tag(i + 1)) === ',' || ref2 === ']') || this.tag(i + 1) === '.' && token.newLine)) {
|
||||
[indent, outdent] = this.indentation(tokens[i]);
|
||||
tokens.splice(i + 1, 0, indent, outdent);
|
||||
return 1;
|
||||
@@ -927,6 +1022,30 @@
|
||||
});
|
||||
}
|
||||
|
||||
// For tokens with extra data, we want to make that data visible to the grammar
|
||||
// by wrapping the token value as a String() object and setting the data as
|
||||
// properties of that object. The grammar should then be responsible for
|
||||
// cleaning this up for the node constructor: unwrapping the token value to a
|
||||
// primitive string and separately passing any expected token data properties
|
||||
exposeTokenDataToGrammar() {
|
||||
return this.scanTokens(function(token, i) {
|
||||
var key, ref, ref1, val;
|
||||
if (token.generated || (token.data && Object.keys(token.data).length !== 0)) {
|
||||
token[1] = new String(token[1]);
|
||||
ref1 = (ref = token.data) != null ? ref : {};
|
||||
for (key in ref1) {
|
||||
if (!hasProp.call(ref1, key)) continue;
|
||||
val = ref1[key];
|
||||
token[1][key] = val;
|
||||
}
|
||||
if (token.generated) {
|
||||
token[1].generated = true;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
});
|
||||
}
|
||||
|
||||
// Generate the indentation tokens, based on another token on the same line.
|
||||
indentation(origin) {
|
||||
var indent, outdent;
|
||||
@@ -959,7 +1078,7 @@
|
||||
// ---------
|
||||
|
||||
// List of the token pairs that must be balanced.
|
||||
BALANCED_PAIRS = [['(', ')'], ['[', ']'], ['{', '}'], ['INDENT', 'OUTDENT'], ['CALL_START', 'CALL_END'], ['PARAM_START', 'PARAM_END'], ['INDEX_START', 'INDEX_END'], ['STRING_START', 'STRING_END'], ['REGEX_START', 'REGEX_END']];
|
||||
BALANCED_PAIRS = [['(', ')'], ['[', ']'], ['{', '}'], ['INDENT', 'OUTDENT'], ['CALL_START', 'CALL_END'], ['PARAM_START', 'PARAM_END'], ['INDEX_START', 'INDEX_END'], ['STRING_START', 'STRING_END'], ['INTERPOLATION_START', 'INTERPOLATION_END'], ['REGEX_START', 'REGEX_END']];
|
||||
|
||||
// The inverse mappings of `BALANCED_PAIRS` we’re trying to fix up, so we can
|
||||
// look things up from either end.
|
||||
@@ -983,7 +1102,7 @@
|
||||
IMPLICIT_FUNC = ['IDENTIFIER', 'PROPERTY', 'SUPER', ')', 'CALL_END', ']', 'INDEX_END', '@', 'THIS'];
|
||||
|
||||
// If preceded by an `IMPLICIT_FUNC`, indicates a function invocation.
|
||||
IMPLICIT_CALL = ['IDENTIFIER', 'CSX_TAG', '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_CALL = ['IDENTIFIER', 'JSX_TAG', 'PROPERTY', 'NUMBER', 'INFINITY', 'NAN', 'STRING', 'STRING_START', 'REGEX', 'REGEX_START', 'JS', 'NEW', 'PARAM_START', 'CLASS', 'IF', 'TRY', 'SWITCH', 'THIS', 'DYNAMIC_IMPORT', 'IMPORT_META', 'NEW_TARGET', 'UNDEFINED', 'NULL', 'BOOL', 'UNARY', 'DO', 'DO_IIFE', 'YIELD', 'AWAIT', 'UNARY_MATH', 'SUPER', 'THROW', '@', '->', '=>', '[', '(', '{', '--', '++'];
|
||||
|
||||
IMPLICIT_UNSPACED_CALL = ['+', '-'];
|
||||
|
||||
@@ -1011,6 +1130,9 @@
|
||||
// `STRING_START` isn’t on this list because its `locationData` matches that of
|
||||
// the node that becomes `StringWithInterpolations`, and therefore
|
||||
// `addDataToNode` attaches `STRING_START`’s tokens to that node.
|
||||
DISCARDED = ['(', ')', '[', ']', '{', '}', '.', '..', '...', ',', '=', '++', '--', '?', 'AS', 'AWAIT', 'CALL_START', 'CALL_END', 'DEFAULT', 'ELSE', 'EXTENDS', 'EXPORT', 'FORIN', 'FOROF', 'FORFROM', 'IMPORT', 'INDENT', 'INDEX_SOAK', 'LEADING_WHEN', 'OUTDENT', 'PARAM_END', 'REGEX_START', 'REGEX_END', 'RETURN', 'STRING_END', 'THROW', 'UNARY', 'YIELD'].concat(IMPLICIT_UNSPACED_CALL.concat(IMPLICIT_END.concat(CALL_CLOSERS.concat(CONTROL_IN_IMPLICIT))));
|
||||
DISCARDED = ['(', ')', '[', ']', '{', '}', ':', '.', '..', '...', ',', '=', '++', '--', '?', 'AS', 'AWAIT', 'CALL_START', 'CALL_END', 'DEFAULT', 'DO', 'DO_IIFE', 'ELSE', 'EXTENDS', 'EXPORT', 'FORIN', 'FOROF', 'FORFROM', 'IMPORT', 'INDENT', 'INDEX_SOAK', 'INTERPOLATION_START', 'INTERPOLATION_END', 'LEADING_WHEN', 'OUTDENT', 'PARAM_END', 'REGEX_START', 'REGEX_END', 'RETURN', 'STRING_END', 'THROW', 'UNARY', 'YIELD'].concat(IMPLICIT_UNSPACED_CALL.concat(IMPLICIT_END.concat(CALL_CLOSERS.concat(CONTROL_IN_IMPLICIT))));
|
||||
|
||||
// Tokens that, when appearing at the end of a line, suppress a following TERMINATOR/INDENT token
|
||||
exports.UNFINISHED = UNFINISHED = ['\\', '.', '?.', '?::', 'UNARY', 'DO', 'DO_IIFE', 'MATH', 'UNARY_MATH', '+', '-', '**', 'SHIFT', 'RELATION', 'COMPARE', '&', '^', '|', '&&', '||', 'BIN?', 'EXTENDS'];
|
||||
|
||||
}).call(this);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Generated by CoffeeScript 2.3.2
|
||||
// Generated by CoffeeScript 2.7.0
|
||||
(function() {
|
||||
// The **Scope** class regulates lexical scoping within CoffeeScript. As you
|
||||
// generate code, you create a tree of scopes in the same shape as the nested
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Generated by CoffeeScript 2.3.2
|
||||
// Generated by CoffeeScript 2.7.0
|
||||
(function() {
|
||||
// Source maps allow JavaScript runtimes to match running JavaScript back to
|
||||
// the original source code that corresponds to it. This can be minified
|
||||
@@ -53,10 +53,10 @@
|
||||
// SourceMap
|
||||
// ---------
|
||||
|
||||
// Maps locations in a single generated JavaScript file back to locations in
|
||||
// Maps locations in a single generated JavaScript file back to locations in
|
||||
// the original CoffeeScript source file.
|
||||
|
||||
// This is intentionally agnostic towards how a source map might be represented on
|
||||
// This is intentionally agnostic towards how a source map might be represented on
|
||||
// disk. Once the compiler is ready to produce a "v3"-style source map, we can walk
|
||||
// through the arrays of line and column buffer to produce it.
|
||||
class SourceMap {
|
||||
@@ -85,10 +85,20 @@
|
||||
return lineMap && lineMap.sourceLocation(column);
|
||||
}
|
||||
|
||||
static registerCompiled(filename, source, sourcemap) {
|
||||
if (sourcemap != null) {
|
||||
return SourceMap.sourceMaps[filename] = sourcemap;
|
||||
}
|
||||
}
|
||||
|
||||
static getSourceMap(filename) {
|
||||
return SourceMap.sourceMaps[filename];
|
||||
}
|
||||
|
||||
// V3 SourceMap Generation
|
||||
// -----------------------
|
||||
|
||||
// Builds up a V3 source map, returning the generated JSON as a string.
|
||||
// Builds up a V3 source map, returning the generated JSON as a string.
|
||||
// `options.sourceRoot` may be used to specify the sourceRoot written to the source
|
||||
// map. Also, `options.sourceFiles` and `options.generatedFile` may be passed to
|
||||
// set "sources" and "file", respectively.
|
||||
@@ -183,6 +193,14 @@
|
||||
|
||||
};
|
||||
|
||||
// Caching
|
||||
// -------
|
||||
|
||||
// A static source maps cache `filename`: `map`. These are used for transforming
|
||||
// stack traces and are currently set in `CoffeeScript.compile` for all files
|
||||
// compiled with the source maps option.
|
||||
SourceMap.sourceMaps = Object.create(null);
|
||||
|
||||
// Base64 VLQ Encoding
|
||||
// -------------------
|
||||
|
||||
|
||||
10411
package-lock.json
generated
10411
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
29
package.json
29
package.json
@@ -8,7 +8,7 @@
|
||||
"compiler"
|
||||
],
|
||||
"author": "Jeremy Ashkenas",
|
||||
"version": "2.3.2",
|
||||
"version": "2.7.0",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
@@ -17,7 +17,8 @@
|
||||
"lib": "./lib/coffeescript"
|
||||
},
|
||||
"main": "./lib/coffeescript/index",
|
||||
"browser": "./lib/coffeescript/browser",
|
||||
"module": "./lib/coffeescript-browser-compiler-modern/coffeescript.js",
|
||||
"browser": "./lib/coffeescript-browser-compiler-legacy/coffeescript.js",
|
||||
"bin": {
|
||||
"coffee": "./bin/coffee",
|
||||
"cake": "./bin/cake"
|
||||
@@ -39,16 +40,16 @@
|
||||
"url": "git://github.com/jashkenas/coffeescript.git"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.0.0",
|
||||
"@babel/preset-env": "^7.0.0",
|
||||
"babel-preset-minify": "^0.4.3",
|
||||
"codemirror": "^5.39.2",
|
||||
"docco": "~0.8.0",
|
||||
"highlight.js": "~9.12.0",
|
||||
"jison": ">=0.4.18",
|
||||
"markdown-it": "~8.4.2",
|
||||
"underscore": "~1.9.1",
|
||||
"webpack": "~4.17.2"
|
||||
},
|
||||
"dependencies": {}
|
||||
"@babel/core": "~7.17.8",
|
||||
"@babel/preset-env": "~7.16.11",
|
||||
"babel-preset-minify": "~0.5.1",
|
||||
"codemirror": "~5.65.2",
|
||||
"docco": "~0.9.1",
|
||||
"highlight.js": "~11.5.0",
|
||||
"jison": "~0.4.18",
|
||||
"markdown-it": "~12.3.2",
|
||||
"puppeteer": "~13.5.2",
|
||||
"underscore": "~1.13.2",
|
||||
"webpack": "~5.71.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ CoffeeScript.load = (url, callback, options = {}, hold = false) ->
|
||||
# Activate CoffeeScript in the browser by having it compile and evaluate
|
||||
# all script tags with a content-type of `text/coffeescript`.
|
||||
# This happens on page load.
|
||||
runScripts = ->
|
||||
CoffeeScript.runScripts = ->
|
||||
scripts = window.document.getElementsByTagName 'script'
|
||||
coffeetypes = ['text/coffeescript', 'text/literate-coffeescript']
|
||||
coffees = (s for s in scripts when s.type in coffeetypes)
|
||||
@@ -96,7 +96,12 @@ runScripts = ->
|
||||
execute()
|
||||
|
||||
# Listen for window load, both in decent browsers and in IE.
|
||||
if window.addEventListener
|
||||
window.addEventListener 'DOMContentLoaded', runScripts, no
|
||||
else
|
||||
window.attachEvent 'onload', runScripts
|
||||
# Only attach this event handler on startup for the
|
||||
# non-ES module version of the browser compiler, to preserve
|
||||
# backward compatibility while letting the ES module version
|
||||
# be importable without side effects.
|
||||
if this is window
|
||||
if window.addEventListener
|
||||
window.addEventListener 'DOMContentLoaded', CoffeeScript.runScripts, no
|
||||
else
|
||||
window.attachEvent 'onload', CoffeeScript.runScripts
|
||||
|
||||
@@ -19,6 +19,12 @@ exports.FILE_EXTENSIONS = FILE_EXTENSIONS = ['.coffee', '.litcoffee', '.coffee.m
|
||||
# Expose helpers for testing.
|
||||
exports.helpers = helpers
|
||||
|
||||
{getSourceMap, registerCompiled} = SourceMap
|
||||
# This is exported to enable an external module to implement caching of
|
||||
# sourcemaps. This is used only when `patchStackTrace` has been called to adjust
|
||||
# stack traces for files with cached source maps.
|
||||
exports.registerCompiled = registerCompiled
|
||||
|
||||
# Function that allows for btoa in both nodejs and the browser.
|
||||
base64encode = (src) -> switch
|
||||
when typeof Buffer is 'function'
|
||||
@@ -43,17 +49,6 @@ withPrettyErrors = (fn) ->
|
||||
throw err if typeof code isnt 'string' # Support `CoffeeScript.nodes(tokens)`.
|
||||
throw helpers.updateSyntaxError err, code, options.filename
|
||||
|
||||
# For each compiled file, save its source in memory in case we need to
|
||||
# recompile it later. We might need to recompile if the first compilation
|
||||
# didn’t create a source map (faster) but something went wrong and we need
|
||||
# a stack trace. Assuming that most of the time, code isn’t throwing
|
||||
# exceptions, it’s probably more efficient to compile twice only when we
|
||||
# need a stack trace, rather than always generating a source map even when
|
||||
# it’s not likely to be used. Save in form of `filename`: [`(source)`]
|
||||
sources = {}
|
||||
# Also save source maps if generated, in form of `(source)`: [`(source map)`].
|
||||
sourceMaps = {}
|
||||
|
||||
# Compile CoffeeScript code to JavaScript, using the Coffee/Jison compiler.
|
||||
#
|
||||
# If `options.sourceMap` is specified, then `options.filename` must also be
|
||||
@@ -67,16 +62,12 @@ sourceMaps = {}
|
||||
exports.compile = compile = withPrettyErrors (code, options = {}) ->
|
||||
# Clone `options`, to avoid mutating the `options` object passed in.
|
||||
options = Object.assign {}, options
|
||||
# Always generate a source map if no filename is passed in, since without a
|
||||
# a filename we have no way to retrieve this source later in the event that
|
||||
# we need to recompile it to get a source map for `prepareStackTrace`.
|
||||
|
||||
generateSourceMap = options.sourceMap or options.inlineMap or not options.filename?
|
||||
filename = options.filename or '<anonymous>'
|
||||
filename = options.filename or helpers.anonymousFileName()
|
||||
|
||||
checkShebangLine filename, code
|
||||
|
||||
sources[filename] ?= []
|
||||
sources[filename].push code
|
||||
map = new SourceMap if generateSourceMap
|
||||
|
||||
tokens = lexer.tokenize code, options
|
||||
@@ -94,7 +85,28 @@ exports.compile = compile = withPrettyErrors (code, options = {}) ->
|
||||
options.bare = yes
|
||||
break
|
||||
|
||||
fragments = parser.parse(tokens).compileToFragments options
|
||||
nodes = parser.parse tokens
|
||||
# If all that was requested was a POJO representation of the nodes, e.g.
|
||||
# the abstract syntax tree (AST), we can stop now and just return that
|
||||
# (after fixing the location data for the root/`File`»`Program` node,
|
||||
# which might’ve gotten misaligned from the original source due to the
|
||||
# `clean` function in the lexer).
|
||||
if options.ast
|
||||
nodes.allCommentTokens = helpers.extractAllCommentTokens tokens
|
||||
sourceCodeNumberOfLines = (code.match(/\r?\n/g) or '').length + 1
|
||||
sourceCodeLastLine = /.*$/.exec(code)[0] # `.*` matches all but line break characters.
|
||||
ast = nodes.ast options
|
||||
range = [0, code.length]
|
||||
ast.start = ast.program.start = range[0]
|
||||
ast.end = ast.program.end = range[1]
|
||||
ast.range = ast.program.range = range
|
||||
ast.loc.start = ast.program.loc.start = {line: 1, column: 0}
|
||||
ast.loc.end.line = ast.program.loc.end.line = sourceCodeNumberOfLines
|
||||
ast.loc.end.column = ast.program.loc.end.column = sourceCodeLastLine.length
|
||||
ast.tokens = tokens
|
||||
return ast
|
||||
|
||||
fragments = nodes.compileToFragments options
|
||||
|
||||
currentLine = 0
|
||||
currentLine += 1 if options.header
|
||||
@@ -126,8 +138,6 @@ exports.compile = compile = withPrettyErrors (code, options = {}) ->
|
||||
|
||||
if generateSourceMap
|
||||
v3SourceMap = map.generate options, code
|
||||
sourceMaps[filename] ?= []
|
||||
sourceMaps[filename].push map
|
||||
|
||||
if options.transpile
|
||||
if typeof options.transpile isnt 'object'
|
||||
@@ -155,9 +165,11 @@ exports.compile = compile = withPrettyErrors (code, options = {}) ->
|
||||
if options.inlineMap
|
||||
encoded = base64encode JSON.stringify v3SourceMap
|
||||
sourceMapDataURI = "//# sourceMappingURL=data:application/json;base64,#{encoded}"
|
||||
sourceURL = "//# sourceURL=#{options.filename ? 'coffeescript'}"
|
||||
sourceURL = "//# sourceURL=#{filename}"
|
||||
js = "#{js}\n#{sourceMapDataURI}\n#{sourceURL}"
|
||||
|
||||
registerCompiled filename, code, map
|
||||
|
||||
if options.sourceMap
|
||||
{
|
||||
js
|
||||
@@ -175,10 +187,8 @@ exports.tokens = withPrettyErrors (code, options) ->
|
||||
# return the AST. You can then compile it by calling `.compile()` on the root,
|
||||
# or traverse it by using `.traverseChildren()` with a callback.
|
||||
exports.nodes = withPrettyErrors (source, options) ->
|
||||
if typeof source is 'string'
|
||||
parser.parse lexer.tokenize source, options
|
||||
else
|
||||
parser.parse source
|
||||
source = lexer.tokenize source, options if typeof source is 'string'
|
||||
parser.parse source
|
||||
|
||||
# This file used to export these methods; leave stubs that throw warnings
|
||||
# instead. These methods have been moved into `index.coffee` to provide
|
||||
@@ -195,6 +205,10 @@ lexer = new Lexer
|
||||
# thin wrapper around it, compatible with the Jison API. We can then pass it
|
||||
# directly as a “Jison lexer.”
|
||||
parser.lexer =
|
||||
yylloc:
|
||||
range: []
|
||||
options:
|
||||
ranges: yes
|
||||
lex: ->
|
||||
token = parser.tokens[@pos++]
|
||||
if token
|
||||
@@ -236,111 +250,77 @@ parser.yy.parseError = (message, {token}) ->
|
||||
# from the lexer.
|
||||
helpers.throwSyntaxError "unexpected #{errorText}", errorLoc
|
||||
|
||||
# Based on http://v8.googlecode.com/svn/branches/bleeding_edge/src/messages.js
|
||||
# Modified to handle sourceMap
|
||||
formatSourcePosition = (frame, getSourceMapping) ->
|
||||
filename = undefined
|
||||
fileLocation = ''
|
||||
exports.patchStackTrace = ->
|
||||
# Based on http://v8.googlecode.com/svn/branches/bleeding_edge/src/messages.js
|
||||
# Modified to handle sourceMap
|
||||
formatSourcePosition = (frame, getSourceMapping) ->
|
||||
filename = undefined
|
||||
fileLocation = ''
|
||||
|
||||
if frame.isNative()
|
||||
fileLocation = "native"
|
||||
else
|
||||
if frame.isEval()
|
||||
filename = frame.getScriptNameOrSourceURL()
|
||||
fileLocation = "#{frame.getEvalOrigin()}, " unless filename
|
||||
if frame.isNative()
|
||||
fileLocation = "native"
|
||||
else
|
||||
filename = frame.getFileName()
|
||||
|
||||
filename or= "<anonymous>"
|
||||
|
||||
line = frame.getLineNumber()
|
||||
column = frame.getColumnNumber()
|
||||
|
||||
# Check for a sourceMap position
|
||||
source = getSourceMapping filename, line, column
|
||||
fileLocation =
|
||||
if source
|
||||
"#{filename}:#{source[0]}:#{source[1]}"
|
||||
if frame.isEval()
|
||||
filename = frame.getScriptNameOrSourceURL()
|
||||
fileLocation = "#{frame.getEvalOrigin()}, " unless filename
|
||||
else
|
||||
"#{filename}:#{line}:#{column}"
|
||||
filename = frame.getFileName()
|
||||
|
||||
functionName = frame.getFunctionName()
|
||||
isConstructor = frame.isConstructor()
|
||||
isMethodCall = not (frame.isToplevel() or isConstructor)
|
||||
filename or= "<anonymous>"
|
||||
|
||||
if isMethodCall
|
||||
methodName = frame.getMethodName()
|
||||
typeName = frame.getTypeName()
|
||||
line = frame.getLineNumber()
|
||||
column = frame.getColumnNumber()
|
||||
|
||||
if functionName
|
||||
tp = as = ''
|
||||
if typeName and functionName.indexOf typeName
|
||||
tp = "#{typeName}."
|
||||
if methodName and functionName.indexOf(".#{methodName}") isnt functionName.length - methodName.length - 1
|
||||
as = " [as #{methodName}]"
|
||||
# Check for a sourceMap position
|
||||
source = getSourceMapping filename, line, column
|
||||
fileLocation =
|
||||
if source
|
||||
"#{filename}:#{source[0]}:#{source[1]}"
|
||||
else
|
||||
"#{filename}:#{line}:#{column}"
|
||||
|
||||
"#{tp}#{functionName}#{as} (#{fileLocation})"
|
||||
functionName = frame.getFunctionName()
|
||||
isConstructor = frame.isConstructor()
|
||||
isMethodCall = not (frame.isToplevel() or isConstructor)
|
||||
|
||||
if isMethodCall
|
||||
methodName = frame.getMethodName()
|
||||
typeName = frame.getTypeName()
|
||||
|
||||
if functionName
|
||||
tp = as = ''
|
||||
if typeName and functionName.indexOf typeName
|
||||
tp = "#{typeName}."
|
||||
if methodName and functionName.indexOf(".#{methodName}") isnt functionName.length - methodName.length - 1
|
||||
as = " [as #{methodName}]"
|
||||
|
||||
"#{tp}#{functionName}#{as} (#{fileLocation})"
|
||||
else
|
||||
"#{typeName}.#{methodName or '<anonymous>'} (#{fileLocation})"
|
||||
else if isConstructor
|
||||
"new #{functionName or '<anonymous>'} (#{fileLocation})"
|
||||
else if functionName
|
||||
"#{functionName} (#{fileLocation})"
|
||||
else
|
||||
"#{typeName}.#{methodName or '<anonymous>'} (#{fileLocation})"
|
||||
else if isConstructor
|
||||
"new #{functionName or '<anonymous>'} (#{fileLocation})"
|
||||
else if functionName
|
||||
"#{functionName} (#{fileLocation})"
|
||||
else
|
||||
fileLocation
|
||||
fileLocation
|
||||
|
||||
getSourceMap = (filename, line, column) ->
|
||||
# Skip files that we didn’t compile, like Node system files that appear in
|
||||
# the stack trace, as they never have source maps.
|
||||
return null unless filename is '<anonymous>' or filename.slice(filename.lastIndexOf('.')) in FILE_EXTENSIONS
|
||||
|
||||
if filename isnt '<anonymous>' and sourceMaps[filename]?
|
||||
return sourceMaps[filename][sourceMaps[filename].length - 1]
|
||||
# CoffeeScript compiled in a browser or via `CoffeeScript.compile` or `.run`
|
||||
# may get compiled with `options.filename` that’s missing, which becomes
|
||||
# `<anonymous>`; but the runtime might request the stack trace with the
|
||||
# filename of the script file. See if we have a source map cached under
|
||||
# `<anonymous>` that matches the error.
|
||||
else if sourceMaps['<anonymous>']?
|
||||
# Work backwards from the most recent anonymous source maps, until we find
|
||||
# one that works. This isn’t foolproof; there is a chance that multiple
|
||||
# source maps will have line/column pairs that match. But we have no other
|
||||
# way to match them. `frame.getFunction().toString()` doesn’t always work,
|
||||
# and it’s not foolproof either.
|
||||
for map in sourceMaps['<anonymous>'] by -1
|
||||
sourceLocation = map.sourceLocation [line - 1, column - 1]
|
||||
return map if sourceLocation?[0]? and sourceLocation[1]?
|
||||
|
||||
# If all else fails, recompile this source to get a source map. We need the
|
||||
# previous section (for `<anonymous>`) despite this option, because after it
|
||||
# gets compiled we will still need to look it up from
|
||||
# `sourceMaps['<anonymous>']` in order to find and return it. That’s why we
|
||||
# start searching from the end in the previous block, because most of the
|
||||
# time the source map we want is the last one.
|
||||
if sources[filename]?
|
||||
answer = compile sources[filename][sources[filename].length - 1],
|
||||
filename: filename
|
||||
sourceMap: yes
|
||||
literate: helpers.isLiterate filename
|
||||
answer.sourceMap
|
||||
else
|
||||
null
|
||||
|
||||
# Based on [michaelficarra/CoffeeScriptRedux](http://goo.gl/ZTx1p)
|
||||
# NodeJS / V8 have no support for transforming positions in stack traces using
|
||||
# sourceMap, so we must monkey-patch Error to display CoffeeScript source
|
||||
# positions.
|
||||
Error.prepareStackTrace = (err, stack) ->
|
||||
getSourceMapping = (filename, line, column) ->
|
||||
sourceMap = getSourceMap filename, line, column
|
||||
|
||||
answer = sourceMap.sourceLocation [line - 1, column - 1] if sourceMap?
|
||||
if answer? then [answer[0] + 1, answer[1] + 1] else null
|
||||
|
||||
frames = for frame in stack
|
||||
break if frame.getFunction() is exports.run
|
||||
" at #{formatSourcePosition frame, getSourceMapping}"
|
||||
# Based on [michaelficarra/CoffeeScriptRedux](http://goo.gl/ZTx1p)
|
||||
# NodeJS / V8 have no support for transforming positions in stack traces using
|
||||
# sourceMap, so we must monkey-patch Error to display CoffeeScript source
|
||||
# positions.
|
||||
Error.prepareStackTrace = (err, stack) ->
|
||||
frames = for frame in stack
|
||||
# Don’t display stack frames deeper than `CoffeeScript.run`.
|
||||
break if frame.getFunction() is exports.run
|
||||
" at #{formatSourcePosition frame, getSourceMapping}"
|
||||
|
||||
"#{err.toString()}\n#{frames.join '\n'}\n"
|
||||
"#{err.toString()}\n#{frames.join '\n'}\n"
|
||||
|
||||
checkShebangLine = (file, input) ->
|
||||
firstLine = input.split(/$/m)[0]
|
||||
|
||||
@@ -32,12 +32,14 @@ BANNER = '''
|
||||
|
||||
# The list of all the valid option flags that `coffee` knows how to handle.
|
||||
SWITCHES = [
|
||||
[ '--ast', 'generate an abstract syntax tree of nodes']
|
||||
['-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']
|
||||
['-l', '--literate', 'treat stdio as literate style coffeescript']
|
||||
['-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']
|
||||
@@ -47,7 +49,6 @@ 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 coffeescript']
|
||||
['-t', '--transpile', 'pipe generated JavaScript through Babel']
|
||||
[ '--tokens', 'print out the tokens that the lexer/rewriter produce']
|
||||
['-v', '--version', 'display the version number']
|
||||
@@ -207,6 +208,9 @@ compileScript = (file, input, base = null) ->
|
||||
printTokens CoffeeScript.tokens task.input, task.options
|
||||
else if opts.nodes
|
||||
printLine CoffeeScript.nodes(task.input, task.options).toString().trim()
|
||||
else if opts.ast
|
||||
compiled = CoffeeScript.compile task.input, task.options
|
||||
printLine JSON.stringify(compiled, null, 2)
|
||||
else if opts.run
|
||||
CoffeeScript.register()
|
||||
CoffeeScript.eval opts.prelude, task.options if opts.prelude
|
||||
@@ -502,6 +506,7 @@ compileOptions = (filename, base) ->
|
||||
transpile: opts.transpile
|
||||
sourceMap: opts.map
|
||||
inlineMap: opts['inline-map']
|
||||
ast: opts.ast
|
||||
|
||||
if filename
|
||||
if base
|
||||
@@ -510,7 +515,7 @@ compileOptions = (filename, base) ->
|
||||
jsDir = path.dirname jsPath
|
||||
answer = helpers.merge answer, {
|
||||
jsPath
|
||||
sourceRoot: path.relative jsDir, cwd
|
||||
sourceRoot: path.relative(jsDir, cwd) + path.sep
|
||||
sourceFiles: [path.relative cwd, filename]
|
||||
generatedFile: helpers.baseFileName(jsPath, no, useWinPathSep)
|
||||
}
|
||||
|
||||
@@ -34,6 +34,9 @@ o = (patternString, action, options) ->
|
||||
patternString = patternString.replace /\s{2,}/g, ' '
|
||||
patternCount = patternString.split(' ').length
|
||||
if action
|
||||
# This code block does string replacements in the generated `parser.js`
|
||||
# file, replacing the calls to the `LOC` function and other strings as
|
||||
# listed below.
|
||||
action = if match = unwrap.exec action then match[1] else "(#{action}())"
|
||||
|
||||
# All runtime functions we need are defined on `yy`
|
||||
@@ -44,12 +47,38 @@ o = (patternString, action, options) ->
|
||||
# that nodes may have, such as comments or location data. Location data
|
||||
# is added to the first parameter passed in, and the parameter is returned.
|
||||
# If the parameter is not a node, it will just be passed through unaffected.
|
||||
getAddDataToNodeFunctionString = (first, last) ->
|
||||
"yy.addDataToNode(yy, @#{first}#{if last then ", @#{last}" else ''})"
|
||||
getAddDataToNodeFunctionString = (first, last, forceUpdateLocation = yes) ->
|
||||
"yy.addDataToNode(yy, @#{first}, #{if first[0] is '$' then '$$' else '$'}#{first}, #{if last then "@#{last}, #{if last[0] is '$' then '$$' else '$'}#{last}" else 'null, null'}, #{if forceUpdateLocation then 'true' else 'false'})"
|
||||
|
||||
# This code replaces the calls to `LOC` with the `yy.addDataToNode` string
|
||||
# defined above. The `LOC` function, when used below in the grammar rules,
|
||||
# is used to make sure that newly created node class objects get correct
|
||||
# location data assigned to them. By default, the grammar will assign the
|
||||
# location data spanned by *all* of the tokens on the left (e.g. a string
|
||||
# such as `'Body TERMINATOR Line'`) to the “top-level” node returned by
|
||||
# the grammar rule (the function on the right). But for “inner” node class
|
||||
# objects created by grammar rules, they won’t get correct location data
|
||||
# assigned to them without adding `LOC`.
|
||||
|
||||
# For example, consider the grammar rule `'NEW_TARGET . Property'`, which
|
||||
# is handled by a function that returns
|
||||
# `new MetaProperty LOC(1)(new IdentifierLiteral $1), LOC(3)(new Access $3)`.
|
||||
# The `1` in `LOC(1)` refers to the first token (`NEW_TARGET`) and the `3`
|
||||
# in `LOC(3)` refers to the third token (`Property`). In order for the
|
||||
# `new IdentifierLiteral` to get assigned the location data corresponding
|
||||
# to `new` in the source code, we use
|
||||
# `LOC(1)(new IdentifierLiteral ...)` to mean “assign the location data of
|
||||
# the *first* token of this grammar rule (`NEW_TARGET`) to this
|
||||
# `new IdentifierLiteral`”. The `LOC(3)` means “assign the location data of
|
||||
# the *third* token of this grammar rule (`Property`) to this
|
||||
# `new Access`”.
|
||||
returnsLoc = /^LOC/.test action
|
||||
action = action.replace /LOC\(([0-9]*)\)/g, getAddDataToNodeFunctionString('$1')
|
||||
# A call to `LOC` with two arguments, e.g. `LOC(2,4)`, sets the location
|
||||
# data for the generated node on both of the referenced tokens (the second
|
||||
# and fourth in this example).
|
||||
action = action.replace /LOC\(([0-9]*),\s*([0-9]*)\)/g, getAddDataToNodeFunctionString('$1', '$2')
|
||||
performActionFunctionString = "$$ = #{getAddDataToNodeFunctionString(1, patternCount)}(#{action});"
|
||||
performActionFunctionString = "$$ = #{getAddDataToNodeFunctionString(1, patternCount, not returnsLoc)}(#{action});"
|
||||
else
|
||||
performActionFunctionString = '$$ = $1;'
|
||||
|
||||
@@ -73,8 +102,8 @@ grammar =
|
||||
# The **Root** is the top-level node in the syntax tree. Since we parse bottom-up,
|
||||
# all parsing must end here.
|
||||
Root: [
|
||||
o '', -> new Block
|
||||
o 'Body'
|
||||
o '', -> new Root new Block
|
||||
o 'Body', -> new Root $1
|
||||
]
|
||||
|
||||
# Any list of statements and expressions, separated by line breaks or semicolons.
|
||||
@@ -84,7 +113,7 @@ grammar =
|
||||
o 'Body TERMINATOR'
|
||||
]
|
||||
|
||||
# Block and statements, which make up a line in a body. YieldReturn is a
|
||||
# Block and statements, which make up a line in a body. FuncDirective is a
|
||||
# statement, but not included in Statement because that results in an ambiguous
|
||||
# grammar.
|
||||
Line: [
|
||||
@@ -152,40 +181,68 @@ grammar =
|
||||
|
||||
Identifier: [
|
||||
o 'IDENTIFIER', -> new IdentifierLiteral $1
|
||||
o 'CSX_TAG', -> new CSXTag $1
|
||||
o 'JSX_TAG', -> new JSXTag $1.toString(),
|
||||
tagNameLocationData: $1.tagNameToken[2]
|
||||
closingTagOpeningBracketLocationData: $1.closingTagOpeningBracketToken?[2]
|
||||
closingTagSlashLocationData: $1.closingTagSlashToken?[2]
|
||||
closingTagNameLocationData: $1.closingTagNameToken?[2]
|
||||
closingTagClosingBracketLocationData: $1.closingTagClosingBracketToken?[2]
|
||||
]
|
||||
|
||||
Property: [
|
||||
o 'PROPERTY', -> new PropertyName $1
|
||||
o 'PROPERTY', -> new PropertyName $1.toString()
|
||||
]
|
||||
|
||||
# Alphanumerics are separated from the other **Literal** matchers because
|
||||
# they can also serve as keys in object literals.
|
||||
AlphaNumeric: [
|
||||
o 'NUMBER', -> new NumberLiteral $1
|
||||
o 'NUMBER', -> new NumberLiteral $1.toString(), parsedValue: $1.parsedValue
|
||||
o 'String'
|
||||
]
|
||||
|
||||
String: [
|
||||
o 'STRING', -> new StringLiteral $1
|
||||
o 'STRING_START Body STRING_END', -> new StringWithInterpolations $2
|
||||
o 'STRING', ->
|
||||
new StringLiteral(
|
||||
$1.slice 1, -1 # strip artificial quotes and unwrap to primitive string
|
||||
quote: $1.quote
|
||||
initialChunk: $1.initialChunk
|
||||
finalChunk: $1.finalChunk
|
||||
indent: $1.indent
|
||||
double: $1.double
|
||||
heregex: $1.heregex
|
||||
)
|
||||
o 'STRING_START Interpolations STRING_END', -> new StringWithInterpolations Block.wrap($2), quote: $1.quote, startQuote: LOC(1)(new Literal $1.toString())
|
||||
]
|
||||
|
||||
Interpolations: [
|
||||
o 'InterpolationChunk', -> [$1]
|
||||
o 'Interpolations InterpolationChunk', -> $1.concat $2
|
||||
]
|
||||
|
||||
InterpolationChunk: [
|
||||
o 'INTERPOLATION_START Body INTERPOLATION_END', -> new Interpolation $2
|
||||
o 'INTERPOLATION_START INDENT Body OUTDENT INTERPOLATION_END', -> new Interpolation $3
|
||||
o 'INTERPOLATION_START INTERPOLATION_END', -> new Interpolation
|
||||
o 'String', -> $1
|
||||
]
|
||||
|
||||
# The .toString() calls here and elsewhere are to convert `String` objects
|
||||
# back to primitive strings now that we've retrieved stowaway extra properties
|
||||
Regex: [
|
||||
o 'REGEX', -> new RegexLiteral $1
|
||||
o 'REGEX_START Invocation REGEX_END', -> new RegexWithInterpolations $2.args
|
||||
o 'REGEX', -> new RegexLiteral $1.toString(), delimiter: $1.delimiter, heregexCommentTokens: $1.heregexCommentTokens
|
||||
o 'REGEX_START Invocation REGEX_END', -> new RegexWithInterpolations $2, heregexCommentTokens: $3.heregexCommentTokens
|
||||
]
|
||||
|
||||
# All of our immediate values. Generally these can be passed straight
|
||||
# through and printed to JavaScript.
|
||||
Literal: [
|
||||
o 'AlphaNumeric'
|
||||
o 'JS', -> new PassthroughLiteral $1
|
||||
o 'JS', -> new PassthroughLiteral $1.toString(), here: $1.here, generated: $1.generated
|
||||
o 'Regex'
|
||||
o 'UNDEFINED', -> new UndefinedLiteral $1
|
||||
o 'NULL', -> new NullLiteral $1
|
||||
o 'BOOL', -> new BooleanLiteral $1
|
||||
o 'INFINITY', -> new InfinityLiteral $1
|
||||
o 'BOOL', -> new BooleanLiteral $1.toString(), originalValue: $1.original
|
||||
o 'INFINITY', -> new InfinityLiteral $1.toString(), originalValue: $1.original
|
||||
o 'NAN', -> new NaNLiteral $1
|
||||
]
|
||||
|
||||
@@ -222,15 +279,16 @@ grammar =
|
||||
ObjAssignable: [
|
||||
o 'SimpleObjAssignable'
|
||||
o '[ Expression ]', -> new Value new ComputedPropertyName $2
|
||||
o '@ [ Expression ]', -> new Value LOC(1)(new ThisLiteral $1), [LOC(3)(new ComputedPropertyName($3))], 'this'
|
||||
o 'AlphaNumeric'
|
||||
]
|
||||
|
||||
# Object literal spread properties.
|
||||
ObjRestValue: [
|
||||
o 'SimpleObjAssignable ...', -> new Splat new Value $1
|
||||
o '... SimpleObjAssignable', -> new Splat new Value $2
|
||||
o '... SimpleObjAssignable', -> new Splat new Value($2), postfix: no
|
||||
o 'ObjSpreadExpr ...', -> new Splat $1
|
||||
o '... ObjSpreadExpr', -> new Splat $2
|
||||
o '... ObjSpreadExpr', -> new Splat $2, postfix: no
|
||||
]
|
||||
|
||||
ObjSpreadExpr: [
|
||||
@@ -239,19 +297,15 @@ grammar =
|
||||
o 'Parenthetical'
|
||||
o 'Super'
|
||||
o 'This'
|
||||
o 'SUPER Arguments', -> new SuperCall LOC(1)(new Super), $2, no, $1
|
||||
o 'SimpleObjAssignable Arguments', -> new Call (new Value $1), $2
|
||||
o 'ObjSpreadExpr Arguments', -> new Call $1, $2
|
||||
o 'SUPER OptFuncExist Arguments', -> new SuperCall LOC(1)(new Super), $3, $2.soak, $1
|
||||
o 'DYNAMIC_IMPORT Arguments', -> new DynamicImportCall LOC(1)(new DynamicImport), $2
|
||||
o 'SimpleObjAssignable OptFuncExist Arguments', -> new Call (new Value $1), $3, $2.soak
|
||||
o 'ObjSpreadExpr OptFuncExist Arguments', -> new Call $1, $3, $2.soak
|
||||
]
|
||||
|
||||
ObjSpreadIdentifier: [
|
||||
o 'SimpleObjAssignable ObjSpreadAccessor', -> (new Value $1).add $2
|
||||
o 'ObjSpreadExpr ObjSpreadAccessor', -> (new Value $1).add $2
|
||||
]
|
||||
|
||||
ObjSpreadAccessor: [
|
||||
o '. Property', -> new Access $2
|
||||
o 'INDEX_START IndexValue INDEX_END', -> $2
|
||||
o 'SimpleObjAssignable Accessor', -> (new Value $1).add $2
|
||||
o 'ObjSpreadExpr Accessor', -> (new Value $1).add $2
|
||||
]
|
||||
|
||||
# A return statement from a function body.
|
||||
@@ -262,16 +316,16 @@ grammar =
|
||||
]
|
||||
|
||||
YieldReturn: [
|
||||
o 'YIELD RETURN Expression', -> new YieldReturn $3
|
||||
o 'YIELD RETURN', -> new YieldReturn
|
||||
o 'YIELD RETURN Expression', -> new YieldReturn $3, returnKeyword: LOC(2)(new Literal $2)
|
||||
o 'YIELD RETURN', -> new YieldReturn null, returnKeyword: LOC(2)(new Literal $2)
|
||||
]
|
||||
|
||||
AwaitReturn: [
|
||||
o 'AWAIT RETURN Expression', -> new AwaitReturn $3
|
||||
o 'AWAIT RETURN', -> new AwaitReturn
|
||||
o 'AWAIT RETURN Expression', -> new AwaitReturn $3, returnKeyword: LOC(2)(new Literal $2)
|
||||
o 'AWAIT RETURN', -> new AwaitReturn null, returnKeyword: LOC(2)(new Literal $2)
|
||||
]
|
||||
|
||||
# The **Code** node is the function literal. It's defined by an indented block
|
||||
# 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.
|
||||
Code: [
|
||||
o 'PARAM_START ParamList PARAM_END FuncGlyph Block', -> new Code $2, $5, $4, LOC(1)(new Literal $1)
|
||||
@@ -312,7 +366,7 @@ grammar =
|
||||
Param: [
|
||||
o 'ParamVar', -> new Param $1
|
||||
o 'ParamVar ...', -> new Param $1, null, on
|
||||
o '... ParamVar', -> new Param $2, null, on
|
||||
o '... ParamVar', -> new Param $2, null, postfix: no
|
||||
o 'ParamVar = Expression', -> new Param $1, $3
|
||||
o '...', -> new Expansion
|
||||
]
|
||||
@@ -328,7 +382,7 @@ grammar =
|
||||
# A splat that occurs outside of a parameter list.
|
||||
Splat: [
|
||||
o 'Expression ...', -> new Splat $1
|
||||
o '... Expression', -> new Splat $2
|
||||
o '... Expression', -> new Splat $2, {postfix: no}
|
||||
]
|
||||
|
||||
# Variables and properties that can be assigned to.
|
||||
@@ -354,32 +408,43 @@ grammar =
|
||||
o 'Parenthetical', -> new Value $1
|
||||
o 'Range', -> new Value $1
|
||||
o 'Invocation', -> new Value $1
|
||||
o 'DoIife', -> new Value $1
|
||||
o 'This'
|
||||
o 'Super', -> new Value $1
|
||||
o 'MetaProperty', -> new Value $1
|
||||
]
|
||||
|
||||
# A `super`-based expression that can be used as a value.
|
||||
Super: [
|
||||
o 'SUPER . Property', -> new Super LOC(3)(new Access $3), [], no, $1
|
||||
o 'SUPER INDEX_START Expression INDEX_END', -> new Super LOC(3)(new Index $3), [], no, $1
|
||||
o 'SUPER . Property', -> new Super LOC(3)(new Access $3), LOC(1)(new Literal $1)
|
||||
o 'SUPER INDEX_START Expression INDEX_END', -> new Super LOC(3)(new Index $3), LOC(1)(new Literal $1)
|
||||
o 'SUPER INDEX_START INDENT Expression OUTDENT INDEX_END', -> new Super LOC(4)(new Index $4), LOC(1)(new Literal $1)
|
||||
]
|
||||
|
||||
# A “meta-property” access e.g. `new.target` or `import.meta`, where
|
||||
# something that looks like a property is referenced on a keyword.
|
||||
MetaProperty: [
|
||||
o 'NEW_TARGET . Property', -> new MetaProperty LOC(1)(new IdentifierLiteral $1), LOC(3)(new Access $3)
|
||||
o 'IMPORT_META . Property', -> new MetaProperty LOC(1)(new IdentifierLiteral $1), LOC(3)(new Access $3)
|
||||
]
|
||||
|
||||
# The general group of accessors into an object, by property, by prototype
|
||||
# or by array index or slice.
|
||||
Accessor: [
|
||||
o '. Property', -> new Access $2
|
||||
o '?. Property', -> new Access $2, 'soak'
|
||||
o ':: Property', -> [LOC(1)(new Access new PropertyName('prototype')), LOC(2)(new Access $2)]
|
||||
o '?:: Property', -> [LOC(1)(new Access new PropertyName('prototype'), 'soak'), LOC(2)(new Access $2)]
|
||||
o '::', -> new Access new PropertyName 'prototype'
|
||||
o '?::', -> new Access new PropertyName('prototype'), 'soak'
|
||||
o '?. Property', -> new Access $2, soak: yes
|
||||
o ':: Property', -> [LOC(1)(new Access new PropertyName('prototype'), shorthand: yes), LOC(2)(new Access $2)]
|
||||
o '?:: Property', -> [LOC(1)(new Access new PropertyName('prototype'), shorthand: yes, soak: yes), LOC(2)(new Access $2)]
|
||||
o '::', -> new Access new PropertyName('prototype'), shorthand: yes
|
||||
o '?::', -> new Access new PropertyName('prototype'), shorthand: yes, soak: yes
|
||||
o 'Index'
|
||||
]
|
||||
|
||||
# Indexing into an object or array using bracket notation.
|
||||
Index: [
|
||||
o 'INDEX_START IndexValue INDEX_END', -> $2
|
||||
o 'INDEX_SOAK Index', -> extend $2, soak: yes
|
||||
o 'INDEX_START IndexValue INDEX_END', -> $2
|
||||
o 'INDEX_START INDENT IndexValue OUTDENT INDEX_END', -> $3
|
||||
o 'INDEX_SOAK Index', -> extend $2, soak: yes
|
||||
]
|
||||
|
||||
IndexValue: [
|
||||
@@ -416,13 +481,20 @@ grammar =
|
||||
]
|
||||
|
||||
Import: [
|
||||
o 'IMPORT String', -> new ImportDeclaration null, $2
|
||||
o 'IMPORT ImportDefaultSpecifier FROM String', -> new ImportDeclaration new ImportClause($2, null), $4
|
||||
o 'IMPORT ImportNamespaceSpecifier FROM String', -> new ImportDeclaration new ImportClause(null, $2), $4
|
||||
o 'IMPORT { } FROM String', -> new ImportDeclaration new ImportClause(null, new ImportSpecifierList []), $5
|
||||
o 'IMPORT { ImportSpecifierList OptComma } FROM String', -> new ImportDeclaration new ImportClause(null, new ImportSpecifierList $3), $7
|
||||
o 'IMPORT ImportDefaultSpecifier , ImportNamespaceSpecifier FROM String', -> new ImportDeclaration new ImportClause($2, $4), $6
|
||||
o 'IMPORT ImportDefaultSpecifier , { ImportSpecifierList OptComma } FROM String', -> new ImportDeclaration new ImportClause($2, new ImportSpecifierList $5), $9
|
||||
o 'IMPORT String', -> new ImportDeclaration null, $2
|
||||
o 'IMPORT String ASSERT Object', -> new ImportDeclaration null, $2, $4
|
||||
o 'IMPORT ImportDefaultSpecifier FROM String', -> new ImportDeclaration new ImportClause($2, null), $4
|
||||
o 'IMPORT ImportDefaultSpecifier FROM String ASSERT Object', -> new ImportDeclaration new ImportClause($2, null), $4, $6
|
||||
o 'IMPORT ImportNamespaceSpecifier FROM String', -> new ImportDeclaration new ImportClause(null, $2), $4
|
||||
o 'IMPORT ImportNamespaceSpecifier FROM String ASSERT Object', -> new ImportDeclaration new ImportClause(null, $2), $4, $6
|
||||
o 'IMPORT { } FROM String', -> new ImportDeclaration new ImportClause(null, new ImportSpecifierList []), $5
|
||||
o 'IMPORT { } FROM String ASSERT Object', -> new ImportDeclaration new ImportClause(null, new ImportSpecifierList []), $5, $7
|
||||
o 'IMPORT { ImportSpecifierList OptComma } FROM String', -> new ImportDeclaration new ImportClause(null, new ImportSpecifierList $3), $7
|
||||
o 'IMPORT { ImportSpecifierList OptComma } FROM String ASSERT Object', -> new ImportDeclaration new ImportClause(null, new ImportSpecifierList $3), $7, $9
|
||||
o 'IMPORT ImportDefaultSpecifier , ImportNamespaceSpecifier FROM String', -> new ImportDeclaration new ImportClause($2, $4), $6
|
||||
o 'IMPORT ImportDefaultSpecifier , ImportNamespaceSpecifier FROM String ASSERT Object', -> new ImportDeclaration new ImportClause($2, $4), $6, $8
|
||||
o 'IMPORT ImportDefaultSpecifier , { ImportSpecifierList OptComma } FROM String', -> new ImportDeclaration new ImportClause($2, new ImportSpecifierList $5), $9
|
||||
o 'IMPORT ImportDefaultSpecifier , { ImportSpecifierList OptComma } FROM String ASSERT Object', -> new ImportDeclaration new ImportClause($2, new ImportSpecifierList $5), $9, $11
|
||||
]
|
||||
|
||||
ImportSpecifierList: [
|
||||
@@ -436,8 +508,8 @@ grammar =
|
||||
ImportSpecifier: [
|
||||
o 'Identifier', -> new ImportSpecifier $1
|
||||
o 'Identifier AS Identifier', -> new ImportSpecifier $1, $3
|
||||
o 'DEFAULT', -> new ImportSpecifier new Literal $1
|
||||
o 'DEFAULT AS Identifier', -> new ImportSpecifier new Literal($1), $3
|
||||
o 'DEFAULT', -> new ImportSpecifier LOC(1)(new DefaultLiteral $1)
|
||||
o 'DEFAULT AS Identifier', -> new ImportSpecifier LOC(1)(new DefaultLiteral($1)), $3
|
||||
]
|
||||
|
||||
ImportDefaultSpecifier: [
|
||||
@@ -449,19 +521,23 @@ grammar =
|
||||
]
|
||||
|
||||
Export: [
|
||||
o 'EXPORT { }', -> new ExportNamedDeclaration new ExportSpecifierList []
|
||||
o 'EXPORT { ExportSpecifierList OptComma }', -> new ExportNamedDeclaration new ExportSpecifierList $3
|
||||
o 'EXPORT Class', -> new ExportNamedDeclaration $2
|
||||
o 'EXPORT Identifier = Expression', -> new ExportNamedDeclaration new Assign $2, $4, null,
|
||||
moduleDeclaration: 'export'
|
||||
o 'EXPORT Identifier = TERMINATOR Expression', -> new ExportNamedDeclaration new Assign $2, $5, null,
|
||||
moduleDeclaration: 'export'
|
||||
o 'EXPORT Identifier = INDENT Expression OUTDENT', -> new ExportNamedDeclaration new Assign $2, $5, null,
|
||||
moduleDeclaration: 'export'
|
||||
o 'EXPORT DEFAULT Expression', -> new ExportDefaultDeclaration $3
|
||||
o 'EXPORT DEFAULT INDENT Object OUTDENT', -> new ExportDefaultDeclaration new Value $4
|
||||
o 'EXPORT EXPORT_ALL FROM String', -> new ExportAllDeclaration new Literal($2), $4
|
||||
o 'EXPORT { ExportSpecifierList OptComma } FROM String', -> new ExportNamedDeclaration new ExportSpecifierList($3), $7
|
||||
o 'EXPORT { }', -> new ExportNamedDeclaration new ExportSpecifierList []
|
||||
o 'EXPORT { ExportSpecifierList OptComma }', -> new ExportNamedDeclaration new ExportSpecifierList $3
|
||||
o 'EXPORT Class', -> new ExportNamedDeclaration $2
|
||||
o 'EXPORT Identifier = Expression', -> new ExportNamedDeclaration LOC(2,4)(new Assign $2, $4, null,
|
||||
moduleDeclaration: 'export')
|
||||
o 'EXPORT Identifier = TERMINATOR Expression', -> new ExportNamedDeclaration LOC(2,5)(new Assign $2, $5, null,
|
||||
moduleDeclaration: 'export')
|
||||
o 'EXPORT Identifier = INDENT Expression OUTDENT', -> new ExportNamedDeclaration LOC(2,6)(new Assign $2, $5, null,
|
||||
moduleDeclaration: 'export')
|
||||
o 'EXPORT DEFAULT Expression', -> new ExportDefaultDeclaration $3
|
||||
o 'EXPORT DEFAULT INDENT Object OUTDENT', -> new ExportDefaultDeclaration new Value $4
|
||||
o 'EXPORT EXPORT_ALL FROM String', -> new ExportAllDeclaration new Literal($2), $4
|
||||
o 'EXPORT EXPORT_ALL FROM String ASSERT Object', -> new ExportAllDeclaration new Literal($2), $4, $6
|
||||
o 'EXPORT { } FROM String', -> new ExportNamedDeclaration new ExportSpecifierList([]), $5
|
||||
o 'EXPORT { } FROM String ASSERT Object', -> new ExportNamedDeclaration new ExportSpecifierList([]), $5, $7
|
||||
o 'EXPORT { ExportSpecifierList OptComma } FROM String', -> new ExportNamedDeclaration new ExportSpecifierList($3), $7
|
||||
o 'EXPORT { ExportSpecifierList OptComma } FROM String ASSERT Object', -> new ExportNamedDeclaration new ExportSpecifierList($3), $7, $9
|
||||
]
|
||||
|
||||
ExportSpecifierList: [
|
||||
@@ -475,28 +551,29 @@ grammar =
|
||||
ExportSpecifier: [
|
||||
o 'Identifier', -> new ExportSpecifier $1
|
||||
o 'Identifier AS Identifier', -> new ExportSpecifier $1, $3
|
||||
o 'Identifier AS DEFAULT', -> new ExportSpecifier $1, new Literal $3
|
||||
o 'DEFAULT', -> new ExportSpecifier new Literal $1
|
||||
o 'DEFAULT AS Identifier', -> new ExportSpecifier new Literal($1), $3
|
||||
o 'Identifier AS DEFAULT', -> new ExportSpecifier $1, LOC(3)(new DefaultLiteral $3)
|
||||
o 'DEFAULT', -> new ExportSpecifier LOC(1)(new DefaultLiteral $1)
|
||||
o 'DEFAULT AS Identifier', -> new ExportSpecifier LOC(1)(new DefaultLiteral($1)), $3
|
||||
]
|
||||
|
||||
# Ordinary function invocation, or a chained series of calls.
|
||||
Invocation: [
|
||||
o 'Value OptFuncExist String', -> new TaggedTemplateCall $1, $3, $2
|
||||
o 'Value OptFuncExist Arguments', -> new Call $1, $3, $2
|
||||
o 'SUPER OptFuncExist Arguments', -> new SuperCall LOC(1)(new Super), $3, $2, $1
|
||||
o 'Value OptFuncExist String', -> new TaggedTemplateCall $1, $3, $2.soak
|
||||
o 'Value OptFuncExist Arguments', -> new Call $1, $3, $2.soak
|
||||
o 'SUPER OptFuncExist Arguments', -> new SuperCall LOC(1)(new Super), $3, $2.soak, $1
|
||||
o 'DYNAMIC_IMPORT Arguments', -> new DynamicImportCall LOC(1)(new DynamicImport), $2
|
||||
]
|
||||
|
||||
# An optional existence check on a function.
|
||||
OptFuncExist: [
|
||||
o '', -> no
|
||||
o 'FUNC_EXIST', -> yes
|
||||
o '', -> soak: no
|
||||
o 'FUNC_EXIST', -> soak: yes
|
||||
]
|
||||
|
||||
# The list of arguments to a function call.
|
||||
Arguments: [
|
||||
o 'CALL_START CALL_END', -> []
|
||||
o 'CALL_START ArgList OptComma CALL_END', -> $2
|
||||
o 'CALL_START ArgList OptComma CALL_END', -> $2.implicit = $1.generated; $2
|
||||
]
|
||||
|
||||
# A reference to the *this* current object.
|
||||
@@ -519,24 +596,24 @@ grammar =
|
||||
|
||||
# Inclusive and exclusive range dots.
|
||||
RangeDots: [
|
||||
o '..', -> 'inclusive'
|
||||
o '...', -> 'exclusive'
|
||||
o '..', -> exclusive: no
|
||||
o '...', -> exclusive: yes
|
||||
]
|
||||
|
||||
# The CoffeeScript range literal.
|
||||
Range: [
|
||||
o '[ Expression RangeDots Expression ]', -> new Range $2, $4, $3
|
||||
o '[ ExpressionLine RangeDots Expression ]', -> new Range $2, $4, $3
|
||||
o '[ Expression RangeDots Expression ]', -> new Range $2, $4, if $3.exclusive then 'exclusive' else 'inclusive'
|
||||
o '[ ExpressionLine RangeDots Expression ]', -> new Range $2, $4, if $3.exclusive then 'exclusive' else 'inclusive'
|
||||
]
|
||||
|
||||
# Array slice literals.
|
||||
Slice: [
|
||||
o 'Expression RangeDots Expression', -> new Range $1, $3, $2
|
||||
o 'Expression RangeDots', -> new Range $1, null, $2
|
||||
o 'ExpressionLine RangeDots Expression', -> new Range $1, $3, $2
|
||||
o 'ExpressionLine RangeDots', -> new Range $1, null, $2
|
||||
o 'RangeDots Expression', -> new Range null, $2, $1
|
||||
o 'RangeDots', -> new Range null, null, $1
|
||||
o 'Expression RangeDots Expression', -> new Range $1, $3, if $2.exclusive then 'exclusive' else 'inclusive'
|
||||
o 'Expression RangeDots', -> new Range $1, null, if $2.exclusive then 'exclusive' else 'inclusive'
|
||||
o 'ExpressionLine RangeDots Expression', -> new Range $1, $3, if $2.exclusive then 'exclusive' else 'inclusive'
|
||||
o 'ExpressionLine RangeDots', -> new Range $1, null, if $2.exclusive then 'exclusive' else 'inclusive'
|
||||
o 'RangeDots Expression', -> new Range null, $2, if $1.exclusive then 'exclusive' else 'inclusive'
|
||||
o 'RangeDots', -> new Range null, null, if $1.exclusive then 'exclusive' else 'inclusive'
|
||||
]
|
||||
|
||||
# The **ArgList** is the list of objects passed into a function call
|
||||
@@ -562,7 +639,7 @@ grammar =
|
||||
ArgElisionList: [
|
||||
o 'ArgElision'
|
||||
o 'ArgElisionList , ArgElision', -> $1.concat $3
|
||||
o 'ArgElisionList OptElisions TERMINATOR ArgElision', -> $1.concat $2, $4
|
||||
o 'ArgElisionList OptComma TERMINATOR ArgElision', -> $1.concat $4
|
||||
o 'INDENT ArgElisionList OptElisions OUTDENT', -> $2.concat $3
|
||||
o 'ArgElisionList OptElisions INDENT ArgElisionList OptElisions OUTDENT', -> $1.concat $2, $4, $5
|
||||
]
|
||||
@@ -584,6 +661,7 @@ grammar =
|
||||
|
||||
Elision: [
|
||||
o ',', -> new Elision
|
||||
o 'Elision TERMINATOR', -> $1
|
||||
]
|
||||
|
||||
# Just simple, comma-separated, required arguments (no fancy syntax). We need
|
||||
@@ -599,16 +677,16 @@ grammar =
|
||||
# The variants of *try/catch/finally* exception handling blocks.
|
||||
Try: [
|
||||
o 'TRY Block', -> new Try $2
|
||||
o 'TRY Block Catch', -> new Try $2, $3[0], $3[1]
|
||||
o 'TRY Block FINALLY Block', -> new Try $2, null, null, $4
|
||||
o 'TRY Block Catch FINALLY Block', -> new Try $2, $3[0], $3[1], $5
|
||||
o 'TRY Block Catch', -> new Try $2, $3
|
||||
o 'TRY Block FINALLY Block', -> new Try $2, null, $4, LOC(3)(new Literal $3)
|
||||
o 'TRY Block Catch FINALLY Block', -> new Try $2, $3, $5, LOC(4)(new Literal $4)
|
||||
]
|
||||
|
||||
# A catch clause names its error and runs a block of code.
|
||||
Catch: [
|
||||
o 'CATCH Identifier Block', -> [$2, $3]
|
||||
o 'CATCH Object Block', -> [LOC(2)(new Value($2)), $3]
|
||||
o 'CATCH Block', -> [null, $2]
|
||||
o 'CATCH Identifier Block', -> new Catch $3, $2
|
||||
o 'CATCH Object Block', -> new Catch $3, LOC(2)(new Value($2))
|
||||
o 'CATCH Block', -> new Catch $2
|
||||
]
|
||||
|
||||
# Throw an exception object.
|
||||
@@ -648,22 +726,22 @@ grammar =
|
||||
While: [
|
||||
o 'WhileSource Block', -> $1.addBody $2
|
||||
o 'WhileLineSource Block', -> $1.addBody $2
|
||||
o 'Statement WhileSource', -> $2.addBody LOC(1) Block.wrap([$1])
|
||||
o 'Expression WhileSource', -> $2.addBody LOC(1) Block.wrap([$1])
|
||||
o 'Statement WhileSource', -> (Object.assign $2, postfix: yes).addBody LOC(1) Block.wrap([$1])
|
||||
o 'Expression WhileSource', -> (Object.assign $2, postfix: yes).addBody LOC(1) Block.wrap([$1])
|
||||
o 'Loop', -> $1
|
||||
]
|
||||
|
||||
Loop: [
|
||||
o 'LOOP Block', -> new While(LOC(1) new BooleanLiteral 'true').addBody $2
|
||||
o 'LOOP Expression', -> new While(LOC(1) new BooleanLiteral 'true').addBody LOC(2) Block.wrap [$2]
|
||||
o 'LOOP Block', -> new While(LOC(1)(new BooleanLiteral 'true'), isLoop: yes).addBody $2
|
||||
o 'LOOP Expression', -> new While(LOC(1)(new BooleanLiteral 'true'), isLoop: yes).addBody LOC(2) Block.wrap [$2]
|
||||
]
|
||||
|
||||
# Array, object, and range comprehensions, at the most generic level.
|
||||
# Comprehensions can either be normal, with a block of expressions to execute,
|
||||
# or postfix, with a single expression.
|
||||
For: [
|
||||
o 'Statement ForBody', -> $2.addBody $1
|
||||
o 'Expression ForBody', -> $2.addBody $1
|
||||
o 'Statement ForBody', -> $2.postfix = yes; $2.addBody $1
|
||||
o 'Expression ForBody', -> $2.postfix = yes; $2.addBody $1
|
||||
o 'ForBody Block', -> $1.addBody $2
|
||||
o 'ForLineBody Block', -> $1.addBody $2
|
||||
]
|
||||
@@ -707,7 +785,7 @@ grammar =
|
||||
]
|
||||
|
||||
# The source of a comprehension is an array or object with an optional guard
|
||||
# clause. If it's an array comprehension, you can also choose to step through
|
||||
# clause. If it’s an array comprehension, you can also choose to step through
|
||||
# in fixed-size increments.
|
||||
ForSource: [
|
||||
o 'FORIN Expression', -> source: $2
|
||||
@@ -756,21 +834,21 @@ grammar =
|
||||
Switch: [
|
||||
o 'SWITCH Expression INDENT Whens OUTDENT', -> new Switch $2, $4
|
||||
o 'SWITCH ExpressionLine INDENT Whens OUTDENT', -> new Switch $2, $4
|
||||
o 'SWITCH Expression INDENT Whens ELSE Block OUTDENT', -> new Switch $2, $4, $6
|
||||
o 'SWITCH ExpressionLine INDENT Whens ELSE Block OUTDENT', -> new Switch $2, $4, $6
|
||||
o 'SWITCH Expression INDENT Whens ELSE Block OUTDENT', -> new Switch $2, $4, LOC(5,6) $6
|
||||
o 'SWITCH ExpressionLine INDENT Whens ELSE Block OUTDENT', -> new Switch $2, $4, LOC(5,6) $6
|
||||
o 'SWITCH INDENT Whens OUTDENT', -> new Switch null, $3
|
||||
o 'SWITCH INDENT Whens ELSE Block OUTDENT', -> new Switch null, $3, $5
|
||||
o 'SWITCH INDENT Whens ELSE Block OUTDENT', -> new Switch null, $3, LOC(4,5) $5
|
||||
]
|
||||
|
||||
Whens: [
|
||||
o 'When'
|
||||
o 'When', -> [$1]
|
||||
o 'Whens When', -> $1.concat $2
|
||||
]
|
||||
|
||||
# An individual **When** clause, with action.
|
||||
When: [
|
||||
o 'LEADING_WHEN SimpleArgs Block', -> [[$2, $3]]
|
||||
o 'LEADING_WHEN SimpleArgs Block TERMINATOR', -> [[$2, $3]]
|
||||
o 'LEADING_WHEN SimpleArgs Block', -> new SwitchWhen $2, $3
|
||||
o 'LEADING_WHEN SimpleArgs Block TERMINATOR', -> LOC(1, 3) new SwitchWhen $2, $3
|
||||
]
|
||||
|
||||
# The most basic form of *if* is a condition and an action. The following
|
||||
@@ -786,8 +864,8 @@ grammar =
|
||||
If: [
|
||||
o 'IfBlock'
|
||||
o 'IfBlock ELSE Block', -> $1.addElse $3
|
||||
o 'Statement POST_IF Expression', -> new If $3, LOC(1)(Block.wrap [$1]), type: $2, statement: true
|
||||
o 'Expression POST_IF Expression', -> new If $3, LOC(1)(Block.wrap [$1]), type: $2, statement: true
|
||||
o 'Statement POST_IF Expression', -> new If $3, LOC(1)(Block.wrap [$1]), type: $2, postfix: true
|
||||
o 'Expression POST_IF Expression', -> new If $3, LOC(1)(Block.wrap [$1]), type: $2, postfix: true
|
||||
]
|
||||
|
||||
IfBlockLine: [
|
||||
@@ -798,8 +876,8 @@ grammar =
|
||||
IfLine: [
|
||||
o 'IfBlockLine'
|
||||
o 'IfBlockLine ELSE Block', -> $1.addElse $3
|
||||
o 'Statement POST_IF ExpressionLine', -> new If $3, LOC(1)(Block.wrap [$1]), type: $2, statement: true
|
||||
o 'Expression POST_IF ExpressionLine', -> new If $3, LOC(1)(Block.wrap [$1]), type: $2, statement: true
|
||||
o 'Statement POST_IF ExpressionLine', -> new If $3, LOC(1)(Block.wrap [$1]), type: $2, postfix: true
|
||||
o 'Expression POST_IF ExpressionLine', -> new If $3, LOC(1)(Block.wrap [$1]), type: $2, postfix: true
|
||||
]
|
||||
|
||||
# Arithmetic and logical operators, working on one or more operands.
|
||||
@@ -810,11 +888,14 @@ grammar =
|
||||
# rules are necessary.
|
||||
OperationLine: [
|
||||
o 'UNARY ExpressionLine', -> new Op $1, $2
|
||||
o 'DO ExpressionLine', -> new Op $1, $2
|
||||
o 'DO_IIFE CodeLine', -> new Op $1, $2
|
||||
]
|
||||
|
||||
Operation: [
|
||||
o 'UNARY Expression', -> new Op $1 , $2
|
||||
o 'UNARY_MATH Expression', -> new Op $1 , $2
|
||||
o 'UNARY Expression', -> new Op $1.toString(), $2, undefined, undefined, originalOperator: $1.original
|
||||
o 'DO Expression', -> new Op $1, $2
|
||||
o 'UNARY_MATH Expression', -> new Op $1, $2
|
||||
o '- Expression', (-> new Op '-', $2), prec: 'UNARY_MATH'
|
||||
o '+ Expression', (-> new Op '+', $2), prec: 'UNARY_MATH'
|
||||
|
||||
@@ -835,25 +916,25 @@ grammar =
|
||||
o 'Expression MATH Expression', -> new Op $2, $1, $3
|
||||
o 'Expression ** Expression', -> new Op $2, $1, $3
|
||||
o 'Expression SHIFT Expression', -> new Op $2, $1, $3
|
||||
o 'Expression COMPARE Expression', -> new Op $2, $1, $3
|
||||
o 'Expression COMPARE Expression', -> new Op $2.toString(), $1, $3, undefined, originalOperator: $2.original
|
||||
o 'Expression & Expression', -> new Op $2, $1, $3
|
||||
o 'Expression ^ Expression', -> new Op $2, $1, $3
|
||||
o 'Expression | Expression', -> new Op $2, $1, $3
|
||||
o 'Expression && Expression', -> new Op $2, $1, $3
|
||||
o 'Expression || Expression', -> new Op $2, $1, $3
|
||||
o 'Expression && Expression', -> new Op $2.toString(), $1, $3, undefined, originalOperator: $2.original
|
||||
o 'Expression || Expression', -> new Op $2.toString(), $1, $3, undefined, originalOperator: $2.original
|
||||
o 'Expression BIN? Expression', -> new Op $2, $1, $3
|
||||
o 'Expression RELATION Expression', ->
|
||||
if $2.charAt(0) is '!'
|
||||
new Op($2[1..], $1, $3).invert()
|
||||
else
|
||||
new Op $2, $1, $3
|
||||
o 'Expression RELATION Expression', -> new Op $2.toString(), $1, $3, undefined, invertOperator: $2.invert?.original ? $2.invert
|
||||
|
||||
o 'SimpleAssignable COMPOUND_ASSIGN
|
||||
Expression', -> new Assign $1, $3, $2
|
||||
Expression', -> new Assign $1, $3, $2.toString(), originalContext: $2.original
|
||||
o 'SimpleAssignable COMPOUND_ASSIGN
|
||||
INDENT Expression OUTDENT', -> new Assign $1, $4, $2
|
||||
INDENT Expression OUTDENT', -> new Assign $1, $4, $2.toString(), originalContext: $2.original
|
||||
o 'SimpleAssignable COMPOUND_ASSIGN TERMINATOR
|
||||
Expression', -> new Assign $1, $4, $2
|
||||
Expression', -> new Assign $1, $4, $2.toString(), originalContext: $2.original
|
||||
]
|
||||
|
||||
DoIife: [
|
||||
o 'DO_IIFE Code', -> new Op $1 , $2
|
||||
]
|
||||
|
||||
# Precedence
|
||||
@@ -868,11 +949,12 @@ grammar =
|
||||
#
|
||||
# (2 + 3) * 4
|
||||
operators = [
|
||||
['right', 'DO_IIFE']
|
||||
['left', '.', '?.', '::', '?::']
|
||||
['left', 'CALL_START', 'CALL_END']
|
||||
['nonassoc', '++', '--']
|
||||
['left', '?']
|
||||
['right', 'UNARY']
|
||||
['right', 'UNARY', 'DO']
|
||||
['right', 'AWAIT']
|
||||
['right', '**']
|
||||
['right', 'UNARY_MATH']
|
||||
@@ -891,7 +973,7 @@ operators = [
|
||||
['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']
|
||||
['right', 'IF', 'ELSE', 'FOR', 'WHILE', 'UNTIL', 'LOOP', 'SUPER', 'CLASS', 'IMPORT', 'EXPORT', 'DYNAMIC_IMPORT']
|
||||
['left', 'POST_IF']
|
||||
]
|
||||
|
||||
|
||||
@@ -107,15 +107,36 @@ buildLocationData = (first, last) ->
|
||||
first_column: first.first_column
|
||||
last_line: last.last_line
|
||||
last_column: last.last_column
|
||||
last_line_exclusive: last.last_line_exclusive
|
||||
last_column_exclusive: last.last_column_exclusive
|
||||
range: [
|
||||
first.range[0]
|
||||
last.range[1]
|
||||
]
|
||||
|
||||
# Build a list of all comments attached to tokens.
|
||||
exports.extractAllCommentTokens = (tokens) ->
|
||||
allCommentsObj = {}
|
||||
for token in tokens when token.comments
|
||||
for comment in token.comments
|
||||
commentKey = comment.locationData.range[0]
|
||||
allCommentsObj[commentKey] = comment
|
||||
sortedKeys = Object.keys(allCommentsObj).sort (a, b) -> a - b
|
||||
for key in sortedKeys
|
||||
allCommentsObj[key]
|
||||
|
||||
# Get a lookup hash for a token based on its location data.
|
||||
# Multiple tokens might have the same location hash, but using exclusive
|
||||
# location data distinguishes e.g. zero-length generated tokens from
|
||||
# actual source tokens.
|
||||
buildLocationHash = (loc) ->
|
||||
"#{loc.first_line}x#{loc.first_column}-#{loc.last_line}x#{loc.last_column}"
|
||||
"#{loc.range[0]}-#{loc.range[1]}"
|
||||
|
||||
# Build a dictionary of extra token properties organized by tokens’ locations
|
||||
# used as lookup hashes.
|
||||
buildTokenDataDictionary = (parserState) ->
|
||||
exports.buildTokenDataDictionary = buildTokenDataDictionary = (tokens) ->
|
||||
tokenData = {}
|
||||
for token in parserState.parser.tokens when token.comments
|
||||
for token in tokens when token.comments
|
||||
tokenHash = buildLocationHash token[2]
|
||||
# Multiple tokens might have the same location hash, such as the generated
|
||||
# `JS` tokens added at the start or end of the token stream to hold
|
||||
@@ -132,15 +153,18 @@ buildTokenDataDictionary = (parserState) ->
|
||||
# This returns a function which takes an object as a parameter, and if that
|
||||
# object is an AST node, updates that object's locationData.
|
||||
# The object is returned either way.
|
||||
exports.addDataToNode = (parserState, first, last) ->
|
||||
exports.addDataToNode = (parserState, firstLocationData, firstValue, lastLocationData, lastValue, forceUpdateLocation = yes) ->
|
||||
(obj) ->
|
||||
# Add location data.
|
||||
if obj?.updateLocationDataIfMissing? and first?
|
||||
obj.updateLocationDataIfMissing buildLocationData(first, last)
|
||||
locationData = buildLocationData(firstValue?.locationData ? firstLocationData, lastValue?.locationData ? lastLocationData)
|
||||
if obj?.updateLocationDataIfMissing? and firstLocationData?
|
||||
obj.updateLocationDataIfMissing locationData, forceUpdateLocation
|
||||
else
|
||||
obj.locationData = locationData
|
||||
|
||||
# Add comments, building the dictionary of token data if it hasn’t been
|
||||
# built yet.
|
||||
parserState.tokenData ?= buildTokenDataDictionary parserState
|
||||
parserState.tokenData ?= buildTokenDataDictionary parserState.parser.tokens
|
||||
if obj.locationData?
|
||||
objHash = buildLocationHash obj.locationData
|
||||
if parserState.tokenData[objHash]?.comments?
|
||||
@@ -164,6 +188,13 @@ exports.locationDataToString = (obj) ->
|
||||
else
|
||||
"No location data"
|
||||
|
||||
# Generate a unique anonymous file name so we can distinguish source map cache
|
||||
# entries for any number of anonymous scripts.
|
||||
exports.anonymousFileName = do ->
|
||||
n = 0
|
||||
->
|
||||
"<anonymous-#{n++}>"
|
||||
|
||||
# A `.coffee.md` compatible version of `basename`, that returns the file sans-extension.
|
||||
exports.baseFileName = (file, stripExt = no, useWinPathSep = no) ->
|
||||
pathSep = if useWinPathSep then /\\|\// else /\//
|
||||
@@ -214,7 +245,11 @@ syntaxErrorToString = ->
|
||||
last_line ?= first_line
|
||||
last_column ?= first_column
|
||||
|
||||
filename = @filename or '[stdin]'
|
||||
if @filename?.startsWith '<anonymous'
|
||||
filename = '[stdin]'
|
||||
else
|
||||
filename = @filename or '[stdin]'
|
||||
|
||||
codeLine = @code.split('\n')[first_line]
|
||||
start = first_column
|
||||
# Show only the first line on multi-line errors.
|
||||
@@ -243,3 +278,54 @@ exports.nameWhitespaceCharacter = (string) ->
|
||||
when '\r' then 'carriage return'
|
||||
when '\t' then 'tab'
|
||||
else string
|
||||
|
||||
exports.parseNumber = (string) ->
|
||||
return NaN unless string?
|
||||
|
||||
base = switch string.charAt 1
|
||||
when 'b' then 2
|
||||
when 'o' then 8
|
||||
when 'x' then 16
|
||||
else null
|
||||
|
||||
if base?
|
||||
parseInt string[2..].replace(/_/g, ''), base
|
||||
else
|
||||
parseFloat string.replace(/_/g, '')
|
||||
|
||||
exports.isFunction = (obj) -> Object::toString.call(obj) is '[object Function]'
|
||||
exports.isNumber = isNumber = (obj) -> Object::toString.call(obj) is '[object Number]'
|
||||
exports.isString = isString = (obj) -> Object::toString.call(obj) is '[object String]'
|
||||
exports.isBoolean = isBoolean = (obj) -> obj is yes or obj is no or Object::toString.call(obj) is '[object Boolean]'
|
||||
exports.isPlainObject = (obj) -> typeof obj is 'object' and !!obj and not Array.isArray(obj) and not isNumber(obj) and not isString(obj) and not isBoolean(obj)
|
||||
|
||||
unicodeCodePointToUnicodeEscapes = (codePoint) ->
|
||||
toUnicodeEscape = (val) ->
|
||||
str = val.toString 16
|
||||
"\\u#{repeat '0', 4 - str.length}#{str}"
|
||||
return toUnicodeEscape(codePoint) if codePoint < 0x10000
|
||||
# surrogate pair
|
||||
high = Math.floor((codePoint - 0x10000) / 0x400) + 0xD800
|
||||
low = (codePoint - 0x10000) % 0x400 + 0xDC00
|
||||
"#{toUnicodeEscape(high)}#{toUnicodeEscape(low)}"
|
||||
|
||||
# Replace `\u{...}` with `\uxxxx[\uxxxx]` in regexes without `u` flag
|
||||
exports.replaceUnicodeCodePointEscapes = (str, {flags, error, delimiter = ''} = {}) ->
|
||||
shouldReplace = flags? and 'u' not in flags
|
||||
str.replace UNICODE_CODE_POINT_ESCAPE, (match, escapedBackslash, codePointHex, offset) ->
|
||||
return escapedBackslash if escapedBackslash
|
||||
|
||||
codePointDecimal = parseInt codePointHex, 16
|
||||
if codePointDecimal > 0x10ffff
|
||||
error "unicode code point escapes greater than \\u{10ffff} are not allowed",
|
||||
offset: offset + delimiter.length
|
||||
length: codePointHex.length + 4
|
||||
return match unless shouldReplace
|
||||
|
||||
unicodeCodePointToUnicodeEscapes codePointDecimal
|
||||
|
||||
UNICODE_CODE_POINT_ESCAPE = ///
|
||||
( \\\\ ) # Make sure the escape isn’t escaped.
|
||||
|
|
||||
\\u\{ ( [\da-fA-F]+ ) \}
|
||||
///g
|
||||
|
||||
@@ -37,7 +37,7 @@ CoffeeScript.run = (code, options = {}) ->
|
||||
|
||||
# Set the filename.
|
||||
mainModule.filename = process.argv[1] =
|
||||
if options.filename then fs.realpathSync(options.filename) else '<anonymous>'
|
||||
if options.filename then fs.realpathSync(options.filename) else helpers.anonymousFileName()
|
||||
|
||||
# Clear the module cache.
|
||||
mainModule.moduleCache and= {}
|
||||
@@ -52,10 +52,12 @@ CoffeeScript.run = (code, options = {}) ->
|
||||
# Save the options for compiling child imports.
|
||||
mainModule.options = options
|
||||
|
||||
options.filename = mainModule.filename
|
||||
options.inlineMap = true
|
||||
|
||||
# Compile.
|
||||
if not helpers.isCoffee(mainModule.filename) or require.extensions
|
||||
answer = CoffeeScript.compile code, options
|
||||
code = answer.js ? answer
|
||||
answer = CoffeeScript.compile code, options
|
||||
code = answer.js ? answer
|
||||
|
||||
mainModule._compile code, mainModule.filename
|
||||
|
||||
@@ -110,8 +112,8 @@ if require.extensions
|
||||
Use CoffeeScript.register() or require the coffeescript/register module to require #{ext} files.
|
||||
"""
|
||||
|
||||
CoffeeScript._compileFile = (filename, options = {}) ->
|
||||
raw = fs.readFileSync filename, 'utf8'
|
||||
CoffeeScript._compileRawFileContent = (raw, filename, options = {}) ->
|
||||
|
||||
# Strip the Unicode byte order mark, if this file begins with one.
|
||||
stripped = if raw.charCodeAt(0) is 0xFEFF then raw.substring 1 else raw
|
||||
|
||||
@@ -119,7 +121,6 @@ CoffeeScript._compileFile = (filename, options = {}) ->
|
||||
filename: filename
|
||||
literate: helpers.isLiterate filename
|
||||
sourceFiles: [filename]
|
||||
inlineMap: yes # Always generate a source map, so that stack traces line up.
|
||||
|
||||
try
|
||||
answer = CoffeeScript.compile stripped, options
|
||||
@@ -131,4 +132,29 @@ CoffeeScript._compileFile = (filename, options = {}) ->
|
||||
|
||||
answer
|
||||
|
||||
CoffeeScript._compileFile = (filename, options = {}) ->
|
||||
raw = fs.readFileSync filename, 'utf8'
|
||||
|
||||
CoffeeScript._compileRawFileContent raw, filename, options
|
||||
|
||||
module.exports = CoffeeScript
|
||||
|
||||
# Explicitly define all named exports so that Node’s automatic detection of
|
||||
# named exports from CommonJS packages finds all of them. This enables consuming
|
||||
# packages to write code like `import { compile } from 'coffeescript'`.
|
||||
# Don’t simplify this into a loop or similar; the `module.exports.name` part is
|
||||
# essential for Node’s algorithm to successfully detect the name.
|
||||
module.exports.VERSION = CoffeeScript.VERSION
|
||||
module.exports.FILE_EXTENSIONS = CoffeeScript.FILE_EXTENSIONS
|
||||
module.exports.helpers = CoffeeScript.helpers
|
||||
module.exports.registerCompiled = CoffeeScript.registerCompiled
|
||||
module.exports.compile = CoffeeScript.compile
|
||||
module.exports.tokens = CoffeeScript.tokens
|
||||
module.exports.nodes = CoffeeScript.nodes
|
||||
module.exports.register = CoffeeScript.register
|
||||
module.exports.eval = CoffeeScript.eval
|
||||
module.exports.run = CoffeeScript.run
|
||||
module.exports.transpile = CoffeeScript.transpile
|
||||
module.exports.patchStackTrace = CoffeeScript.patchStackTrace
|
||||
module.exports._compileRawFileContent = CoffeeScript._compileRawFileContent
|
||||
module.exports._compileFile = CoffeeScript._compileFile
|
||||
|
||||
783
src/lexer.coffee
783
src/lexer.coffee
File diff suppressed because it is too large
Load Diff
2981
src/nodes.coffee
2981
src/nodes.coffee
File diff suppressed because it is too large
Load Diff
@@ -3,11 +3,29 @@ child_process = require 'child_process'
|
||||
helpers = require './helpers'
|
||||
path = require 'path'
|
||||
|
||||
{patchStackTrace} = CoffeeScript
|
||||
|
||||
# Check if Node's built-in source map stack trace transformations are enabled.
|
||||
nodeSourceMapsSupportEnabled = process? and (
|
||||
process.execArgv.includes('--enable-source-maps') or
|
||||
process.env.NODE_OPTIONS?.includes('--enable-source-maps')
|
||||
)
|
||||
|
||||
unless Error.prepareStackTrace or nodeSourceMapsSupportEnabled
|
||||
cacheSourceMaps = true
|
||||
patchStackTrace()
|
||||
|
||||
# Load and run a CoffeeScript file for Node, stripping any `BOM`s.
|
||||
loadFile = (module, filename) ->
|
||||
options = module.options or getRootModule(module).options
|
||||
answer = CoffeeScript._compileFile filename, options
|
||||
module._compile answer, filename
|
||||
options = module.options or getRootModule(module).options or {}
|
||||
|
||||
# Currently `CoffeeScript.compile` caches all source maps if present. They
|
||||
# are available in `getSourceMap` retrieved by `filename`.
|
||||
if cacheSourceMaps or nodeSourceMapsSupportEnabled
|
||||
options.inlineMap = true
|
||||
js = CoffeeScript._compileFile filename, options
|
||||
|
||||
module._compile js, filename
|
||||
|
||||
# If the installed version of Node supports `require.extensions`, register
|
||||
# CoffeeScript as an extension.
|
||||
|
||||
@@ -25,30 +25,30 @@ replDefaults =
|
||||
input = input.replace /^\s*try\s*{([\s\S]*)}\s*catch.*$/m, '$1'
|
||||
|
||||
# Require AST nodes to do some AST manipulation.
|
||||
{Block, Assign, Value, Literal, Call, Code} = require './nodes'
|
||||
{Block, Assign, Value, Literal, Call, Code, Root} = require './nodes'
|
||||
|
||||
try
|
||||
# Tokenize the clean input.
|
||||
tokens = CoffeeScript.tokens input
|
||||
# Filter out tokens generated just to hold comments.
|
||||
if tokens.length >= 2 and tokens[0].generated and
|
||||
tokens[0].comments?.length isnt 0 and tokens[0][1] is '' and
|
||||
tokens[0].comments?.length isnt 0 and "#{tokens[0][1]}" is '' and
|
||||
tokens[1][0] is 'TERMINATOR'
|
||||
tokens = tokens[2...]
|
||||
if tokens.length >= 1 and tokens[tokens.length - 1].generated and
|
||||
tokens[tokens.length - 1].comments?.length isnt 0 and tokens[tokens.length - 1][1] is ''
|
||||
tokens[tokens.length - 1].comments?.length isnt 0 and "#{tokens[tokens.length - 1][1]}" is ''
|
||||
tokens.pop()
|
||||
# Collect referenced variable names just like in `CoffeeScript.compile`.
|
||||
referencedVars = (token[1] for token in tokens when token[0] is 'IDENTIFIER')
|
||||
# Generate the AST of the tokens.
|
||||
ast = CoffeeScript.nodes tokens
|
||||
ast = CoffeeScript.nodes(tokens).body
|
||||
# Add assignment to `__` variable to force the input to be an expression.
|
||||
ast = new Block [new Assign (new Value new Literal '__'), ast, '=']
|
||||
# Wrap the expression in a closure to support top-level `await`.
|
||||
ast = new Code [], ast
|
||||
isAsync = ast.isAsync
|
||||
# Invoke the wrapping closure.
|
||||
ast = new Block [new Call ast]
|
||||
ast = new Root new Block [new Call ast]
|
||||
js = ast.compile {bare: yes, locals: Object.keys(context), referencedVars, sharedScope: yes}
|
||||
if transpile
|
||||
js = transpile.transpile(js, transpile.options).code
|
||||
@@ -75,7 +75,7 @@ runInContext = (js, context, filename) ->
|
||||
vm.runInContext js, context, filename
|
||||
|
||||
addMultilineHandler = (repl) ->
|
||||
{rli, inputStream, outputStream} = repl
|
||||
{inputStream, outputStream} = repl
|
||||
# Node 0.11.12 changed API, prompt is now _prompt.
|
||||
origPrompt = repl._prompt ? repl.prompt
|
||||
|
||||
@@ -86,15 +86,15 @@ addMultilineHandler = (repl) ->
|
||||
buffer: ''
|
||||
|
||||
# Proxy node's line listener
|
||||
nodeLineListener = rli.listeners('line')[0]
|
||||
rli.removeListener 'line', nodeLineListener
|
||||
rli.on 'line', (cmd) ->
|
||||
nodeLineListener = repl.listeners('line')[0]
|
||||
repl.removeListener 'line', nodeLineListener
|
||||
repl.on 'line', (cmd) ->
|
||||
if multiline.enabled
|
||||
multiline.buffer += "#{cmd}\n"
|
||||
rli.setPrompt multiline.prompt
|
||||
rli.prompt true
|
||||
repl.setPrompt multiline.prompt
|
||||
repl.prompt true
|
||||
else
|
||||
rli.setPrompt origPrompt
|
||||
repl.setPrompt origPrompt
|
||||
nodeLineListener cmd
|
||||
return
|
||||
|
||||
@@ -105,25 +105,25 @@ addMultilineHandler = (repl) ->
|
||||
# allow arbitrarily switching between modes any time before multiple lines are entered
|
||||
unless multiline.buffer.match /\n/
|
||||
multiline.enabled = not multiline.enabled
|
||||
rli.setPrompt origPrompt
|
||||
rli.prompt true
|
||||
repl.setPrompt origPrompt
|
||||
repl.prompt true
|
||||
return
|
||||
# no-op unless the current line is empty
|
||||
return if rli.line? and not rli.line.match /^\s*$/
|
||||
return if repl.line? and not repl.line.match /^\s*$/
|
||||
# eval, print, loop
|
||||
multiline.enabled = not multiline.enabled
|
||||
rli.line = ''
|
||||
rli.cursor = 0
|
||||
rli.output.cursorTo 0
|
||||
rli.output.clearLine 1
|
||||
repl.line = ''
|
||||
repl.cursor = 0
|
||||
repl.output.cursorTo 0
|
||||
repl.output.clearLine 1
|
||||
# XXX: multiline hack
|
||||
multiline.buffer = multiline.buffer.replace /\n/g, '\uFF00'
|
||||
rli.emit 'line', multiline.buffer
|
||||
repl.emit 'line', multiline.buffer
|
||||
multiline.buffer = ''
|
||||
else
|
||||
multiline.enabled = not multiline.enabled
|
||||
rli.setPrompt multiline.initialPrompt
|
||||
rli.prompt true
|
||||
repl.setPrompt multiline.initialPrompt
|
||||
repl.prompt true
|
||||
return
|
||||
|
||||
# Store and load command history from a file
|
||||
@@ -139,17 +139,17 @@ addHistory = (repl, filename, maxSize) ->
|
||||
fs.readSync readFd, buffer, 0, size, stat.size - size
|
||||
fs.closeSync readFd
|
||||
# Set the history on the interpreter
|
||||
repl.rli.history = buffer.toString().split('\n').reverse()
|
||||
repl.history = buffer.toString().split('\n').reverse()
|
||||
# If the history file was truncated we should pop off a potential partial line
|
||||
repl.rli.history.pop() if stat.size > maxSize
|
||||
repl.history.pop() if stat.size > maxSize
|
||||
# Shift off the final blank newline
|
||||
repl.rli.history.shift() if repl.rli.history[0] is ''
|
||||
repl.rli.historyIndex = -1
|
||||
lastLine = repl.rli.history[0]
|
||||
repl.history.shift() if repl.history[0] is ''
|
||||
repl.historyIndex = -1
|
||||
lastLine = repl.history[0]
|
||||
|
||||
fd = fs.openSync filename, 'a'
|
||||
|
||||
repl.rli.addListener 'line', (code) ->
|
||||
repl.addListener 'line', (code) ->
|
||||
if code and code.length and code isnt '.history' and code isnt '.exit' and lastLine isnt code
|
||||
# Save the latest command in the file
|
||||
fs.writeSync fd, "#{code}\n"
|
||||
@@ -163,7 +163,7 @@ addHistory = (repl, filename, maxSize) ->
|
||||
repl.commands[getCommandId(repl, 'history')] =
|
||||
help: 'Show command history'
|
||||
action: ->
|
||||
repl.outputStream.write "#{repl.rli.history[..].reverse().join '\n'}\n"
|
||||
repl.outputStream.write "#{repl.history[..].reverse().join '\n'}\n"
|
||||
repl.displayPrompt()
|
||||
|
||||
getCommandId = (repl, commandName) ->
|
||||
@@ -212,7 +212,7 @@ module.exports =
|
||||
opts = merge replDefaults, opts
|
||||
repl = nodeREPL.start opts
|
||||
runInContext opts.prelude, repl.context, 'prelude' if opts.prelude
|
||||
repl.on 'exit', -> repl.outputStream.write '\n' if not repl.rli.closed
|
||||
repl.on 'exit', -> repl.outputStream.write '\n' if not repl.closed
|
||||
addMultilineHandler repl
|
||||
addHistory repl, opts.historyFile, opts.historyMaxInputSize if opts.historyFile
|
||||
# Adapt help inherited from the node REPL
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
# shorthand into the unambiguous long form, add implicit indentation and
|
||||
# parentheses, and generally clean things up.
|
||||
|
||||
{throwSyntaxError} = require './helpers'
|
||||
{throwSyntaxError, extractAllCommentTokens} = require './helpers'
|
||||
|
||||
# Move attached comments from one token to another.
|
||||
moveComments = (fromToken, toToken) ->
|
||||
@@ -53,11 +53,11 @@ exports.Rewriter = class Rewriter
|
||||
@normalizeLines()
|
||||
@tagPostfixConditionals()
|
||||
@addImplicitBracesAndParens()
|
||||
@addParensToChainedDoIife()
|
||||
@rescueStowawayComments()
|
||||
@addLocationDataToGeneratedTokens()
|
||||
@enforceValidCSXAttributes()
|
||||
@fixOutdentLocationData()
|
||||
@enforceValidJSXAttributes()
|
||||
@fixIndentationLocationData()
|
||||
@exposeTokenDataToGrammar()
|
||||
if process?.env?.DEBUG_REWRITTEN_TOKEN_STREAM
|
||||
console.log 'Rewritten token stream:' if process.env.DEBUG_TOKEN_STREAM
|
||||
console.log (t[0] + '/' + t[1] + (if t.comments then '*' else '') for t in @tokens).join ' '
|
||||
@@ -118,14 +118,21 @@ exports.Rewriter = class Rewriter
|
||||
# The lexer has tagged the opening bracket of an indexing operation call.
|
||||
# Match it with its paired close.
|
||||
closeOpenIndexes: ->
|
||||
startToken = null
|
||||
condition = (token, i) ->
|
||||
token[0] in [']', 'INDEX_END']
|
||||
|
||||
action = (token, i) ->
|
||||
token[0] = 'INDEX_END'
|
||||
if @tokens.length >= i and @tokens[i + 1][0] is ':'
|
||||
startToken[0] = '['
|
||||
token[0] = ']'
|
||||
else
|
||||
token[0] = 'INDEX_END'
|
||||
|
||||
@scanTokens (token, i) ->
|
||||
@detectEnd i + 1, condition, action if token[0] is 'INDEX_START'
|
||||
if token[0] is 'INDEX_START'
|
||||
startToken = token
|
||||
@detectEnd i + 1, condition, action
|
||||
1
|
||||
|
||||
# Match tags in token stream starting at `i` with `pattern`.
|
||||
@@ -202,8 +209,8 @@ exports.Rewriter = class Rewriter
|
||||
tokens.splice i, 0, generate 'CALL_END', ')', ['', 'end of input', token[2]], prevToken
|
||||
i += 1
|
||||
|
||||
startImplicitObject = (idx, startsLine = yes) ->
|
||||
stack.push ['{', idx, sameLine: yes, startsLine: startsLine, ours: yes]
|
||||
startImplicitObject = (idx, {startsLine = yes, continuationLineIndent} = {}) ->
|
||||
stack.push ['{', idx, sameLine: yes, startsLine: startsLine, ours: yes, continuationLineIndent: continuationLineIndent]
|
||||
val = new String '{'
|
||||
val.generated = yes
|
||||
tokens.splice idx, 0, generate '{', val, token, prevToken
|
||||
@@ -307,12 +314,15 @@ exports.Rewriter = class Rewriter
|
||||
# if f(a: 1)
|
||||
#
|
||||
# which is probably always unintended.
|
||||
# Furthermore don’t allow this in literal arrays, as
|
||||
# that creates grammatical ambiguities.
|
||||
# Furthermore don’t allow this in the first line of a literal array
|
||||
# or explicit object, as that creates grammatical ambiguities (#5368).
|
||||
if tag in IMPLICIT_FUNC and
|
||||
@indexOfTag(i + 1, 'INDENT') > -1 and @looksObjectish(i + 2) and
|
||||
not @findTagsBackwards(i, ['CLASS', 'EXTENDS', 'IF', 'CATCH',
|
||||
'SWITCH', 'LEADING_WHEN', 'FOR', 'WHILE', 'UNTIL'])
|
||||
'SWITCH', 'LEADING_WHEN', 'FOR', 'WHILE', 'UNTIL']) and
|
||||
not ((s = stackTop()?[0]) in ['{', '['] and
|
||||
not isImplicit(stackTop()) and
|
||||
@findTagsBackwards(i, s))
|
||||
startImplicitCall i + 1
|
||||
stack.push ['INDENT', i + 2]
|
||||
return forward(3)
|
||||
@@ -321,19 +331,31 @@ exports.Rewriter = class Rewriter
|
||||
if tag is ':'
|
||||
# Go back to the (implicit) start of the object.
|
||||
s = switch
|
||||
when @tag(i - 1) in EXPRESSION_END then start[1]
|
||||
when @tag(i - 1) in EXPRESSION_END
|
||||
[startTag, startIndex] = start
|
||||
if startTag is '[' and startIndex > 0 and @tag(startIndex - 1) is '@' and not tokens[startIndex - 1].spaced
|
||||
startIndex - 1
|
||||
else
|
||||
startIndex
|
||||
when @tag(i - 2) is '@' then i - 2
|
||||
else i - 1
|
||||
|
||||
startsLine = s <= 0 or @tag(s - 1) in LINEBREAKS or tokens[s - 1].newLine
|
||||
# Are we just continuing an already declared object?
|
||||
# Including the case where we indent on the line after an explicit '{'.
|
||||
if stackTop()
|
||||
[stackTag, stackIdx] = stackTop()
|
||||
if (stackTag is '{' or stackTag is 'INDENT' and @tag(stackIdx - 1) is '{') and
|
||||
(startsLine or @tag(s - 1) is ',' or @tag(s - 1) is '{')
|
||||
stackNext = stack[stack.length - 2]
|
||||
if (stackTag is '{' or
|
||||
stackTag is 'INDENT' and stackNext?[0] is '{' and
|
||||
not isImplicit(stackNext) and
|
||||
@findTagsBackwards(stackIdx-1, ['{'])) and
|
||||
(startsLine or @tag(s - 1) is ',' or @tag(s - 1) is '{') and
|
||||
@tag(s - 1) not in UNFINISHED
|
||||
return forward(1)
|
||||
|
||||
startImplicitObject(s, !!startsLine)
|
||||
preObjectToken = if i > 1 then tokens[i - 2] else []
|
||||
startImplicitObject(s, {startsLine: !!startsLine, continuationLineIndent: preObjectToken.continuationLineIndent})
|
||||
return forward(2)
|
||||
|
||||
# End implicit calls when chaining method calls
|
||||
@@ -357,6 +379,12 @@ exports.Rewriter = class Rewriter
|
||||
break unless isImplicit stackItem
|
||||
stackItem[2].sameLine = no if isImplicitObject stackItem
|
||||
|
||||
# End indented-continuation-line implicit objects once that indentation is over.
|
||||
if tag is 'TERMINATOR' and token.endsContinuationLineIndentation
|
||||
{preContinuationLineIndent} = token.endsContinuationLineIndentation
|
||||
while inImplicitObject() and (implicitObjectIndent = stackTop()[2].continuationLineIndent)? and implicitObjectIndent > preContinuationLineIndent
|
||||
endImplicitObject()
|
||||
|
||||
newLine = prevTag is 'OUTDENT' or prevToken.newLine
|
||||
if tag in IMPLICIT_END or
|
||||
(tag in CALL_CLOSERS and newLine) or
|
||||
@@ -409,10 +437,10 @@ exports.Rewriter = class Rewriter
|
||||
endImplicitObject i + offset
|
||||
return forward(1)
|
||||
|
||||
# Make sure only strings and wrapped expressions are used in CSX attributes.
|
||||
enforceValidCSXAttributes: ->
|
||||
# Make sure only strings and wrapped expressions are used in JSX attributes.
|
||||
enforceValidJSXAttributes: ->
|
||||
@scanTokens (token, i, tokens) ->
|
||||
if token.csxColon
|
||||
if token.jsxColon
|
||||
next = tokens[i + 1]
|
||||
if next[0] not in ['STRING_START', 'STRING', '(']
|
||||
throwSyntaxError 'expected wrapped or quoted JSX attribute', next[2]
|
||||
@@ -426,6 +454,13 @@ exports.Rewriter = class Rewriter
|
||||
tokens[method] generate 'TERMINATOR', '\n', tokens[j] unless tokens[j][0] is 'TERMINATOR'
|
||||
tokens[method] generate 'JS', '', tokens[j], token
|
||||
|
||||
dontShiftForward = (i, tokens) ->
|
||||
j = i + 1
|
||||
while j isnt tokens.length and tokens[j][0] in DISCARDED
|
||||
return yes if tokens[j][0] is 'INTERPOLATION_END'
|
||||
j++
|
||||
no
|
||||
|
||||
shiftCommentsForward = (token, i, tokens) ->
|
||||
# Find the next surviving token and attach this token’s comments to it,
|
||||
# with a flag that we know to output such comments *before* that
|
||||
@@ -474,7 +509,7 @@ exports.Rewriter = class Rewriter
|
||||
ret = shiftCommentsBackward dummyToken, i - 1, tokens
|
||||
if token.comments.length isnt 0
|
||||
shiftCommentsForward token, i, tokens
|
||||
else
|
||||
else unless dontShiftForward i, tokens
|
||||
# If any of this token’s comments start a line—there’s only
|
||||
# whitespace between the preceding newline and the start of the
|
||||
# comment—and this isn’t one of the special `JS` tokens, then
|
||||
@@ -504,58 +539,112 @@ exports.Rewriter = class Rewriter
|
||||
@scanTokens (token, i, tokens) ->
|
||||
return 1 if token[2]
|
||||
return 1 unless token.generated or token.explicit
|
||||
if token.fromThen and token[0] is 'INDENT'
|
||||
token[2] = token.origin[2]
|
||||
return 1
|
||||
if token[0] is '{' and nextLocation=tokens[i + 1]?[2]
|
||||
{first_line: line, first_column: column} = nextLocation
|
||||
{first_line: line, first_column: column, range: [rangeIndex]} = nextLocation
|
||||
else if prevLocation = tokens[i - 1]?[2]
|
||||
{last_line: line, last_column: column} = prevLocation
|
||||
{last_line: line, last_column: column, range: [, rangeIndex]} = prevLocation
|
||||
column += 1
|
||||
else
|
||||
line = column = 0
|
||||
token[2] =
|
||||
first_line: line
|
||||
first_column: column
|
||||
last_line: line
|
||||
last_column: column
|
||||
rangeIndex = 0
|
||||
token[2] = {
|
||||
first_line: line
|
||||
first_column: column
|
||||
last_line: line
|
||||
last_column: column
|
||||
last_line_exclusive: line
|
||||
last_column_exclusive: column
|
||||
range: [rangeIndex, rangeIndex]
|
||||
}
|
||||
return 1
|
||||
|
||||
# `OUTDENT` tokens should always be positioned at the last character of the
|
||||
# previous token, so that AST nodes ending in an `OUTDENT` token end up with a
|
||||
# location corresponding to the last “real” token under the node.
|
||||
fixOutdentLocationData: ->
|
||||
@scanTokens (token, i, tokens) ->
|
||||
return 1 unless token[0] is 'OUTDENT' or
|
||||
(token.generated and token[0] is 'CALL_END') or
|
||||
(token.generated and token[0] is '}')
|
||||
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
|
||||
fixIndentationLocationData: ->
|
||||
@allComments ?= extractAllCommentTokens @tokens
|
||||
findPrecedingComment = (token, {afterPosition, indentSize, first, indented}) =>
|
||||
tokenStart = token[2].range[0]
|
||||
matches = (comment) ->
|
||||
if comment.outdented
|
||||
return no unless indentSize? and comment.indentSize > indentSize
|
||||
return no if indented and not comment.indented
|
||||
return no unless comment.locationData.range[0] < tokenStart
|
||||
return no unless comment.locationData.range[0] > afterPosition
|
||||
yes
|
||||
if first
|
||||
lastMatching = null
|
||||
for comment in @allComments by -1
|
||||
if matches comment
|
||||
lastMatching = comment
|
||||
else if lastMatching
|
||||
return lastMatching
|
||||
return lastMatching
|
||||
for comment in @allComments when matches comment by -1
|
||||
return comment
|
||||
null
|
||||
|
||||
# Add parens around a `do` IIFE followed by a chained `.` so that the
|
||||
# chaining applies to the executed function rather than the function
|
||||
# object (see #3736)
|
||||
addParensToChainedDoIife: ->
|
||||
condition = (token, i) ->
|
||||
@tag(i - 1) is 'OUTDENT'
|
||||
action = (token, i) ->
|
||||
return unless token[0] in CALL_CLOSERS
|
||||
@tokens.splice doIndex, 0, generate '(', '(', @tokens[doIndex]
|
||||
@tokens.splice i + 1, 0, generate ')', ')', @tokens[i]
|
||||
doIndex = null
|
||||
@scanTokens (token, i, tokens) ->
|
||||
return 1 unless token[1] is 'do'
|
||||
doIndex = i
|
||||
glyphIndex = i + 1
|
||||
if @tag(i + 1) is 'PARAM_START'
|
||||
glyphIndex = null
|
||||
@detectEnd i + 1,
|
||||
(token, i) -> @tag(i - 1) is 'PARAM_END'
|
||||
(token, i) -> glyphIndex = i
|
||||
return 1 unless glyphIndex? and @tag(glyphIndex) in ['->', '=>'] and @tag(glyphIndex + 1) is 'INDENT'
|
||||
@detectEnd glyphIndex + 1, condition, action
|
||||
return 2
|
||||
return 1 unless token[0] in ['INDENT', 'OUTDENT'] or
|
||||
(token.generated and token[0] is 'CALL_END' and not token.data?.closingTagNameToken) or
|
||||
(token.generated and token[0] is '}')
|
||||
isIndent = token[0] is 'INDENT'
|
||||
prevToken = token.prevToken ? tokens[i - 1]
|
||||
prevLocationData = prevToken[2]
|
||||
# addLocationDataToGeneratedTokens() set the outdent’s location data
|
||||
# to the preceding token’s, but in order to detect comments inside an
|
||||
# empty "block" we want to look for comments preceding the next token.
|
||||
useNextToken = token.explicit or token.generated
|
||||
if useNextToken
|
||||
nextToken = token
|
||||
nextTokenIndex = i
|
||||
nextToken = tokens[nextTokenIndex++] while (nextToken.explicit or nextToken.generated) and nextTokenIndex isnt tokens.length - 1
|
||||
precedingComment = findPrecedingComment(
|
||||
if useNextToken
|
||||
nextToken
|
||||
else
|
||||
token
|
||||
afterPosition: prevLocationData.range[0]
|
||||
indentSize: token.indentSize
|
||||
first: isIndent
|
||||
indented: useNextToken
|
||||
)
|
||||
if isIndent
|
||||
return 1 unless precedingComment?.newLine
|
||||
# We don’t want e.g. an implicit call at the end of an `if` condition to
|
||||
# include a following indented comment.
|
||||
return 1 if token.generated and token[0] is 'CALL_END' and precedingComment?.indented
|
||||
prevLocationData = precedingComment.locationData if precedingComment?
|
||||
token[2] =
|
||||
first_line:
|
||||
if precedingComment?
|
||||
prevLocationData.first_line
|
||||
else
|
||||
prevLocationData.last_line
|
||||
first_column:
|
||||
if precedingComment?
|
||||
if isIndent
|
||||
0
|
||||
else
|
||||
prevLocationData.first_column
|
||||
else
|
||||
prevLocationData.last_column
|
||||
last_line: prevLocationData.last_line
|
||||
last_column: prevLocationData.last_column
|
||||
last_line_exclusive: prevLocationData.last_line_exclusive
|
||||
last_column_exclusive: prevLocationData.last_column_exclusive
|
||||
range:
|
||||
if isIndent and precedingComment?
|
||||
[
|
||||
prevLocationData.range[0] - precedingComment.indentSize
|
||||
prevLocationData.range[1]
|
||||
]
|
||||
else
|
||||
prevLocationData.range
|
||||
return 1
|
||||
|
||||
# Because our grammar is LALR(1), it can’t handle some single-line
|
||||
# expressions that lack ending delimiters. The **Rewriter** adds the implicit
|
||||
@@ -612,13 +701,16 @@ exports.Rewriter = class Rewriter
|
||||
tokens.splice i, 1, @indentation()...
|
||||
return 1
|
||||
if @tag(i + 1) in EXPRESSION_CLOSE
|
||||
if token[1] is ';' and @tag(i + 1) is 'OUTDENT'
|
||||
tokens[i + 1].prevToken = token
|
||||
moveComments token, tokens[i + 1]
|
||||
tokens.splice i, 1
|
||||
return 0
|
||||
if tag is 'CATCH'
|
||||
for j in [1..2] when @tag(i + j) in ['OUTDENT', 'TERMINATOR', 'FINALLY']
|
||||
tokens.splice i + j, 0, @indentation()...
|
||||
return 2 + j
|
||||
if tag in ['->', '=>'] and (@tag(i + 1) is ',' or @tag(i + 1) is '.' and token.newLine)
|
||||
if tag in ['->', '=>'] and (@tag(i + 1) in [',', ']'] or @tag(i + 1) is '.' and token.newLine)
|
||||
[indent, outdent] = @indentation tokens[i]
|
||||
tokens.splice i + 1, 0, indent, outdent
|
||||
return 1
|
||||
@@ -661,6 +753,19 @@ exports.Rewriter = class Rewriter
|
||||
@detectEnd i + 1, condition, action
|
||||
return 1
|
||||
|
||||
# For tokens with extra data, we want to make that data visible to the grammar
|
||||
# by wrapping the token value as a String() object and setting the data as
|
||||
# properties of that object. The grammar should then be responsible for
|
||||
# cleaning this up for the node constructor: unwrapping the token value to a
|
||||
# primitive string and separately passing any expected token data properties
|
||||
exposeTokenDataToGrammar: ->
|
||||
@scanTokens (token, i) ->
|
||||
if token.generated or (token.data and Object.keys(token.data).length isnt 0)
|
||||
token[1] = new String token[1]
|
||||
token[1][key] = val for own key, val of (token.data ? {})
|
||||
token[1].generated = yes if token.generated
|
||||
1
|
||||
|
||||
# Generate the indentation tokens, based on another token on the same line.
|
||||
indentation: (origin) ->
|
||||
indent = ['INDENT', 2]
|
||||
@@ -690,6 +795,7 @@ BALANCED_PAIRS = [
|
||||
['PARAM_START', 'PARAM_END']
|
||||
['INDEX_START', 'INDEX_END']
|
||||
['STRING_START', 'STRING_END']
|
||||
['INTERPOLATION_START', 'INTERPOLATION_END']
|
||||
['REGEX_START', 'REGEX_END']
|
||||
]
|
||||
|
||||
@@ -713,11 +819,12 @@ IMPLICIT_FUNC = ['IDENTIFIER', 'PROPERTY', 'SUPER', ')', 'CALL_END', ']', 'IN
|
||||
|
||||
# If preceded by an `IMPLICIT_FUNC`, indicates a function invocation.
|
||||
IMPLICIT_CALL = [
|
||||
'IDENTIFIER', 'CSX_TAG', 'PROPERTY', 'NUMBER', 'INFINITY', 'NAN'
|
||||
'IDENTIFIER', 'JSX_TAG', 'PROPERTY', 'NUMBER', 'INFINITY', 'NAN'
|
||||
'STRING', 'STRING_START', 'REGEX', 'REGEX_START', 'JS'
|
||||
'NEW', 'PARAM_START', 'CLASS', 'IF', 'TRY', 'SWITCH', 'THIS'
|
||||
'DYNAMIC_IMPORT', 'IMPORT_META', 'NEW_TARGET'
|
||||
'UNDEFINED', 'NULL', 'BOOL'
|
||||
'UNARY', 'YIELD', 'AWAIT', 'UNARY_MATH', 'SUPER', 'THROW'
|
||||
'UNARY', 'DO', 'DO_IIFE', 'YIELD', 'AWAIT', 'UNARY_MATH', 'SUPER', 'THROW'
|
||||
'@', '->', '=>', '[', '(', '{', '--', '++'
|
||||
]
|
||||
|
||||
@@ -747,9 +854,14 @@ CONTROL_IN_IMPLICIT = ['IF', 'TRY', 'FINALLY', 'CATCH', 'CLASS', 'SWITCH']
|
||||
# `STRING_START` isn’t on this list because its `locationData` matches that of
|
||||
# the node that becomes `StringWithInterpolations`, and therefore
|
||||
# `addDataToNode` attaches `STRING_START`’s tokens to that node.
|
||||
DISCARDED = ['(', ')', '[', ']', '{', '}', '.', '..', '...', ',', '=', '++', '--', '?',
|
||||
'AS', 'AWAIT', 'CALL_START', 'CALL_END', 'DEFAULT', 'ELSE', 'EXTENDS', 'EXPORT',
|
||||
'FORIN', 'FOROF', 'FORFROM', 'IMPORT', 'INDENT', 'INDEX_SOAK', 'LEADING_WHEN',
|
||||
'OUTDENT', 'PARAM_END', 'REGEX_START', 'REGEX_END', 'RETURN', 'STRING_END', 'THROW',
|
||||
'UNARY', 'YIELD'
|
||||
DISCARDED = ['(', ')', '[', ']', '{', '}', ':', '.', '..', '...', ',', '=', '++', '--', '?',
|
||||
'AS', 'AWAIT', 'CALL_START', 'CALL_END', 'DEFAULT', 'DO', 'DO_IIFE', 'ELSE',
|
||||
'EXTENDS', 'EXPORT', 'FORIN', 'FOROF', 'FORFROM', 'IMPORT', 'INDENT', 'INDEX_SOAK',
|
||||
'INTERPOLATION_START', 'INTERPOLATION_END', 'LEADING_WHEN', 'OUTDENT', 'PARAM_END',
|
||||
'REGEX_START', 'REGEX_END', 'RETURN', 'STRING_END', 'THROW', 'UNARY', 'YIELD'
|
||||
].concat IMPLICIT_UNSPACED_CALL.concat IMPLICIT_END.concat CALL_CLOSERS.concat CONTROL_IN_IMPLICIT
|
||||
|
||||
# Tokens that, when appearing at the end of a line, suppress a following TERMINATOR/INDENT token
|
||||
exports.UNFINISHED = UNFINISHED = ['\\', '.', '?.', '?::', 'UNARY', 'DO', 'DO_IIFE', 'MATH', 'UNARY_MATH', '+', '-',
|
||||
'**', 'SHIFT', 'RELATION', 'COMPARE', '&', '^', '|', '&&', '||',
|
||||
'BIN?', 'EXTENDS']
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user