[CS2] 2.0.0-beta1 docs (#4494)

* Update package versions; remove marked

* Revise docs to use Markdown-It: tables are now GitHub-Flavored Markdown tables, avoid hack of blockquoted code blocks

* Add anchors for sub-sections

* Add syntax highlighting to uneducable code blocks; fix missing italics variant for comments font

* Update docs about breaking changes in Literate CoffeeScript, move Breaking Changes section below Literate CoffeeScript section

* Update docs regarding destructuring default values breaking change

* Update changelog, with spitball release date for beta1

* Fix highlight function return statement
This commit is contained in:
Geoffrey Booth 2017-04-09 23:07:58 -07:00 committed by GitHub
parent be7c1be75f
commit d20f54967e
19 changed files with 664 additions and 743 deletions

View File

@ -199,22 +199,36 @@ buildDocs = (watch = no) ->
codeFor = require "./documentation/v#{majorVersion}/code.coffee"
htmlFor = ->
marked = require 'marked'
markdownRenderer = new marked.Renderer()
markdownRenderer.heading = (text, level) ->
"<h#{level}>#{text}</h#{level}>" # Dont let marked add an id
markdownRenderer.code = (code) ->
hljs = require 'highlight.js'
hljs.configure classPrefix: ''
markdownRenderer = require('markdown-it')
html: yes
typographer: yes
highlight: (str, lang) ->
# From https://github.com/markdown-it/markdown-it#syntax-highlighting
if lang and hljs.getLanguage(lang)
try
return hljs.highlight(lang, str).value
catch ex
return '' # No syntax highlighting
# Add some custom overrides to Markdown-Its rendering, per
# https://github.com/markdown-it/markdown-it/blob/master/docs/architecture.md#renderer
defaultFence = markdownRenderer.renderer.rules.fence
markdownRenderer.renderer.rules.fence = (tokens, idx, options, env, slf) ->
code = tokens[idx].content
if code.indexOf('codeFor(') is 0 or code.indexOf('releaseHeader(') is 0
"<%= #{code} %>"
else
"<pre><code>#{code}</code></pre>" # Default
"<blockquote class=\"uneditable-code-block\">#{defaultFence.apply @, arguments}</blockquote>"
(file, bookmark) ->
md = fs.readFileSync "#{sectionsSourceFolder}/#{file}.md", 'utf-8'
md = md.replace /<%= releaseHeader %>/g, releaseHeader
md = md.replace /<%= majorVersion %>/g, majorVersion
md = md.replace /<%= fullVersion %>/g, CoffeeScript.VERSION
html = marked md, renderer: markdownRenderer
html = markdownRenderer.render md
html = _.template(html)
codeFor: codeFor()
releaseHeader: releaseHeader

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,3 @@
{a = 1} = {a: null}
a # Equals 1 in CoffeeScript 1.x, null in CoffeeScript 2

View File

@ -2,20 +2,30 @@
CoffeeScript 2 aims to output as much idiomatic ES2015+ syntax as possible with as few breaking changes from CoffeeScript 1.x as possible. Some breaking changes, unfortunately, were unavoidable.
### Function parameter default values
<section id="breaking-changes-default-values">
Per the [ES2015 spec regarding default parameters](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Default_parameters), default values are only applied when a parameter value is missing or `undefined`. In CoffeeScript 1.x, the default value would be applied in those cases but also if the parameter value was `null`.
### Default values for function parameters and destructured elements
Per the [ES2015 spec regarding function default parameters](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Default_parameters) and [destructuring default values](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment#Default_values), default values are only applied when a value is missing or `undefined`. In CoffeeScript 1.x, the default value would be applied in those cases but also if the value was `null`.
```
codeFor('breaking_change_function_parameter_default_values', 'f(null)')
```
```
codeFor('breaking_change_destructuring_default_values', 'a')
```
</section>
<section id="breaking-changes-bound-generator-functions">
### Bound generator functions
Bound generator functions, a.k.a. generator arrow functions, [arent allowed in ECMAScript](http://stackoverflow.com/questions/27661306/can-i-use-es6s-arrow-function-syntax-with-generators-arrow-notation). You can write `function*` or `=>`, but not both. Therefore, CoffeeScript code like this:
> ```coffee
f = => yield this # Throws a compiler error
```coffee
f = => yield this
# Throws a compiler error
```
Needs to be rewritten the old-fashioned way:
@ -24,38 +34,48 @@ Needs to be rewritten the old-fashioned way:
codeFor('breaking_change_bound_generator_function')
```
</section>
<section id="breaking-changes-classes">
### Classes are compiled to ES2015 classes
ES2015 classes and their methods have some restrictions beyond those on regular functions.
Class constructors cant be invoked without `new`:
> ```coffee
(class)() # Throws a TypeError at runtime
```coffee
(class)()
# Throws a TypeError at runtime
```
Derived (extended) class `constructor`s cannot use `this` before calling `super`:
> ```coffee
```coffee
class B extends A
constructor: -> this # Throws a compiler error
constructor: -> this
# Throws a compiler error
```
Class methods cant be used with `new` (uncommon):
> ```coffee
```coffee
class Namespace
@Klass = ->
new Namespace.Klass # Throws a TypeError at runtime
new Namespace.Klass
# Throws a TypeError at runtime
```
</section>
<section id="breaking-changes-bare-super">
### Bare `super`
Due to a syntax clash with `super` with accessors, bare `super` no longer compiles to a super call forwarding all arguments.
> ```coffee
```coffee
class B extends A
foo: -> super # Throws a compiler error
foo: -> super
# Throws a compiler error
```
Arguments can be forwarded explicitly using splats:
@ -70,15 +90,19 @@ Or if you know that the parent function doesnt require arguments, just call `
codeFor('breaking_change_super_without_arguments')
```
</section>
<section id="breaking-changes-super-in-non-class-methods">
### `super` in non-class methods
In CoffeeScript 1.x it is possible to use `super` in more than just class methods, such as in manually prototype-assigned functions:
> ```coffee
```coffee
A = ->
B = ->
B extends A
B.prototype.foo = -> super arguments... # Throws a compiler error
B.prototype.foo = -> super arguments...
# Throws a compiler error
```
Due to the switch to ES2015 `super`, this is no longer supported. The above case could be refactored to:
@ -93,13 +117,26 @@ or
codeFor('breaking_change_super_in_non-class_methods_refactor_with_class')
```
</section>
<section id="breaking-changes-dynamic-class-keys-exclude-executable-class-scope">
### Dynamic class keys exclude executable class scope
Due to the hoisting required to compile to ES2015 classes, dynamic keys in class methods cant use values from the executable class body unless the methods are assigned in prototype style.
> ```coffee
```coffee
class A
name = 'method'
"#{name}": -> # This method will be named 'undefined'
@::[name] = -> # This will work; assigns to `A.prototype.method`
```
</section>
<section id="breaking-changes-literate-coffeescript">
### Literate CoffeeScript now parsed by a Markdown library
The CoffeeScript 1.x implementation of Literate CoffeeScript relies on indentation to tell apart code blocks from documentation, and as such it can get confused by Markdown features that also use indentation like lists. In CoffeeScript 2 this has been refactored to now use [Markdown-It](https://github.com/markdown-it/markdown-it) to detect Markdown sections rather than just looking at indentation. The only significant difference is that now if you want to include a code block in documentation, as opposed to the compiler recognizing that code block as code, it must have at least one line fully unindented. Wrapping it in HTML tags is no longer sufficient.
Code blocks interspersed with lists may need to be refactored. In general, code blocks should be separated by a blank line between documentation, and should maintain a consistent indentation level—so an indentation of one tab (or whatever you consider to be a tab stop, like 2 spaces or 4 spaces) should be treated as your codes “left margin,” with all code in the file relative to that column.

View File

@ -1,5 +1,16 @@
## Change Log
```
releaseHeader('2017-04-14', '2.0.0-beta1', '2.0.0-alpha1')
```
* Initial beta release of CoffeeScript 2. No further breaking changes are anticipated.
* Destructured objects and arrays now output using ES2015+ syntax whenever possible.
* Literate CoffeeScript now has much better support for parsing Markdown, thanks to using [Markdown-It](https://github.com/markdown-it/markdown-it) to detect Markdown sections rather than just looking at indentation.
* Calling a function named `get` or `set` now requires parentheses, to disambiguate from the `get` or `set` keywords (which are [disallowed](#unsupported-get-set)).
* The compiler now requires Node 7.6+, the first version of Node to support asynchronous functions without requiring a flag.
```
releaseHeader('2017-02-21', '2.0.0-alpha1', '1.12.4')
```

View File

@ -14,7 +14,7 @@ Since the CoffeeScript 2 compiler outputs ES2015+ syntax, it is your responsibil
There are many great task runners for setting up JavaScript build chains, such as [Gulp](http://gulpjs.com/), [Webpack](https://webpack.github.io/), [Grunt](https://gruntjs.com/) and [Broccoli](http://broccolijs.com/). If youre looking for a very minimal solution to get started, you can use [babel-preset-env](https://babeljs.io/docs/plugins/preset-env/) and the command line:
> ```bash
```bash
npm install --global coffeescript@next
npm install --save-dev coffeescript@next babel-cli babel-preset-env
coffee -p *.coffee | babel --presets env > app.js

View File

@ -4,12 +4,12 @@ The command-line version of `coffee` is available as a [Node.js](http://nodejs.o
To install, first make sure you have a working copy of the latest stable version of [Node.js](http://nodejs.org/). You can then install CoffeeScript globally with [npm](http://npmjs.org):
> ```
```bash
npm install --global coffeescript@next
```
When you need CoffeeScript as a dependency of a project, within that projects folder you can install it locally:
> ```
```bash
npm install --save coffeescript@next
```

View File

@ -4,6 +4,6 @@ The golden rule of CoffeeScript is: _“Its just JavaScript.”_ The code com
**Latest Version:** [<%= fullVersion %>](http://github.com/jashkenas/coffeescript/tarball/<%= fullVersion %>)
> ```
```bash
npm install -g coffeescript@next
```

View File

@ -24,125 +24,21 @@ codeFor('modulo')
All together now:
<table class="definitions">
<tbody>
<tr>
<th>CoffeeScript</th>
<th>JavaScript</th>
</tr>
<tr>
<td>`is`</td>
<td>`===`</td>
</tr>
<tr>
<td>`isnt`</td>
<td>`!==`</td>
</tr>
<tr>
<td>`not`</td>
<td>`!`</td>
</tr>
<tr>
<td>`and`</td>
<td>`&&`</td>
</tr>
<tr>
<td>`or`</td>
<td>`||`</td>
</tr>
<tr>
<td>`true`, `yes`, `on`</td>
<td>`true`</td>
</tr>
<tr>
<td>`false`, `no`, `off`&emsp;</td>
<td>`false`</td>
</tr>
<tr>
<td>`@`, `this`</td>
<td>`this`</td>
</tr>
<tr>
<td>`of`</td>
<td>`in`</td>
</tr>
<tr>
<td>`in`</td>
<td>_<small>no JS equivalent</small>_</td>
</tr>
<tr>
<td>`a ** b`</td>
<td>`Math.pow(a, b)`</td>
</tr>
<tr>
<td>`a // b`</td>
<td>`Math.floor(a / b)`</td>
</tr>
<tr>
<td>`a %% b`</td>
<td>`(a % b + b) % b`</td>
</tr>
</tbody>
</table>
| CoffeeScript | JavaScript |
| --- | --- |
| `is` | `===` |
| `isnt` | `!==` |
| `not` | `!` |
| `and` | `&&` |
| `or` | `||` |
| `true`, `yes`, `on` | `true` |
| `false`, `no`, `off`&emsp; | `false` |
| `@`, `this` | `this` |
| `of` | `in` |
| `in` | _no JS equivalent_ |
| `a ** b` | `Math.pow(a, b)` |
| `a // b` | `Math.floor(a / b)` |
| `a %% b` | `(a % b + b) % b` |
```
codeFor('aliases')

View File

@ -2,6 +2,8 @@
There are a few ECMAScript features that CoffeeScript intentionally doesnt support.
<section id="unsupported-let-const">
### `let` and `const`: Block-Scoped and Reassignment-Protected Variables
When CoffeeScript was designed, `var` was [intentionally omitted](https://github.com/jashkenas/coffeescript/issues/238#issuecomment-153502). This was to spare developers the mental housekeeping of needing to worry about variable _declaration_ (`var foo`) as opposed to variable _assignment_ (`foo = 1`). The CoffeeScript compiler automatically takes care of declaration for you, by generating `var` statements at the top of every function scope. This makes it impossible to accidentally declare a global variable.
@ -10,12 +12,15 @@ When CoffeeScript was designed, `var` was [intentionally omitted](https://github
Keep in mind that `const` only protects you from _reassigning_ a variable; it doesnt prevent the variables value from changing, the way constants usually do in other languages:
> ```js
```js
const obj = {foo: 'bar'};
obj.foo = 'baz'; // Allowed!
obj = {}; // Throws error
```
</section>
<section id="unsupported-get-set">
### `get` and `set` Keyword Shorthand Syntax
`get` and `set`, as keywords preceding functions or class methods, are intentionally unimplemented in CoffeeScript.
@ -25,3 +30,5 @@ This is to avoid grammatical ambiguity, since in CoffeeScript such a construct l
```
codeFor('get_set', 'screen.height')
```
</section>

View File

@ -2,158 +2,24 @@
Once installed, you should have access to the `coffee` command, which can execute scripts, compile `.coffee` files into `.js`, and provide an interactive REPL. The `coffee` command takes the following options:
<table>
<tbody>
<tr>
<td>`-c, --compile`</td>
<td>Compile a `.coffee` script into a `.js` JavaScript file of the same name.</td>
</tr>
<tr>
<td>`-m, --map`</td>
<td>Generate source maps alongside the compiled JavaScript files. Adds `sourceMappingURL` directives to the JavaScript as well.</td>
</tr>
<tr>
<td>`-M, --inline-map`</td>
<td>Just like `--map`, but include the source map directly in the compiled JavaScript files, rather than in a separate file.</td>
</tr>
<tr>
<td width="25%">`-i, --interactive`</td>
<td>Launch an interactive CoffeeScript session to try short snippets. Identical to calling `coffee` with no arguments.</td>
</tr>
<tr>
<td>`-o, --output [DIR]`</td>
<td>Write out all compiled JavaScript files into the specified directory. Use in conjunction with `--compile` or `--watch`.</td>
</tr>
<tr>
<td>`-w, --watch`</td>
<td>Watch files for changes, rerunning the specified command when any file is updated.</td>
</tr>
<tr>
<td>`-p, --print`</td>
<td>Instead of writing out the JavaScript as a file, print it directly to **stdout**.</td>
</tr>
<tr>
<td>`-s, --stdio`</td>
<td>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`</td>
</tr>
<tr>
<td>`-l, --literate`</td>
<td>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.</td>
</tr>
<tr>
<td>`-e, --eval`</td>
<td>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]"`</td>
</tr>
<tr>
<td>`-r, --require [MODULE]`</td>
<td>`require()` the given module before starting the REPL or evaluating the code given with the `--eval` flag.</td>
</tr>
<tr>
<td>`-b, --bare`</td>
<td>Compile the JavaScript without the [top-level function safety wrapper](#lexical-scope).</td>
</tr>
<tr>
<td>`-t, --tokens`</td>
<td>Instead of parsing the CoffeeScript, just lex it, and print out the token stream:<br>
`[IDENTIFIER square] [= =] [PARAM_START (]` ...</td>
</tr>
<tr>
<td>`-n, --nodes`</td>
<td>Instead of compiling the CoffeeScript, just lex and parse it, and print out the parse tree:<br>
```
Block
Assign
Value IdentifierLiteral: square
Code
Param IdentifierLiteral: x
Block
Op *
Value IdentifierLiteral: x
Value IdentifierLiteral: x
```
</td>
</tr>
<tr>
<td>`--nodejs`</td>
<td>The `node` executable has some useful options you can set, such as<br>
`--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.</td>
</tr>
<tr>
<td>`--no-header`</td>
<td>Suppress the “Generated by CoffeeScript” header.</td>
</tr>
</tbody>
</table>
| Option | Description |
| --- | --- |
| `-c, --compile` | Compile a `.coffee` script into a `.js` JavaScript file of the same name. |
| `-m, --map` | Generate source maps alongside the compiled JavaScript files. Adds `sourceMappingURL` directives to the JavaScript as well. |
| `-M, --inline-map` | Just like `--map`, but include the source map directly in the compiled JavaScript files, rather than in a separate file. |
| `-i, --interactive` | Launch an interactive CoffeeScript session to try short snippets. Identical to calling `coffee` with no arguments. |
| `-o, --output [DIR]` | Write out all compiled JavaScript files into the specified directory. Use in conjunction with `--compile` or `--watch`. |
| `-w, --watch` | Watch files for changes, rerunning the specified command when any file is updated. |
| `-p, --print` | Instead of writing out the JavaScript as a file, print it directly to **stdout**. |
| `-s, --stdio` | Pipe in CoffeeScript to STDIN and get back JavaScript over STDOUT. Good for use with processes written in other languages. An example:<br>`cat src/cake.coffee | coffee -sc` |
| `-l, --literate` | Parses the code as Literate CoffeeScript. You only need to specify this when passing in code directly over **stdio**, or using some sort of extension-less file name. |
| `-e, --eval` | Compile and print a little snippet of CoffeeScript directly from the command line. For example:<br>`coffee -e "console.log num for num in [10..1]"` |
| `-r, --require [MODULE]`&emsp; | `require()` the given module before starting the REPL or evaluating the code given with the `--eval` flag. |
| `-b, --bare` | Compile the JavaScript without the [top-level function safety wrapper](#lexical-scope). |
| `-t, --tokens` | Instead of parsing the CoffeeScript, just lex it, and print out the token stream. Used for debugging the compiler. |
| `-n, --nodes` | Instead of compiling the CoffeeScript, just lex and parse it, and print out the parse tree. Used for debugging the compiler. |
| `--nodejs` | The `node` executable has some useful options you can set, such as `--debug`, `--debug-brk`, `--max-stack-size`, and `--expose-gc`. Use this flag to forward options directly to Node.js. To pass multiple flags, use `--nodejs` multiple times. |
| `--no-header` | Suppress the “Generated by CoffeeScript” header. |
### Examples:

View File

@ -101,9 +101,6 @@
<section id="unsupported">
<%= htmlFor('unsupported') %>
</section>
<section id="breaking-changes">
<%= htmlFor('breaking_changes') %>
</section>
<section id="literate">
<%= htmlFor('literate') %>
</section>
@ -137,6 +134,9 @@
<%= htmlFor('contributing') %>
</section>
</section>
<section id="breaking-changes">
<%= htmlFor('breaking_changes') %>
</section>
<section id="changelog">
<%= htmlFor('changelog') %>
</section>

View File

@ -282,6 +282,10 @@ p, blockquote, table, .code-example {
margin-bottom: 1.3rem;
}
td code {
white-space: nowrap;
}
h2, h3 {
margin-top: 1.3em;
margin-bottom: 0.6em;

View File

@ -86,9 +86,6 @@
</li>
</ul>
</li>
<li class="nav-item">
<a href="#breaking-changes" class="nav-link" data-action="sidebar-nav">Breaking Changes From 1.x</a>
</li>
<li class="nav-item">
<a href="#literate" class="nav-link" data-action="sidebar-nav">Literate CoffeeScript</a>
</li>
@ -127,6 +124,9 @@
</li>
</ul>
</li>
<li class="nav-item">
<a href="#breaking-changes" class="nav-link" data-action="sidebar-nav">Breaking Changes From 1.x</a>
</li>
<li class="nav-item">
<a href="#changelog" class="nav-link" data-action="sidebar-nav">Change Log</a>
</li>

View File

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

View File

@ -38,3 +38,38 @@
.cm-s-twilight .cm-operator {
color: #cda869;
}
/* Uneditable code blocks are inverted, so use darker versions of the above */
.uneditable-code-block .comment {
font-style: italic;
color: #837B85;
}
.uneditable-code-block .class,
.uneditable-code-block .function,
.uneditable-code-block .keyword,
.uneditable-code-block .reserved,
.uneditable-code-block .title {
color: #534328;
}
.uneditable-code-block .string
.uneditable-code-block .value
.uneditable-code-block .inheritance
.uneditable-code-block .header {
color: #3A4029;
}
.uneditable-code-block .variable,
.uneditable-code-block .literal,
.uneditable-code-block .tag,
.uneditable-code-block .regexp,
.uneditable-code-block .subst,
.uneditable-code-block .property {
color: #474429;
}
.uneditable-code-block .number,
.uneditable-code-block .preprocessor,
.uneditable-code-block .built_in,
.uneditable-code-block .params,
.uneditable-code-block .constant {
color: #474429;
}

View File

@ -101,7 +101,7 @@
var out;
out = [];
md.renderer.rules = {
code_block: function(tokens, idx) {
code_block: function(tokens, idx, options, env, slf) {
var i, j, len1, line, lines, results, startLine;
startLine = tokens[idx].map[0];
lines = tokens[idx].content.split('\n');

View File

@ -40,10 +40,9 @@
},
"devDependencies": {
"docco": "~0.7.0",
"google-closure-compiler-js": "^20170124.0.0",
"highlight.js": "~9.9.0",
"google-closure-compiler-js": "^20170218.0.0",
"highlight.js": "~9.10.0",
"jison": ">=0.4.17",
"marked": "^0.3.6",
"underscore": "~1.8.3"
},
"dependencies": {

View File

@ -76,7 +76,8 @@ exports.some = Array::some ? (fn) ->
exports.invertLiterate = (code) ->
out = []
md.renderer.rules =
code_block: (tokens, idx) ->
# Delete all other rules, since all we want are the code blocks.
code_block: (tokens, idx, options, env, slf) ->
startLine = tokens[idx].map[0]
lines = tokens[idx].content.split '\n'
for line, i in lines