diff --git a/Cakefile b/Cakefile index cd96e5e44e..6e72ab413a 100644 --- a/Cakefile +++ b/Cakefile @@ -179,6 +179,11 @@ buildDocs = (watch = no) -> sectionsSourceFolder = 'documentation/sections' examplesSourceFolder = 'documentation/examples' outputFolder = "docs/v#{majorVersion}" + cheerio = require "cheerio" + + searchCollection = + tree: {} + data: [] # Helpers releaseHeader = (date, version, prevVersion) -> @@ -188,8 +193,79 @@ buildDocs = (watch = no) -> """ + formatDate = (date) -> + monthNames = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'] + date.replace /^(\d\d\d\d)-(\d\d)-(\d\d)$/, (match, $1, $2, $3) -> + "#{monthNames[$2 - 1]} #{+$3}, #{$1}" + codeFor = require "./documentation/site/code.coffee" + # Template for search results. + searchResults = """ +
+
+
+ <%= section %> +
+ <%= results %> +
+
+ """ + # Template for search result item. + searchResultsList = """ +
+
+
+ <%= title %> +
+
<%= content %>
+
+
+ """ + searchResultsTemplate = _.template(searchResults).source + searchResultsListTemplate = _.template(searchResultsList).source + + # Build search catalog. + buildSearchCatalog = (html) -> + $ = cheerio.load html + parseSectionContent = (section, level) -> + sectionId = $(section).attr "id" + header = "> h#{level + 1}" + # Chagelogs subsections, e.g. 2.3.0 - + version = $("#{header} a", section).text() + date = $("#{header} span time", section).text() + title = if version and date then "#{version} - #{date}" else $(header, section).text() + dataLevel = $(section).data("level") or no + content = $(":not(section)", section).text() + .replace ///^#{title}///, "" # Remove title from the content. + .replace /\n+/g, " " # Convertnewlines into spaces. + .replace /^(?:\t|\s)+/g, " " # Remove extra spaces. + {section:sectionId, title, content, dataLevel} + + addCollection = ({el, level, parent=no}) -> + {section, title, dataLevel} = data = Object.assign {}, parseSectionContent(el, level), {level, parent} + if not dataLevel and parent + dataLevel = searchCollection.tree[parent].dataLevel + searchCollection.tree[section] = {title, parent, dataLevel} + searchCollection.data.push Object.assign {}, data, {dataLevel} + section + + parseSections = (sections, level=1, parent=no) -> + # Level 1, e.g. main > section + sections.each (i, el) -> + section = addCollection {el, level, parent} + # Level 2, e.g. main > section > section + subSections = $("section", el) + if subSections?.length > 1 + parseSections subSections, level + 1, section + + parseSections $("main.main > section") + """ + window.searchResultTemplate = #{searchResultsTemplate}; + window.searchResultsListTemplate = #{searchResultsListTemplate}; + window.searchCollection = #{JSON.stringify searchCollection}; + """ + htmlFor = -> hljs = require 'highlight.js' hljs.configure classPrefix: '' @@ -204,7 +280,6 @@ buildDocs = (watch = no) -> catch ex return '' # No syntax highlighting - # Add some custom overrides to Markdown-It’s rendering, per # https://github.com/markdown-it/markdown-it/blob/master/docs/architecture.md#renderer defaultFence = markdownRenderer.renderer.rules.fence @@ -249,14 +324,16 @@ buildDocs = (watch = no) -> includeScript: includeScript() output - # Task do renderIndex = -> render = _.template fs.readFileSync(indexFile, 'utf-8') - output = render - include: include() + output = render include: include() + searchIndex = buildSearchCatalog output + fs.writeFileSync "#{outputFolder}/search-index.js", searchIndex + log 'compiled', green, "search index → #{outputFolder}/search-index.js" fs.writeFileSync "#{outputFolder}/index.html", output log 'compiled', green, "#{indexFile} → #{outputFolder}/index.html" try + fs.symlinkSync "v#{majorVersion}/search-index.js", 'docs/search-index.js' fs.symlinkSync "v#{majorVersion}/index.html", 'docs/index.html' catch exception diff --git a/docs/search-index.js b/docs/search-index.js new file mode 120000 index 0000000000..588e0e3850 --- /dev/null +++ b/docs/search-index.js @@ -0,0 +1 @@ +v2/search-index.js \ No newline at end of file diff --git a/docs/v2/index.html b/docs/v2/index.html index 9eb16668cf..eeda9e9145 100644 --- a/docs/v2/index.html +++ b/docs/v2/index.html @@ -18,6 +18,715 @@ @@ -565,10 +1311,25 @@ GitHub + + + var renderStarRating; renderStarRating = function({rating, maxStars}) { var emptyStar, wholeStar; return ; }; var renderStarRating; renderStarRating = function({rating, maxStars}) { var emptyStar, wholeStar; return ; }; var renderStarRating; renderStarRating = function({rating, maxStars}) { var emptyStar, wholeStar; return ; }; var renderStarRating; renderStarRating = function({rating, maxStars}) { var emptyStar, wholeStar; return ; }; varrenderStarRatingrenderStarRating=functionratingmaxStarsvaremptyStarwholeStarreturn{(function() {var i, ref, results;results = [];for (wholeStar = i = 0, ref = Math.floor(rating); (0 <= ref ? i < ref : i > ref); wholeStar = 0 <= ref ? ++i : --i) {results.push();}return results;})()}{(rating % 1 !== 0 ? : void 0)}{(function() {var i, ref, ref1, results;results = [];for (emptyStar = i = ref = Math.ceil(rating), ref1 = maxStars; (ref <= ref1 ? i < ref1 : i > ref1); emptyStar = ref <= ref1 ? ++i : --i) {results.push();}return results;})()};};Older plugins or forks of CoffeeScript supported JSX syntax and referred to it as CSX or CJSX. They also often used a .cjsx file extension, but this is no longer necessary; regular .coffee will do..cjsx.coffee","dataLevel":1,"level":1,"parent":false},{"section":"functions","title":"Functions","content":"Functions are defined by an optional list of parameters in parentheses, an arrow, and the function body. The empty function looks like this: ->-> square = (x) -> x * x cube = (x) -> square(x) * x square = (x) -> x * x cube = (x) -> square(x) * x var cube, square; square = function(x) { return x * x; }; cube = function(x) { return square(x) * x; }; var cube, square; square = function(x) { return x * x; }; cube = function(x) { return square(x) * x; }; \t cube(5) square = (x) -> x * x cube = (x) -> square(x) * x square = (x) -> x * x cube = (x) -> square(x) * x var cube, square; square = function(x) { return x * x; }; cube = function(x) { return square(x) * x; }; var cube, square; square = function(x) { return x * x; }; cube = function(x) { return square(x) * x; }; square = (x) -> x * x cube = (x) -> square(x) * x square = (x) -> x * x cube = (x) -> square(x) * x square = (x) -> x * x cube = (x) -> square(x) * x square = (x) -> x * x cube = (x) -> square(x) * x square=(x)->x*xcube=(x)->square(x)*x var cube, square; square = function(x) { return x * x; }; cube = function(x) { return square(x) * x; }; var cube, square; square = function(x) { return x * x; }; cube = function(x) { return square(x) * x; }; var cube, square; square = function(x) { return x * x; }; cube = function(x) { return square(x) * x; }; var cube, square; square = function(x) { return x * x; }; cube = function(x) { return square(x) * x; }; varcubesquaresquare=functionxreturnx*xcube=functionxreturnsquarex*x \t cube(5) \t cube(5) \t cube(5) \t \t Functions may also have default values for arguments, which will be used if the incoming argument is missing (undefined).undefined fill = (container, liquid = \"coffee\") -> \"Filling the #{container} with #{liquid}...\" fill = (container, liquid = \"coffee\") -> \"Filling the #{container} with #{liquid}...\" var fill; fill = function(container, liquid = \"coffee\") { return `Filling the ${container} with ${liquid}...`; }; var fill; fill = function(container, liquid = \"coffee\") { return `Filling the ${container} with ${liquid}...`; }; \t fill(\"cup\") fill = (container, liquid = \"coffee\") -> \"Filling the #{container} with #{liquid}...\" fill = (container, liquid = \"coffee\") -> \"Filling the #{container} with #{liquid}...\" var fill; fill = function(container, liquid = \"coffee\") { return `Filling the ${container} with ${liquid}...`; }; var fill; fill = function(container, liquid = \"coffee\") { return `Filling the ${container} with ${liquid}...`; }; fill = (container, liquid = \"coffee\") -> \"Filling the #{container} with #{liquid}...\" fill = (container, liquid = \"coffee\") -> \"Filling the #{container} with #{liquid}...\" fill = (container, liquid = \"coffee\") -> \"Filling the #{container} with #{liquid}...\" fill = (container, liquid = \"coffee\") -> \"Filling the #{container} with #{liquid}...\" fill=(container,liquid=\"coffee\")->\"Filling the #{container} with #{liquid}...\" var fill; fill = function(container, liquid = \"coffee\") { return `Filling the ${container} with ${liquid}...`; }; var fill; fill = function(container, liquid = \"coffee\") { return `Filling the ${container} with ${liquid}...`; }; var fill; fill = function(container, liquid = \"coffee\") { return `Filling the ${container} with ${liquid}...`; }; var fill; fill = function(container, liquid = \"coffee\") { return `Filling the ${container} with ${liquid}...`; }; varfillfill=functioncontainerliquid=\"coffee\"return`Filling the ${container}with ${liquid}...` \t fill(\"cup\") \t fill(\"cup\") \t fill(\"cup\") \t \t ","dataLevel":1,"level":2,"parent":"language"},{"section":"strings","title":"Strings","content":"Like JavaScript and many other languages, CoffeeScript supports strings as delimited by the \" or ' characters. CoffeeScript also supports string interpolation within \"-quoted strings, using #{ … }. Single-quoted strings are literal. You may even use interpolation in object keys.\"'\"#{ … } author = \"Wittgenstein\" quote = \"A picture is a fact. -- #{ author }\" sentence = \"#{ 22 / 7 } is a decent approximation of π\" author = \"Wittgenstein\" quote = \"A picture is a fact. -- #{ author }\" sentence = \"#{ 22 / 7 } is a decent approximation of π\" var author, quote, sentence; author = \"Wittgenstein\"; quote = `A picture is a fact. -- ${author}`; sentence = `${22 / 7} is a decent approximation of π`; var author, quote, sentence; author = \"Wittgenstein\"; quote = `A picture is a fact. -- ${author}`; sentence = `${22 / 7} is a decent approximation of π`; \t sentence author = \"Wittgenstein\" quote = \"A picture is a fact. -- #{ author }\" sentence = \"#{ 22 / 7 } is a decent approximation of π\" author = \"Wittgenstein\" quote = \"A picture is a fact. -- #{ author }\" sentence = \"#{ 22 / 7 } is a decent approximation of π\" var author, quote, sentence; author = \"Wittgenstein\"; quote = `A picture is a fact. -- ${author}`; sentence = `${22 / 7} is a decent approximation of π`; var author, quote, sentence; author = \"Wittgenstein\"; quote = `A picture is a fact. -- ${author}`; sentence = `${22 / 7} is a decent approximation of π`; author = \"Wittgenstein\" quote = \"A picture is a fact. -- #{ author }\" sentence = \"#{ 22 / 7 } is a decent approximation of π\" author = \"Wittgenstein\" quote = \"A picture is a fact. -- #{ author }\" sentence = \"#{ 22 / 7 } is a decent approximation of π\" author = \"Wittgenstein\" quote = \"A picture is a fact. -- #{ author }\" sentence = \"#{ 22 / 7 } is a decent approximation of π\" author = \"Wittgenstein\" quote = \"A picture is a fact. -- #{ author }\" sentence = \"#{ 22 / 7 } is a decent approximation of π\" author=\"Wittgenstein\"quote=\"A picture is a fact. -- #{ author }\"sentence=\"#{ 22 / 7 } is a decent approximation of π\" var author, quote, sentence; author = \"Wittgenstein\"; quote = `A picture is a fact. -- ${author}`; sentence = `${22 / 7} is a decent approximation of π`; var author, quote, sentence; author = \"Wittgenstein\"; quote = `A picture is a fact. -- ${author}`; sentence = `${22 / 7} is a decent approximation of π`; var author, quote, sentence; author = \"Wittgenstein\"; quote = `A picture is a fact. -- ${author}`; sentence = `${22 / 7} is a decent approximation of π`; var author, quote, sentence; author = \"Wittgenstein\"; quote = `A picture is a fact. -- ${author}`; sentence = `${22 / 7} is a decent approximation of π`; varauthorquotesentenceauthor=\"Wittgenstein\"quote=`A picture is a fact. -- ${author}`sentence=`${22/7}is a decent approximation of π` \t sentence \t sentence \t sentence \t \t Multiline strings are allowed in CoffeeScript. Lines are joined by a single space unless they end with a backslash. Indentation is ignored. mobyDick = \"Call me Ishmael. Some years ago -- never mind how long precisely -- having little or no money in my purse, and nothing particular to interest me on shore, I thought I would sail about a little and see the watery part of the world...\" mobyDick = \"Call me Ishmael. Some years ago -- never mind how long precisely -- having little or no money in my purse, and nothing particular to interest me on shore, I thought I would sail about a little and see the watery part of the world...\" var mobyDick; mobyDick = \"Call me Ishmael. Some years ago -- never mind how long precisely -- having little or no money in my purse, and nothing particular to interest me on shore, I thought I would sail about a little and see the watery part of the world...\"; var mobyDick; mobyDick = \"Call me Ishmael. Some years ago -- never mind how long precisely -- having little or no money in my purse, and nothing particular to interest me on shore, I thought I would sail about a little and see the watery part of the world...\"; \t mobyDick mobyDick = \"Call me Ishmael. Some years ago -- never mind how long precisely -- having little or no money in my purse, and nothing particular to interest me on shore, I thought I would sail about a little and see the watery part of the world...\" mobyDick = \"Call me Ishmael. Some years ago -- never mind how long precisely -- having little or no money in my purse, and nothing particular to interest me on shore, I thought I would sail about a little and see the watery part of the world...\" var mobyDick; mobyDick = \"Call me Ishmael. Some years ago -- never mind how long precisely -- having little or no money in my purse, and nothing particular to interest me on shore, I thought I would sail about a little and see the watery part of the world...\"; var mobyDick; mobyDick = \"Call me Ishmael. Some years ago -- never mind how long precisely -- having little or no money in my purse, and nothing particular to interest me on shore, I thought I would sail about a little and see the watery part of the world...\"; mobyDick = \"Call me Ishmael. Some years ago -- never mind how long precisely -- having little or no money in my purse, and nothing particular to interest me on shore, I thought I would sail about a little and see the watery part of the world...\" mobyDick = \"Call me Ishmael. Some years ago -- never mind how long precisely -- having little or no money in my purse, and nothing particular to interest me on shore, I thought I would sail about a little and see the watery part of the world...\" mobyDick = \"Call me Ishmael. Some years ago -- never mind how long precisely -- having little or no money in my purse, and nothing particular to interest me on shore, I thought I would sail about a little and see the watery part of the world...\" mobyDick = \"Call me Ishmael. Some years ago -- never mind how long precisely -- having little or no money in my purse, and nothing particular to interest me on shore, I thought I would sail about a little and see the watery part of the world...\" mobyDick=\"Call me Ishmael. Some years ago -- never mind how long precisely -- having little or no money in my purse, and nothing particular to interest me on shore, I thought I would sail about a little and see the watery part of the world...\" var mobyDick; mobyDick = \"Call me Ishmael. Some years ago -- never mind how long precisely -- having little or no money in my purse, and nothing particular to interest me on shore, I thought I would sail about a little and see the watery part of the world...\"; var mobyDick; mobyDick = \"Call me Ishmael. Some years ago -- never mind how long precisely -- having little or no money in my purse, and nothing particular to interest me on shore, I thought I would sail about a little and see the watery part of the world...\"; var mobyDick; mobyDick = \"Call me Ishmael. Some years ago -- never mind how long precisely -- having little or no money in my purse, and nothing particular to interest me on shore, I thought I would sail about a little and see the watery part of the world...\"; var mobyDick; mobyDick = \"Call me Ishmael. Some years ago -- never mind how long precisely -- having little or no money in my purse, and nothing particular to interest me on shore, I thought I would sail about a little and see the watery part of the world...\"; varmobyDickmobyDick=\"Call me Ishmael. Some years ago -- never mind how long precisely -- having little or no money in my purse, and nothing particular to interest me on shore, I thought I would sail about a little and see the watery part of the world...\" \t mobyDick \t mobyDick \t mobyDick \t \t Block strings, delimited by \"\"\" or ''', can be used to hold formatted or indentation-sensitive text (or, if you just don’t feel like escaping quotes and apostrophes). The indentation level that begins the block is maintained throughout, so you can keep it all aligned with the body of your code.\"\"\"''' html = \"\"\" cup of coffeescript \"\"\" html = \"\"\" cup of coffeescript \"\"\" var html; html = \"\\n cup of coffeescript\\n\"; var html; html = \"\\n cup of coffeescript\\n\"; \t html html = \"\"\" cup of coffeescript \"\"\" html = \"\"\" cup of coffeescript \"\"\" var html; html = \"\\n cup of coffeescript\\n\"; var html; html = \"\\n cup of coffeescript\\n\"; html = \"\"\" cup of coffeescript \"\"\" html = \"\"\" cup of coffeescript \"\"\" html = \"\"\" cup of coffeescript \"\"\" html = \"\"\" cup of coffeescript \"\"\" html=\"\"\" cup of coffeescript \"\"\" var html; html = \"\\n cup of coffeescript\\n\"; var html; html = \"\\n cup of coffeescript\\n\"; var html; html = \"\\n cup of coffeescript\\n\"; var html; html = \"\\n cup of coffeescript\\n\"; varhtmlhtml=\"\\n cup of coffeescript\\n\" \t html \t html \t html \t \t Double-quoted block strings, like other double-quoted strings, allow interpolation.","dataLevel":1,"level":2,"parent":"language"},{"section":"objects-and-arrays","title":"Objects and Arrays","content":"The CoffeeScript literals for objects and arrays look very similar to their JavaScript cousins. When each property is listed on its own line, the commas are optional. Objects may be created using indentation instead of explicit braces, similar to YAML.YAML song = [\"do\", \"re\", \"mi\", \"fa\", \"so\"] singers = {Jagger: \"Rock\", Elvis: \"Roll\"} bitlist = [ 1, 0, 1 0, 0, 1 1, 1, 0 ] kids = brother: name: \"Max\" age: 11 sister: name: \"Ida\" age: 9 song = [\"do\", \"re\", \"mi\", \"fa\", \"so\"] singers = {Jagger: \"Rock\", Elvis: \"Roll\"} bitlist = [ 1, 0, 1 0, 0, 1 1, 1, 0 ] kids = brother: name: \"Max\" age: 11 sister: name: \"Ida\" age: 9 var bitlist, kids, singers, song; song = [\"do\", \"re\", \"mi\", \"fa\", \"so\"]; singers = { Jagger: \"Rock\", Elvis: \"Roll\" }; bitlist = [1, 0, 1, 0, 0, 1, 1, 1, 0]; kids = { brother: { name: \"Max\", age: 11 }, sister: { name: \"Ida\", age: 9 } }; var bitlist, kids, singers, song; song = [\"do\", \"re\", \"mi\", \"fa\", \"so\"]; singers = { Jagger: \"Rock\", Elvis: \"Roll\" }; bitlist = [1, 0, 1, 0, 0, 1, 1, 1, 0]; kids = { brother: { name: \"Max\", age: 11 }, sister: { name: \"Ida\", age: 9 } }; \t song.join(\" … \") song = [\"do\", \"re\", \"mi\", \"fa\", \"so\"] singers = {Jagger: \"Rock\", Elvis: \"Roll\"} bitlist = [ 1, 0, 1 0, 0, 1 1, 1, 0 ] kids = brother: name: \"Max\" age: 11 sister: name: \"Ida\" age: 9 song = [\"do\", \"re\", \"mi\", \"fa\", \"so\"] singers = {Jagger: \"Rock\", Elvis: \"Roll\"} bitlist = [ 1, 0, 1 0, 0, 1 1, 1, 0 ] kids = brother: name: \"Max\" age: 11 sister: name: \"Ida\" age: 9 var bitlist, kids, singers, song; song = [\"do\", \"re\", \"mi\", \"fa\", \"so\"]; singers = { Jagger: \"Rock\", Elvis: \"Roll\" }; bitlist = [1, 0, 1, 0, 0, 1, 1, 1, 0]; kids = { brother: { name: \"Max\", age: 11 }, sister: { name: \"Ida\", age: 9 } }; var bitlist, kids, singers, song; song = [\"do\", \"re\", \"mi\", \"fa\", \"so\"]; singers = { Jagger: \"Rock\", Elvis: \"Roll\" }; bitlist = [1, 0, 1, 0, 0, 1, 1, 1, 0]; kids = { brother: { name: \"Max\", age: 11 }, sister: { name: \"Ida\", age: 9 } }; song = [\"do\", \"re\", \"mi\", \"fa\", \"so\"] singers = {Jagger: \"Rock\", Elvis: \"Roll\"} bitlist = [ 1, 0, 1 0, 0, 1 1, 1, 0 ] kids = brother: name: \"Max\" age: 11 sister: name: \"Ida\" age: 9 song = [\"do\", \"re\", \"mi\", \"fa\", \"so\"] singers = {Jagger: \"Rock\", Elvis: \"Roll\"} bitlist = [ 1, 0, 1 0, 0, 1 1, 1, 0 ] kids = brother: name: \"Max\" age: 11 sister: name: \"Ida\" age: 9 song = [\"do\", \"re\", \"mi\", \"fa\", \"so\"] singers = {Jagger: \"Rock\", Elvis: \"Roll\"} bitlist = [ 1, 0, 1 0, 0, 1 1, 1, 0 ] kids = brother: name: \"Max\" age: 11 sister: name: \"Ida\" age: 9 song = [\"do\", \"re\", \"mi\", \"fa\", \"so\"] singers = {Jagger: \"Rock\", Elvis: \"Roll\"} bitlist = [ 1, 0, 1 0, 0, 1 1, 1, 0 ] kids = brother: name: \"Max\" age: 11 sister: name: \"Ida\" age: 9 song=[\"do\",\"re\",\"mi\",\"fa\",\"so\"]singers={Jagger:\"Rock\",Elvis:\"Roll\"}bitlist=[1,0,10,0,11,1,0]kids= brother: name:\"Max\"age:11 sister: name:\"Ida\"age:9 var bitlist, kids, singers, song; song = [\"do\", \"re\", \"mi\", \"fa\", \"so\"]; singers = { Jagger: \"Rock\", Elvis: \"Roll\" }; bitlist = [1, 0, 1, 0, 0, 1, 1, 1, 0]; kids = { brother: { name: \"Max\", age: 11 }, sister: { name: \"Ida\", age: 9 } }; var bitlist, kids, singers, song; song = [\"do\", \"re\", \"mi\", \"fa\", \"so\"]; singers = { Jagger: \"Rock\", Elvis: \"Roll\" }; bitlist = [1, 0, 1, 0, 0, 1, 1, 1, 0]; kids = { brother: { name: \"Max\", age: 11 }, sister: { name: \"Ida\", age: 9 } }; var bitlist, kids, singers, song; song = [\"do\", \"re\", \"mi\", \"fa\", \"so\"]; singers = { Jagger: \"Rock\", Elvis: \"Roll\" }; bitlist = [1, 0, 1, 0, 0, 1, 1, 1, 0]; kids = { brother: { name: \"Max\", age: 11 }, sister: { name: \"Ida\", age: 9 } }; var bitlist, kids, singers, song; song = [\"do\", \"re\", \"mi\", \"fa\", \"so\"]; singers = { Jagger: \"Rock\", Elvis: \"Roll\" }; bitlist = [1, 0, 1, 0, 0, 1, 1, 1, 0]; kids = { brother: { name: \"Max\", age: 11 }, sister: { name: \"Ida\", age: 9 } }; varbitlistkidssingerssongsong=\"do\"\"re\"\"mi\"\"fa\"\"so\"singers=Jagger\"Rock\"Elvis\"Roll\"bitlist=101001110kids=brothername\"Max\"age11sistername\"Ida\"age9 \t song.join(\" … \") \t song.join(\" … \") \t song.join(\" … \") \t \t CoffeeScript has a shortcut for creating objects when you want the key to be set with a variable of the same name. name = \"Michelangelo\" mask = \"orange\" weapon = \"nunchuks\" turtle = {name, mask, weapon} output = \"#{turtle.name} wears an #{turtle.mask} mask. Watch out for his #{turtle.weapon}!\" name = \"Michelangelo\" mask = \"orange\" weapon = \"nunchuks\" turtle = {name, mask, weapon} output = \"#{turtle.name} wears an #{turtle.mask} mask. Watch out for his #{turtle.weapon}!\" var mask, name, output, turtle, weapon; name = \"Michelangelo\"; mask = \"orange\"; weapon = \"nunchuks\"; turtle = {name, mask, weapon}; output = `${turtle.name} wears an ${turtle.mask} mask. Watch out for his ${turtle.weapon}!`; var mask, name, output, turtle, weapon; name = \"Michelangelo\"; mask = \"orange\"; weapon = \"nunchuks\"; turtle = {name, mask, weapon}; output = `${turtle.name} wears an ${turtle.mask} mask. Watch out for his ${turtle.weapon}!`; name = \"Michelangelo\" mask = \"orange\" weapon = \"nunchuks\" turtle = {name, mask, weapon} output = \"#{turtle.name} wears an #{turtle.mask} mask. Watch out for his #{turtle.weapon}!\" name = \"Michelangelo\" mask = \"orange\" weapon = \"nunchuks\" turtle = {name, mask, weapon} output = \"#{turtle.name} wears an #{turtle.mask} mask. Watch out for his #{turtle.weapon}!\" var mask, name, output, turtle, weapon; name = \"Michelangelo\"; mask = \"orange\"; weapon = \"nunchuks\"; turtle = {name, mask, weapon}; output = `${turtle.name} wears an ${turtle.mask} mask. Watch out for his ${turtle.weapon}!`; var mask, name, output, turtle, weapon; name = \"Michelangelo\"; mask = \"orange\"; weapon = \"nunchuks\"; turtle = {name, mask, weapon}; output = `${turtle.name} wears an ${turtle.mask} mask. Watch out for his ${turtle.weapon}!`; name = \"Michelangelo\" mask = \"orange\" weapon = \"nunchuks\" turtle = {name, mask, weapon} output = \"#{turtle.name} wears an #{turtle.mask} mask. Watch out for his #{turtle.weapon}!\" name = \"Michelangelo\" mask = \"orange\" weapon = \"nunchuks\" turtle = {name, mask, weapon} output = \"#{turtle.name} wears an #{turtle.mask} mask. Watch out for his #{turtle.weapon}!\" name = \"Michelangelo\" mask = \"orange\" weapon = \"nunchuks\" turtle = {name, mask, weapon} output = \"#{turtle.name} wears an #{turtle.mask} mask. Watch out for his #{turtle.weapon}!\" name = \"Michelangelo\" mask = \"orange\" weapon = \"nunchuks\" turtle = {name, mask, weapon} output = \"#{turtle.name} wears an #{turtle.mask} mask. Watch out for his #{turtle.weapon}!\" name=\"Michelangelo\"mask=\"orange\"weapon=\"nunchuks\"turtle={name,mask,weapon}output=\"#{turtle.name} wears an #{turtle.mask} mask. Watch out for his #{turtle.weapon}!\" var mask, name, output, turtle, weapon; name = \"Michelangelo\"; mask = \"orange\"; weapon = \"nunchuks\"; turtle = {name, mask, weapon}; output = `${turtle.name} wears an ${turtle.mask} mask. Watch out for his ${turtle.weapon}!`; var mask, name, output, turtle, weapon; name = \"Michelangelo\"; mask = \"orange\"; weapon = \"nunchuks\"; turtle = {name, mask, weapon}; output = `${turtle.name} wears an ${turtle.mask} mask. Watch out for his ${turtle.weapon}!`; var mask, name, output, turtle, weapon; name = \"Michelangelo\"; mask = \"orange\"; weapon = \"nunchuks\"; turtle = {name, mask, weapon}; output = `${turtle.name} wears an ${turtle.mask} mask. Watch out for his ${turtle.weapon}!`; var mask, name, output, turtle, weapon; name = \"Michelangelo\"; mask = \"orange\"; weapon = \"nunchuks\"; turtle = {name, mask, weapon}; output = `${turtle.name} wears an ${turtle.mask} mask. Watch out for his ${turtle.weapon}!`; varmasknameoutputturtleweaponname=\"Michelangelo\"mask=\"orange\"weapon=\"nunchuks\"turtle=namemaskweaponoutput=`${turtlename}wears an ${turtlemask}mask. Watch out for his ${turtleweapon}!`","dataLevel":1,"level":2,"parent":"language"},{"section":"comments","title":"Comments","content":"In CoffeeScript, comments are denoted by the # character to the end of a line, or from ### to the next appearance of ###. Comments are ignored by the compiler, though the compiler makes its best effort at reinserting your comments into the output JavaScript after compilation.####### ### Fortune Cookie Reader v1.0 Released under the MIT License ### sayFortune = (fortune) -> console.log fortune # in bed! ### Fortune Cookie Reader v1.0 Released under the MIT License ### sayFortune = (fortune) -> console.log fortune # in bed! /* Fortune Cookie Reader v1.0 Released under the MIT License */ var sayFortune; sayFortune = function(fortune) { return console.log(fortune); // in bed! }; /* Fortune Cookie Reader v1.0 Released under the MIT License */ var sayFortune; sayFortune = function(fortune) { return console.log(fortune); // in bed! }; ### Fortune Cookie Reader v1.0 Released under the MIT License ### sayFortune = (fortune) -> console.log fortune # in bed! ### Fortune Cookie Reader v1.0 Released under the MIT License ### sayFortune = (fortune) -> console.log fortune # in bed! /* Fortune Cookie Reader v1.0 Released under the MIT License */ var sayFortune; sayFortune = function(fortune) { return console.log(fortune); // in bed! }; /* Fortune Cookie Reader v1.0 Released under the MIT License */ var sayFortune; sayFortune = function(fortune) { return console.log(fortune); // in bed! }; ### Fortune Cookie Reader v1.0 Released under the MIT License ### sayFortune = (fortune) -> console.log fortune # in bed! ### Fortune Cookie Reader v1.0 Released under the MIT License ### sayFortune = (fortune) -> console.log fortune # in bed! ### Fortune Cookie Reader v1.0 Released under the MIT License ### sayFortune = (fortune) -> console.log fortune # in bed! ### Fortune Cookie Reader v1.0 Released under the MIT License ### sayFortune = (fortune) -> console.log fortune # in bed! ###Fortune Cookie Reader v1.0Released under the MIT License###sayFortune=(fortune)->console.logfortune# in bed! /* Fortune Cookie Reader v1.0 Released under the MIT License */ var sayFortune; sayFortune = function(fortune) { return console.log(fortune); // in bed! }; /* Fortune Cookie Reader v1.0 Released under the MIT License */ var sayFortune; sayFortune = function(fortune) { return console.log(fortune); // in bed! }; /* Fortune Cookie Reader v1.0 Released under the MIT License */ var sayFortune; sayFortune = function(fortune) { return console.log(fortune); // in bed! }; /* Fortune Cookie Reader v1.0 Released under the MIT License */ var sayFortune; sayFortune = function(fortune) { return console.log(fortune); // in bed! }; /*Fortune Cookie Reader v1.0Released under the MIT License*/varsayFortunesayFortune=functionfortunereturnconsolelogfortune// in bed!Inline ### comments make type annotations possible.###type annotations","dataLevel":1,"level":2,"parent":"language"},{"section":"lexical-scope","title":"Lexical Scoping and Variable Safety","content":"The CoffeeScript compiler takes care to make sure that all of your variables are properly declared within lexical scope — you never need to write var yourself.var outer = 1 changeNumbers = -> inner = -1 outer = 10 inner = changeNumbers() outer = 1 changeNumbers = -> inner = -1 outer = 10 inner = changeNumbers() var changeNumbers, inner, outer; outer = 1; changeNumbers = function() { var inner; inner = -1; return outer = 10; }; inner = changeNumbers(); var changeNumbers, inner, outer; outer = 1; changeNumbers = function() { var inner; inner = -1; return outer = 10; }; inner = changeNumbers(); \t inner outer = 1 changeNumbers = -> inner = -1 outer = 10 inner = changeNumbers() outer = 1 changeNumbers = -> inner = -1 outer = 10 inner = changeNumbers() var changeNumbers, inner, outer; outer = 1; changeNumbers = function() { var inner; inner = -1; return outer = 10; }; inner = changeNumbers(); var changeNumbers, inner, outer; outer = 1; changeNumbers = function() { var inner; inner = -1; return outer = 10; }; inner = changeNumbers(); outer = 1 changeNumbers = -> inner = -1 outer = 10 inner = changeNumbers() outer = 1 changeNumbers = -> inner = -1 outer = 10 inner = changeNumbers() outer = 1 changeNumbers = -> inner = -1 outer = 10 inner = changeNumbers() outer = 1 changeNumbers = -> inner = -1 outer = 10 inner = changeNumbers() outer=1changeNumbers=->inner=-1outer=10inner=changeNumbers() var changeNumbers, inner, outer; outer = 1; changeNumbers = function() { var inner; inner = -1; return outer = 10; }; inner = changeNumbers(); var changeNumbers, inner, outer; outer = 1; changeNumbers = function() { var inner; inner = -1; return outer = 10; }; inner = changeNumbers(); var changeNumbers, inner, outer; outer = 1; changeNumbers = function() { var inner; inner = -1; return outer = 10; }; inner = changeNumbers(); var changeNumbers, inner, outer; outer = 1; changeNumbers = function() { var inner; inner = -1; return outer = 10; }; inner = changeNumbers(); varchangeNumbersinnerouterouter=1changeNumbers=functionvarinnerinner=-1returnouter=10inner=changeNumbers \t inner \t inner \t inner \t \t Notice how all of the variable declarations have been pushed up to the top of the closest scope, the first time they appear. outer is not redeclared within the inner function, because it’s already in scope; inner within the function, on the other hand, should not be able to change the value of the external variable of the same name, and therefore has a declaration of its own.outerinnerBecause you don’t have direct access to the var keyword, it’s impossible to shadow an outer variable on purpose, you may only refer to it. So be careful that you’re not reusing the name of an external variable accidentally, if you’re writing a deeply nested function.varAlthough suppressed within this documentation for clarity, all CoffeeScript output (except in files with import or export statements) is wrapped in an anonymous function: (function(){ … })();. This safety wrapper, combined with the automatic generation of the var keyword, make it exceedingly difficult to pollute the global namespace by accident. (The safety wrapper can be disabled with the bare option, and is unnecessary and automatically disabled when using modules.)importexport(function(){ … })();varbare optionbareIf you’d like to create top-level variables for other scripts to use, attach them as properties on window; attach them as properties on the exports object in CommonJS; or use an export statement. If you’re targeting both CommonJS and the browser, the existential operator (covered below), gives you a reliable way to figure out where to add them: exports ? this.windowexportsexport statementexportexistential operatorexports ? thisSince CoffeeScript takes care of all variable declaration, it is not possible to declare variables with ES2015’s let or const. This is intentional; we feel that the simplicity gained by not having to think about variable declaration outweighs the benefit of having three separate ways to declare variables.letconstThis is intentional","dataLevel":1,"level":2,"parent":"language"},{"section":"conditionals","title":"If, Else, Unless, and Conditional Assignment","content":"if/else statements can be written without the use of parentheses and curly brackets. As with functions and other block expressions, multi-line conditionals are delimited by indentation. There’s also a handy postfix form, with the if or unless at the end.ifelseifunlessCoffeeScript can compile if statements into JavaScript expressions, using the ternary operator when possible, and closure wrapping otherwise. There is no explicit ternary statement in CoffeeScript — you simply use a regular if statement on a single line.ifif mood = greatlyImproved if singing if happy and knowsIt clapsHands() chaChaCha() else showIt() date = if friday then sue else jill mood = greatlyImproved if singing if happy and knowsIt clapsHands() chaChaCha() else showIt() date = if friday then sue else jill var date, mood; if (singing) { mood = greatlyImproved; } if (happy && knowsIt) { clapsHands(); chaChaCha(); } else { showIt(); } date = friday ? sue : jill; var date, mood; if (singing) { mood = greatlyImproved; } if (happy && knowsIt) { clapsHands(); chaChaCha(); } else { showIt(); } date = friday ? sue : jill; mood = greatlyImproved if singing if happy and knowsIt clapsHands() chaChaCha() else showIt() date = if friday then sue else jill mood = greatlyImproved if singing if happy and knowsIt clapsHands() chaChaCha() else showIt() date = if friday then sue else jill var date, mood; if (singing) { mood = greatlyImproved; } if (happy && knowsIt) { clapsHands(); chaChaCha(); } else { showIt(); } date = friday ? sue : jill; var date, mood; if (singing) { mood = greatlyImproved; } if (happy && knowsIt) { clapsHands(); chaChaCha(); } else { showIt(); } date = friday ? sue : jill; mood = greatlyImproved if singing if happy and knowsIt clapsHands() chaChaCha() else showIt() date = if friday then sue else jill mood = greatlyImproved if singing if happy and knowsIt clapsHands() chaChaCha() else showIt() date = if friday then sue else jill mood = greatlyImproved if singing if happy and knowsIt clapsHands() chaChaCha() else showIt() date = if friday then sue else jill mood = greatlyImproved if singing if happy and knowsIt clapsHands() chaChaCha() else showIt() date = if friday then sue else jill mood=greatlyImprovedifsingingifhappyandknowsItclapsHands()chaChaCha()elseshowIt()date=iffridaythensueelsejill var date, mood; if (singing) { mood = greatlyImproved; } if (happy && knowsIt) { clapsHands(); chaChaCha(); } else { showIt(); } date = friday ? sue : jill; var date, mood; if (singing) { mood = greatlyImproved; } if (happy && knowsIt) { clapsHands(); chaChaCha(); } else { showIt(); } date = friday ? sue : jill; var date, mood; if (singing) { mood = greatlyImproved; } if (happy && knowsIt) { clapsHands(); chaChaCha(); } else { showIt(); } date = friday ? sue : jill; var date, mood; if (singing) { mood = greatlyImproved; } if (happy && knowsIt) { clapsHands(); chaChaCha(); } else { showIt(); } date = friday ? sue : jill; vardatemoodifsingingmood=greatlyImprovedifhappy&&knowsItclapsHandschaChaChaelseshowItdate=friday?suejill","dataLevel":1,"level":2,"parent":"language"},{"section":"splats","title":"Splats, or Rest Parameters/Spread Syntax","content":"The JavaScript arguments object is a useful way to work with functions that accept variable numbers of arguments. CoffeeScript provides splats ..., both for function definition as well as invocation, making variable numbers of arguments a little bit more palatable. ES2015 adopted this feature as their rest parameters.arguments...rest parameters gold = silver = rest = \"unknown\" awardMedals = (first, second, others...) -> gold = first silver = second rest = others contenders = [ \"Michael Phelps\" \"Liu Xiang\" \"Yao Ming\" \"Allyson Felix\" \"Shawn Johnson\" \"Roman Sebrle\" \"Guo Jingjing\" \"Tyson Gay\" \"Asafa Powell\" \"Usain Bolt\" ] awardMedals contenders... alert \"\"\" Gold: #{gold} Silver: #{silver} The Field: #{rest.join ', '} \"\"\" gold = silver = rest = \"unknown\" awardMedals = (first, second, others...) -> gold = first silver = second rest = others contenders = [ \"Michael Phelps\" \"Liu Xiang\" \"Yao Ming\" \"Allyson Felix\" \"Shawn Johnson\" \"Roman Sebrle\" \"Guo Jingjing\" \"Tyson Gay\" \"Asafa Powell\" \"Usain Bolt\" ] awardMedals contenders... alert \"\"\" Gold: #{gold} Silver: #{silver} The Field: #{rest.join ', '} \"\"\" var awardMedals, contenders, gold, rest, silver; gold = silver = rest = \"unknown\"; awardMedals = function(first, second, ...others) { gold = first; silver = second; return rest = others; }; contenders = [\"Michael Phelps\", \"Liu Xiang\", \"Yao Ming\", \"Allyson Felix\", \"Shawn Johnson\", \"Roman Sebrle\", \"Guo Jingjing\", \"Tyson Gay\", \"Asafa Powell\", \"Usain Bolt\"]; awardMedals(...contenders); alert(`Gold: ${gold}\\nSilver: ${silver}\\nThe Field: ${rest.join(', ')}`); var awardMedals, contenders, gold, rest, silver; gold = silver = rest = \"unknown\"; awardMedals = function(first, second, ...others) { gold = first; silver = second; return rest = others; }; contenders = [\"Michael Phelps\", \"Liu Xiang\", \"Yao Ming\", \"Allyson Felix\", \"Shawn Johnson\", \"Roman Sebrle\", \"Guo Jingjing\", \"Tyson Gay\", \"Asafa Powell\", \"Usain Bolt\"]; awardMedals(...contenders); alert(`Gold: ${gold}\\nSilver: ${silver}\\nThe Field: ${rest.join(', ')}`); \t gold = silver = rest = \"unknown\" awardMedals = (first, second, others...) -> gold = first silver = second rest = others contenders = [ \"Michael Phelps\" \"Liu Xiang\" \"Yao Ming\" \"Allyson Felix\" \"Shawn Johnson\" \"Roman Sebrle\" \"Guo Jingjing\" \"Tyson Gay\" \"Asafa Powell\" \"Usain Bolt\" ] awardMedals contenders... alert \"\"\" Gold: #{gold} Silver: #{silver} The Field: #{rest.join ', '} \"\"\" gold = silver = rest = \"unknown\" awardMedals = (first, second, others...) -> gold = first silver = second rest = others contenders = [ \"Michael Phelps\" \"Liu Xiang\" \"Yao Ming\" \"Allyson Felix\" \"Shawn Johnson\" \"Roman Sebrle\" \"Guo Jingjing\" \"Tyson Gay\" \"Asafa Powell\" \"Usain Bolt\" ] awardMedals contenders... alert \"\"\" Gold: #{gold} Silver: #{silver} The Field: #{rest.join ', '} \"\"\" var awardMedals, contenders, gold, rest, silver; gold = silver = rest = \"unknown\"; awardMedals = function(first, second, ...others) { gold = first; silver = second; return rest = others; }; contenders = [\"Michael Phelps\", \"Liu Xiang\", \"Yao Ming\", \"Allyson Felix\", \"Shawn Johnson\", \"Roman Sebrle\", \"Guo Jingjing\", \"Tyson Gay\", \"Asafa Powell\", \"Usain Bolt\"]; awardMedals(...contenders); alert(`Gold: ${gold}\\nSilver: ${silver}\\nThe Field: ${rest.join(', ')}`); var awardMedals, contenders, gold, rest, silver; gold = silver = rest = \"unknown\"; awardMedals = function(first, second, ...others) { gold = first; silver = second; return rest = others; }; contenders = [\"Michael Phelps\", \"Liu Xiang\", \"Yao Ming\", \"Allyson Felix\", \"Shawn Johnson\", \"Roman Sebrle\", \"Guo Jingjing\", \"Tyson Gay\", \"Asafa Powell\", \"Usain Bolt\"]; awardMedals(...contenders); alert(`Gold: ${gold}\\nSilver: ${silver}\\nThe Field: ${rest.join(', ')}`); gold = silver = rest = \"unknown\" awardMedals = (first, second, others...) -> gold = first silver = second rest = others contenders = [ \"Michael Phelps\" \"Liu Xiang\" \"Yao Ming\" \"Allyson Felix\" \"Shawn Johnson\" \"Roman Sebrle\" \"Guo Jingjing\" \"Tyson Gay\" \"Asafa Powell\" \"Usain Bolt\" ] awardMedals contenders... alert \"\"\" Gold: #{gold} Silver: #{silver} The Field: #{rest.join ', '} \"\"\" gold = silver = rest = \"unknown\" awardMedals = (first, second, others...) -> gold = first silver = second rest = others contenders = [ \"Michael Phelps\" \"Liu Xiang\" \"Yao Ming\" \"Allyson Felix\" \"Shawn Johnson\" \"Roman Sebrle\" \"Guo Jingjing\" \"Tyson Gay\" \"Asafa Powell\" \"Usain Bolt\" ] awardMedals contenders... alert \"\"\" Gold: #{gold} Silver: #{silver} The Field: #{rest.join ', '} \"\"\" gold = silver = rest = \"unknown\" awardMedals = (first, second, others...) -> gold = first silver = second rest = others contenders = [ \"Michael Phelps\" \"Liu Xiang\" \"Yao Ming\" \"Allyson Felix\" \"Shawn Johnson\" \"Roman Sebrle\" \"Guo Jingjing\" \"Tyson Gay\" \"Asafa Powell\" \"Usain Bolt\" ] awardMedals contenders... alert \"\"\" Gold: #{gold} Silver: #{silver} The Field: #{rest.join ', '} \"\"\" gold = silver = rest = \"unknown\" awardMedals = (first, second, others...) -> gold = first silver = second rest = others contenders = [ \"Michael Phelps\" \"Liu Xiang\" \"Yao Ming\" \"Allyson Felix\" \"Shawn Johnson\" \"Roman Sebrle\" \"Guo Jingjing\" \"Tyson Gay\" \"Asafa Powell\" \"Usain Bolt\" ] awardMedals contenders... alert \"\"\" Gold: #{gold} Silver: #{silver} The Field: #{rest.join ', '} \"\"\" gold=silver=rest=\"unknown\"awardMedals=(first,second,others...)->gold=firstsilver=secondrest=otherscontenders=[\"Michael Phelps\"\"Liu Xiang\"\"Yao Ming\"\"Allyson Felix\"\"Shawn Johnson\"\"Roman Sebrle\"\"Guo Jingjing\"\"Tyson Gay\"\"Asafa Powell\"\"Usain Bolt\"]awardMedalscontenders...alert\"\"\"Gold: #{gold}Silver: #{silver}The Field: #{rest.join ', '}\"\"\" var awardMedals, contenders, gold, rest, silver; gold = silver = rest = \"unknown\"; awardMedals = function(first, second, ...others) { gold = first; silver = second; return rest = others; }; contenders = [\"Michael Phelps\", \"Liu Xiang\", \"Yao Ming\", \"Allyson Felix\", \"Shawn Johnson\", \"Roman Sebrle\", \"Guo Jingjing\", \"Tyson Gay\", \"Asafa Powell\", \"Usain Bolt\"]; awardMedals(...contenders); alert(`Gold: ${gold}\\nSilver: ${silver}\\nThe Field: ${rest.join(', ')}`); var awardMedals, contenders, gold, rest, silver; gold = silver = rest = \"unknown\"; awardMedals = function(first, second, ...others) { gold = first; silver = second; return rest = others; }; contenders = [\"Michael Phelps\", \"Liu Xiang\", \"Yao Ming\", \"Allyson Felix\", \"Shawn Johnson\", \"Roman Sebrle\", \"Guo Jingjing\", \"Tyson Gay\", \"Asafa Powell\", \"Usain Bolt\"]; awardMedals(...contenders); alert(`Gold: ${gold}\\nSilver: ${silver}\\nThe Field: ${rest.join(', ')}`); var awardMedals, contenders, gold, rest, silver; gold = silver = rest = \"unknown\"; awardMedals = function(first, second, ...others) { gold = first; silver = second; return rest = others; }; contenders = [\"Michael Phelps\", \"Liu Xiang\", \"Yao Ming\", \"Allyson Felix\", \"Shawn Johnson\", \"Roman Sebrle\", \"Guo Jingjing\", \"Tyson Gay\", \"Asafa Powell\", \"Usain Bolt\"]; awardMedals(...contenders); alert(`Gold: ${gold}\\nSilver: ${silver}\\nThe Field: ${rest.join(', ')}`); var awardMedals, contenders, gold, rest, silver; gold = silver = rest = \"unknown\"; awardMedals = function(first, second, ...others) { gold = first; silver = second; return rest = others; }; contenders = [\"Michael Phelps\", \"Liu Xiang\", \"Yao Ming\", \"Allyson Felix\", \"Shawn Johnson\", \"Roman Sebrle\", \"Guo Jingjing\", \"Tyson Gay\", \"Asafa Powell\", \"Usain Bolt\"]; awardMedals(...contenders); alert(`Gold: ${gold}\\nSilver: ${silver}\\nThe Field: ${rest.join(', ')}`); varawardMedalscontendersgoldrestsilvergold=silver=rest=\"unknown\"awardMedals=functionfirstsecond...othersgold=firstsilver=secondreturnrest=otherscontenders=\"Michael Phelps\"\"Liu Xiang\"\"Yao Ming\"\"Allyson Felix\"\"Shawn Johnson\"\"Roman Sebrle\"\"Guo Jingjing\"\"Tyson Gay\"\"Asafa Powell\"\"Usain Bolt\"awardMedals...contendersalert`Gold: ${gold}\\nSilver: ${silver}\\nThe Field: ${restjoin', '}` \t \t \t \t \t Splats also let us elide array elements… popular = ['pepperoni', 'sausage', 'cheese'] unwanted = ['anchovies', 'olives'] all = [popular..., unwanted..., 'mushrooms'] popular = ['pepperoni', 'sausage', 'cheese'] unwanted = ['anchovies', 'olives'] all = [popular..., unwanted..., 'mushrooms'] var all, popular, unwanted; popular = ['pepperoni', 'sausage', 'cheese']; unwanted = ['anchovies', 'olives']; all = [...popular, ...unwanted, 'mushrooms']; var all, popular, unwanted; popular = ['pepperoni', 'sausage', 'cheese']; unwanted = ['anchovies', 'olives']; all = [...popular, ...unwanted, 'mushrooms']; \t all popular = ['pepperoni', 'sausage', 'cheese'] unwanted = ['anchovies', 'olives'] all = [popular..., unwanted..., 'mushrooms'] popular = ['pepperoni', 'sausage', 'cheese'] unwanted = ['anchovies', 'olives'] all = [popular..., unwanted..., 'mushrooms'] var all, popular, unwanted; popular = ['pepperoni', 'sausage', 'cheese']; unwanted = ['anchovies', 'olives']; all = [...popular, ...unwanted, 'mushrooms']; var all, popular, unwanted; popular = ['pepperoni', 'sausage', 'cheese']; unwanted = ['anchovies', 'olives']; all = [...popular, ...unwanted, 'mushrooms']; popular = ['pepperoni', 'sausage', 'cheese'] unwanted = ['anchovies', 'olives'] all = [popular..., unwanted..., 'mushrooms'] popular = ['pepperoni', 'sausage', 'cheese'] unwanted = ['anchovies', 'olives'] all = [popular..., unwanted..., 'mushrooms'] popular = ['pepperoni', 'sausage', 'cheese'] unwanted = ['anchovies', 'olives'] all = [popular..., unwanted..., 'mushrooms'] popular = ['pepperoni', 'sausage', 'cheese'] unwanted = ['anchovies', 'olives'] all = [popular..., unwanted..., 'mushrooms'] popular=['pepperoni','sausage','cheese']unwanted=['anchovies','olives']all=[popular...,unwanted...,'mushrooms'] var all, popular, unwanted; popular = ['pepperoni', 'sausage', 'cheese']; unwanted = ['anchovies', 'olives']; all = [...popular, ...unwanted, 'mushrooms']; var all, popular, unwanted; popular = ['pepperoni', 'sausage', 'cheese']; unwanted = ['anchovies', 'olives']; all = [...popular, ...unwanted, 'mushrooms']; var all, popular, unwanted; popular = ['pepperoni', 'sausage', 'cheese']; unwanted = ['anchovies', 'olives']; all = [...popular, ...unwanted, 'mushrooms']; var all, popular, unwanted; popular = ['pepperoni', 'sausage', 'cheese']; unwanted = ['anchovies', 'olives']; all = [...popular, ...unwanted, 'mushrooms']; varallpopularunwantedpopular='pepperoni''sausage''cheese'unwanted='anchovies''olives'all=...popular...unwanted'mushrooms' \t all \t all \t all \t \t …and object properties. user = name: 'Werner Heisenberg' occupation: 'theoretical physicist' currentUser = { user..., status: 'Uncertain' } user = name: 'Werner Heisenberg' occupation: 'theoretical physicist' currentUser = { user..., status: 'Uncertain' } var currentUser, user; user = { name: 'Werner Heisenberg', occupation: 'theoretical physicist' }; currentUser = { ...user, status: 'Uncertain' }; var currentUser, user; user = { name: 'Werner Heisenberg', occupation: 'theoretical physicist' }; currentUser = { ...user, status: 'Uncertain' }; \t JSON.stringify(currentUser) user = name: 'Werner Heisenberg' occupation: 'theoretical physicist' currentUser = { user..., status: 'Uncertain' } user = name: 'Werner Heisenberg' occupation: 'theoretical physicist' currentUser = { user..., status: 'Uncertain' } var currentUser, user; user = { name: 'Werner Heisenberg', occupation: 'theoretical physicist' }; currentUser = { ...user, status: 'Uncertain' }; var currentUser, user; user = { name: 'Werner Heisenberg', occupation: 'theoretical physicist' }; currentUser = { ...user, status: 'Uncertain' }; user = name: 'Werner Heisenberg' occupation: 'theoretical physicist' currentUser = { user..., status: 'Uncertain' } user = name: 'Werner Heisenberg' occupation: 'theoretical physicist' currentUser = { user..., status: 'Uncertain' } user = name: 'Werner Heisenberg' occupation: 'theoretical physicist' currentUser = { user..., status: 'Uncertain' } user = name: 'Werner Heisenberg' occupation: 'theoretical physicist' currentUser = { user..., status: 'Uncertain' } user= name:'Werner Heisenberg'occupation:'theoretical physicist'currentUser={user...,status:'Uncertain'} var currentUser, user; user = { name: 'Werner Heisenberg', occupation: 'theoretical physicist' }; currentUser = { ...user, status: 'Uncertain' }; var currentUser, user; user = { name: 'Werner Heisenberg', occupation: 'theoretical physicist' }; currentUser = { ...user, status: 'Uncertain' }; var currentUser, user; user = { name: 'Werner Heisenberg', occupation: 'theoretical physicist' }; currentUser = { ...user, status: 'Uncertain' }; var currentUser, user; user = { name: 'Werner Heisenberg', occupation: 'theoretical physicist' }; currentUser = { ...user, status: 'Uncertain' }; varcurrentUseruseruser=name'Werner Heisenberg'occupation'theoretical physicist'currentUser=...userstatus'Uncertain' \t JSON.stringify(currentUser) \t JSON.stringify(currentUser) \t JSON.stringify(currentUser) \t \t In ECMAScript this is called spread syntax, and has been supported for arrays since ES2015 and objects since ES2018.spread syntax","dataLevel":1,"level":2,"parent":"language"},{"section":"loops","title":"Loops and Comprehensions","content":"Most of the loops you’ll write in CoffeeScript will be comprehensions over arrays, objects, and ranges. Comprehensions replace (and compile into) for loops, with optional guard clauses and the value of the current array index. Unlike for loops, array comprehensions are expressions, and can be returned and assigned.comprehensionsfor # Eat lunch. eat = (food) -> \"#{food} eaten.\" eat food for food in ['toast', 'cheese', 'wine'] # Fine five course dining. courses = ['greens', 'caviar', 'truffles', 'roast', 'cake'] menu = (i, dish) -> \"Menu Item #{i}: #{dish}\" menu i + 1, dish for dish, i in courses # Health conscious meal. foods = ['broccoli', 'spinach', 'chocolate'] eat food for food in foods when food isnt 'chocolate' # Eat lunch. eat = (food) -> \"#{food} eaten.\" eat food for food in ['toast', 'cheese', 'wine'] # Fine five course dining. courses = ['greens', 'caviar', 'truffles', 'roast', 'cake'] menu = (i, dish) -> \"Menu Item #{i}: #{dish}\" menu i + 1, dish for dish, i in courses # Health conscious meal. foods = ['broccoli', 'spinach', 'chocolate'] eat food for food in foods when food isnt 'chocolate' // Eat lunch. var courses, dish, eat, food, foods, i, j, k, l, len, len1, len2, menu, ref; eat = function(food) { return `${food} eaten.`; }; ref = ['toast', 'cheese', 'wine']; for (j = 0, len = ref.length; j < len; j++) { food = ref[j]; eat(food); } // Fine five course dining. courses = ['greens', 'caviar', 'truffles', 'roast', 'cake']; menu = function(i, dish) { return `Menu Item ${i}: ${dish}`; }; for (i = k = 0, len1 = courses.length; k < len1; i = ++k) { dish = courses[i]; menu(i + 1, dish); } // Health conscious meal. foods = ['broccoli', 'spinach', 'chocolate']; for (l = 0, len2 = foods.length; l < len2; l++) { food = foods[l]; if (food !== 'chocolate') { eat(food); } } // Eat lunch. var courses, dish, eat, food, foods, i, j, k, l, len, len1, len2, menu, ref; eat = function(food) { return `${food} eaten.`; }; ref = ['toast', 'cheese', 'wine']; for (j = 0, len = ref.length; j < len; j++) { food = ref[j]; eat(food); } // Fine five course dining. courses = ['greens', 'caviar', 'truffles', 'roast', 'cake']; menu = function(i, dish) { return `Menu Item ${i}: ${dish}`; }; for (i = k = 0, len1 = courses.length; k < len1; i = ++k) { dish = courses[i]; menu(i + 1, dish); } // Health conscious meal. foods = ['broccoli', 'spinach', 'chocolate']; for (l = 0, len2 = foods.length; l < len2; l++) { food = foods[l]; if (food !== 'chocolate') { eat(food); } } # Eat lunch. eat = (food) -> \"#{food} eaten.\" eat food for food in ['toast', 'cheese', 'wine'] # Fine five course dining. courses = ['greens', 'caviar', 'truffles', 'roast', 'cake'] menu = (i, dish) -> \"Menu Item #{i}: #{dish}\" menu i + 1, dish for dish, i in courses # Health conscious meal. foods = ['broccoli', 'spinach', 'chocolate'] eat food for food in foods when food isnt 'chocolate' # Eat lunch. eat = (food) -> \"#{food} eaten.\" eat food for food in ['toast', 'cheese', 'wine'] # Fine five course dining. courses = ['greens', 'caviar', 'truffles', 'roast', 'cake'] menu = (i, dish) -> \"Menu Item #{i}: #{dish}\" menu i + 1, dish for dish, i in courses # Health conscious meal. foods = ['broccoli', 'spinach', 'chocolate'] eat food for food in foods when food isnt 'chocolate' // Eat lunch. var courses, dish, eat, food, foods, i, j, k, l, len, len1, len2, menu, ref; eat = function(food) { return `${food} eaten.`; }; ref = ['toast', 'cheese', 'wine']; for (j = 0, len = ref.length; j < len; j++) { food = ref[j]; eat(food); } // Fine five course dining. courses = ['greens', 'caviar', 'truffles', 'roast', 'cake']; menu = function(i, dish) { return `Menu Item ${i}: ${dish}`; }; for (i = k = 0, len1 = courses.length; k < len1; i = ++k) { dish = courses[i]; menu(i + 1, dish); } // Health conscious meal. foods = ['broccoli', 'spinach', 'chocolate']; for (l = 0, len2 = foods.length; l < len2; l++) { food = foods[l]; if (food !== 'chocolate') { eat(food); } } // Eat lunch. var courses, dish, eat, food, foods, i, j, k, l, len, len1, len2, menu, ref; eat = function(food) { return `${food} eaten.`; }; ref = ['toast', 'cheese', 'wine']; for (j = 0, len = ref.length; j < len; j++) { food = ref[j]; eat(food); } // Fine five course dining. courses = ['greens', 'caviar', 'truffles', 'roast', 'cake']; menu = function(i, dish) { return `Menu Item ${i}: ${dish}`; }; for (i = k = 0, len1 = courses.length; k < len1; i = ++k) { dish = courses[i]; menu(i + 1, dish); } // Health conscious meal. foods = ['broccoli', 'spinach', 'chocolate']; for (l = 0, len2 = foods.length; l < len2; l++) { food = foods[l]; if (food !== 'chocolate') { eat(food); } } # Eat lunch. eat = (food) -> \"#{food} eaten.\" eat food for food in ['toast', 'cheese', 'wine'] # Fine five course dining. courses = ['greens', 'caviar', 'truffles', 'roast', 'cake'] menu = (i, dish) -> \"Menu Item #{i}: #{dish}\" menu i + 1, dish for dish, i in courses # Health conscious meal. foods = ['broccoli', 'spinach', 'chocolate'] eat food for food in foods when food isnt 'chocolate' # Eat lunch. eat = (food) -> \"#{food} eaten.\" eat food for food in ['toast', 'cheese', 'wine'] # Fine five course dining. courses = ['greens', 'caviar', 'truffles', 'roast', 'cake'] menu = (i, dish) -> \"Menu Item #{i}: #{dish}\" menu i + 1, dish for dish, i in courses # Health conscious meal. foods = ['broccoli', 'spinach', 'chocolate'] eat food for food in foods when food isnt 'chocolate' # Eat lunch. eat = (food) -> \"#{food} eaten.\" eat food for food in ['toast', 'cheese', 'wine'] # Fine five course dining. courses = ['greens', 'caviar', 'truffles', 'roast', 'cake'] menu = (i, dish) -> \"Menu Item #{i}: #{dish}\" menu i + 1, dish for dish, i in courses # Health conscious meal. foods = ['broccoli', 'spinach', 'chocolate'] eat food for food in foods when food isnt 'chocolate' # Eat lunch. eat = (food) -> \"#{food} eaten.\" eat food for food in ['toast', 'cheese', 'wine'] # Fine five course dining. courses = ['greens', 'caviar', 'truffles', 'roast', 'cake'] menu = (i, dish) -> \"Menu Item #{i}: #{dish}\" menu i + 1, dish for dish, i in courses # Health conscious meal. foods = ['broccoli', 'spinach', 'chocolate'] eat food for food in foods when food isnt 'chocolate' # Eat lunch.eat=(food)->\"#{food} eaten.\"eatfoodforfoodin['toast','cheese','wine']# Fine five course dining.courses=['greens','caviar','truffles','roast','cake']menu=(i,dish)->\"Menu Item #{i}: #{dish}\"menui+1,dishfordish,iincourses# Health conscious meal.foods=['broccoli','spinach','chocolate']eatfoodforfoodinfoodswhenfoodisnt'chocolate' // Eat lunch. var courses, dish, eat, food, foods, i, j, k, l, len, len1, len2, menu, ref; eat = function(food) { return `${food} eaten.`; }; ref = ['toast', 'cheese', 'wine']; for (j = 0, len = ref.length; j < len; j++) { food = ref[j]; eat(food); } // Fine five course dining. courses = ['greens', 'caviar', 'truffles', 'roast', 'cake']; menu = function(i, dish) { return `Menu Item ${i}: ${dish}`; }; for (i = k = 0, len1 = courses.length; k < len1; i = ++k) { dish = courses[i]; menu(i + 1, dish); } // Health conscious meal. foods = ['broccoli', 'spinach', 'chocolate']; for (l = 0, len2 = foods.length; l < len2; l++) { food = foods[l]; if (food !== 'chocolate') { eat(food); } } // Eat lunch. var courses, dish, eat, food, foods, i, j, k, l, len, len1, len2, menu, ref; eat = function(food) { return `${food} eaten.`; }; ref = ['toast', 'cheese', 'wine']; for (j = 0, len = ref.length; j < len; j++) { food = ref[j]; eat(food); } // Fine five course dining. courses = ['greens', 'caviar', 'truffles', 'roast', 'cake']; menu = function(i, dish) { return `Menu Item ${i}: ${dish}`; }; for (i = k = 0, len1 = courses.length; k < len1; i = ++k) { dish = courses[i]; menu(i + 1, dish); } // Health conscious meal. foods = ['broccoli', 'spinach', 'chocolate']; for (l = 0, len2 = foods.length; l < len2; l++) { food = foods[l]; if (food !== 'chocolate') { eat(food); } } // Eat lunch. var courses, dish, eat, food, foods, i, j, k, l, len, len1, len2, menu, ref; eat = function(food) { return `${food} eaten.`; }; ref = ['toast', 'cheese', 'wine']; for (j = 0, len = ref.length; j < len; j++) { food = ref[j]; eat(food); } // Fine five course dining. courses = ['greens', 'caviar', 'truffles', 'roast', 'cake']; menu = function(i, dish) { return `Menu Item ${i}: ${dish}`; }; for (i = k = 0, len1 = courses.length; k < len1; i = ++k) { dish = courses[i]; menu(i + 1, dish); } // Health conscious meal. foods = ['broccoli', 'spinach', 'chocolate']; for (l = 0, len2 = foods.length; l < len2; l++) { food = foods[l]; if (food !== 'chocolate') { eat(food); } } // Eat lunch. var courses, dish, eat, food, foods, i, j, k, l, len, len1, len2, menu, ref; eat = function(food) { return `${food} eaten.`; }; ref = ['toast', 'cheese', 'wine']; for (j = 0, len = ref.length; j < len; j++) { food = ref[j]; eat(food); } // Fine five course dining. courses = ['greens', 'caviar', 'truffles', 'roast', 'cake']; menu = function(i, dish) { return `Menu Item ${i}: ${dish}`; }; for (i = k = 0, len1 = courses.length; k < len1; i = ++k) { dish = courses[i]; menu(i + 1, dish); } // Health conscious meal. foods = ['broccoli', 'spinach', 'chocolate']; for (l = 0, len2 = foods.length; l < len2; l++) { food = foods[l]; if (food !== 'chocolate') { eat(food); } } // Eat lunch.varcoursesdisheatfoodfoodsijkllenlen1len2menurefeat=functionfoodreturn`${food}eaten.`ref='toast''cheese''wine'forj=0len=reflengthj= 1; num = --i) { results.push(num); } return results; })(); var countdown, num; countdown = (function() { var i, results; results = []; for (num = i = 10; i >= 1; num = --i) { results.push(num); } return results; })(); \t countdown countdown = (num for num in [10..1]) countdown = (num for num in [10..1]) var countdown, num; countdown = (function() { var i, results; results = []; for (num = i = 10; i >= 1; num = --i) { results.push(num); } return results; })(); var countdown, num; countdown = (function() { var i, results; results = []; for (num = i = 10; i >= 1; num = --i) { results.push(num); } return results; })(); countdown = (num for num in [10..1]) countdown = (num for num in [10..1]) countdown = (num for num in [10..1]) countdown = (num for num in [10..1]) countdown=(numfornumin[10..1]) var countdown, num; countdown = (function() { var i, results; results = []; for (num = i = 10; i >= 1; num = --i) { results.push(num); } return results; })(); var countdown, num; countdown = (function() { var i, results; results = []; for (num = i = 10; i >= 1; num = --i) { results.push(num); } return results; })(); var countdown, num; countdown = (function() { var i, results; results = []; for (num = i = 10; i >= 1; num = --i) { results.push(num); } return results; })(); var countdown, num; countdown = (function() { var i, results; results = []; for (num = i = 10; i >= 1; num = --i) { results.push(num); } return results; })(); varcountdownnumcountdown=functionvariresultsresults=fornum=i=10i>=1num=--iresultspushnumreturnresults \t countdown \t countdown \t countdown \t \t Note how because we are assigning the value of the comprehensions to a variable in the example above, CoffeeScript is collecting the result of each iteration into an array. Sometimes functions end with loops that are intended to run only for their side-effects. Be careful that you’re not accidentally returning the results of the comprehension in these cases, by adding a meaningful return value — like true — or null, to the bottom of your function.truenullTo step through a range comprehension in fixed-size chunks, use by, for example: evens = (x for x in [0..10] by 2)byevens = (x for x in [0..10] by 2)If you don’t need the current iteration value you may omit it: browser.closeCurrentTab() for [0...count]browser.closeCurrentTab() for [0...count]Comprehensions can also be used to iterate over the keys and values in an object. Use of to signal comprehension over the properties of an object instead of the values in an array.of yearsOld = max: 10, ida: 9, tim: 11 ages = for child, age of yearsOld \"#{child} is #{age}\" yearsOld = max: 10, ida: 9, tim: 11 ages = for child, age of yearsOld \"#{child} is #{age}\" var age, ages, child, yearsOld; yearsOld = { max: 10, ida: 9, tim: 11 }; ages = (function() { var results; results = []; for (child in yearsOld) { age = yearsOld[child]; results.push(`${child} is ${age}`); } return results; })(); var age, ages, child, yearsOld; yearsOld = { max: 10, ida: 9, tim: 11 }; ages = (function() { var results; results = []; for (child in yearsOld) { age = yearsOld[child]; results.push(`${child} is ${age}`); } return results; })(); \t ages.join(\", \") yearsOld = max: 10, ida: 9, tim: 11 ages = for child, age of yearsOld \"#{child} is #{age}\" yearsOld = max: 10, ida: 9, tim: 11 ages = for child, age of yearsOld \"#{child} is #{age}\" var age, ages, child, yearsOld; yearsOld = { max: 10, ida: 9, tim: 11 }; ages = (function() { var results; results = []; for (child in yearsOld) { age = yearsOld[child]; results.push(`${child} is ${age}`); } return results; })(); var age, ages, child, yearsOld; yearsOld = { max: 10, ida: 9, tim: 11 }; ages = (function() { var results; results = []; for (child in yearsOld) { age = yearsOld[child]; results.push(`${child} is ${age}`); } return results; })(); yearsOld = max: 10, ida: 9, tim: 11 ages = for child, age of yearsOld \"#{child} is #{age}\" yearsOld = max: 10, ida: 9, tim: 11 ages = for child, age of yearsOld \"#{child} is #{age}\" yearsOld = max: 10, ida: 9, tim: 11 ages = for child, age of yearsOld \"#{child} is #{age}\" yearsOld = max: 10, ida: 9, tim: 11 ages = for child, age of yearsOld \"#{child} is #{age}\" yearsOld=max:10,ida:9,tim:11ages=forchild,ageofyearsOld\"#{child} is #{age}\" var age, ages, child, yearsOld; yearsOld = { max: 10, ida: 9, tim: 11 }; ages = (function() { var results; results = []; for (child in yearsOld) { age = yearsOld[child]; results.push(`${child} is ${age}`); } return results; })(); var age, ages, child, yearsOld; yearsOld = { max: 10, ida: 9, tim: 11 }; ages = (function() { var results; results = []; for (child in yearsOld) { age = yearsOld[child]; results.push(`${child} is ${age}`); } return results; })(); var age, ages, child, yearsOld; yearsOld = { max: 10, ida: 9, tim: 11 }; ages = (function() { var results; results = []; for (child in yearsOld) { age = yearsOld[child]; results.push(`${child} is ${age}`); } return results; })(); var age, ages, child, yearsOld; yearsOld = { max: 10, ida: 9, tim: 11 }; ages = (function() { var results; results = []; for (child in yearsOld) { age = yearsOld[child]; results.push(`${child} is ${age}`); } return results; })(); varageageschildyearsOldyearsOld=max10ida9tim11ages=functionvarresultsresults=forchildinyearsOldage=yearsOldchildresultspush`${child}is ${age}`returnresults \t ages.join(\", \") \t ages.join(\", \") \t ages.join(\", \") \t \t If you would like to iterate over just the keys that are defined on the object itself, by adding a hasOwnProperty check to avoid properties that may be inherited from the prototype, use for own key, value of object.hasOwnPropertyfor own key, value of objectTo iterate a generator function, use from. See Generator Functions.fromGenerator FunctionsThe only low-level loop that CoffeeScript provides is the while loop. The main difference from JavaScript is that the while loop can be used as an expression, returning an array containing the result of each iteration through the loop.whilewhile # Econ 101 if this.studyingEconomics buy() while supply > demand sell() until supply > demand # Nursery Rhyme num = 6 lyrics = while num -= 1 \"#{num} little monkeys, jumping on the bed. One fell out and bumped his head.\" # Econ 101 if this.studyingEconomics buy() while supply > demand sell() until supply > demand # Nursery Rhyme num = 6 lyrics = while num -= 1 \"#{num} little monkeys, jumping on the bed. One fell out and bumped his head.\" // Econ 101 var lyrics, num; if (this.studyingEconomics) { while (supply > demand) { buy(); } while (!(supply > demand)) { sell(); } } // Nursery Rhyme num = 6; lyrics = (function() { var results; results = []; while (num -= 1) { results.push(`${num} little monkeys, jumping on the bed. One fell out and bumped his head.`); } return results; })(); // Econ 101 var lyrics, num; if (this.studyingEconomics) { while (supply > demand) { buy(); } while (!(supply > demand)) { sell(); } } // Nursery Rhyme num = 6; lyrics = (function() { var results; results = []; while (num -= 1) { results.push(`${num} little monkeys, jumping on the bed. One fell out and bumped his head.`); } return results; })(); \t lyrics.join(\"\\n\") # Econ 101 if this.studyingEconomics buy() while supply > demand sell() until supply > demand # Nursery Rhyme num = 6 lyrics = while num -= 1 \"#{num} little monkeys, jumping on the bed. One fell out and bumped his head.\" # Econ 101 if this.studyingEconomics buy() while supply > demand sell() until supply > demand # Nursery Rhyme num = 6 lyrics = while num -= 1 \"#{num} little monkeys, jumping on the bed. One fell out and bumped his head.\" // Econ 101 var lyrics, num; if (this.studyingEconomics) { while (supply > demand) { buy(); } while (!(supply > demand)) { sell(); } } // Nursery Rhyme num = 6; lyrics = (function() { var results; results = []; while (num -= 1) { results.push(`${num} little monkeys, jumping on the bed. One fell out and bumped his head.`); } return results; })(); // Econ 101 var lyrics, num; if (this.studyingEconomics) { while (supply > demand) { buy(); } while (!(supply > demand)) { sell(); } } // Nursery Rhyme num = 6; lyrics = (function() { var results; results = []; while (num -= 1) { results.push(`${num} little monkeys, jumping on the bed. One fell out and bumped his head.`); } return results; })(); # Econ 101 if this.studyingEconomics buy() while supply > demand sell() until supply > demand # Nursery Rhyme num = 6 lyrics = while num -= 1 \"#{num} little monkeys, jumping on the bed. One fell out and bumped his head.\" # Econ 101 if this.studyingEconomics buy() while supply > demand sell() until supply > demand # Nursery Rhyme num = 6 lyrics = while num -= 1 \"#{num} little monkeys, jumping on the bed. One fell out and bumped his head.\" # Econ 101 if this.studyingEconomics buy() while supply > demand sell() until supply > demand # Nursery Rhyme num = 6 lyrics = while num -= 1 \"#{num} little monkeys, jumping on the bed. One fell out and bumped his head.\" # Econ 101 if this.studyingEconomics buy() while supply > demand sell() until supply > demand # Nursery Rhyme num = 6 lyrics = while num -= 1 \"#{num} little monkeys, jumping on the bed. One fell out and bumped his head.\" # Econ 101ifthis.studyingEconomicsbuy()whilesupply>demand sell()untilsupply>demand# Nursery Rhymenum=6lyrics=whilenum-=1\"#{num} little monkeys, jumping on the bed. One fell out and bumped his head.\" // Econ 101 var lyrics, num; if (this.studyingEconomics) { while (supply > demand) { buy(); } while (!(supply > demand)) { sell(); } } // Nursery Rhyme num = 6; lyrics = (function() { var results; results = []; while (num -= 1) { results.push(`${num} little monkeys, jumping on the bed. One fell out and bumped his head.`); } return results; })(); // Econ 101 var lyrics, num; if (this.studyingEconomics) { while (supply > demand) { buy(); } while (!(supply > demand)) { sell(); } } // Nursery Rhyme num = 6; lyrics = (function() { var results; results = []; while (num -= 1) { results.push(`${num} little monkeys, jumping on the bed. One fell out and bumped his head.`); } return results; })(); // Econ 101 var lyrics, num; if (this.studyingEconomics) { while (supply > demand) { buy(); } while (!(supply > demand)) { sell(); } } // Nursery Rhyme num = 6; lyrics = (function() { var results; results = []; while (num -= 1) { results.push(`${num} little monkeys, jumping on the bed. One fell out and bumped his head.`); } return results; })(); // Econ 101 var lyrics, num; if (this.studyingEconomics) { while (supply > demand) { buy(); } while (!(supply > demand)) { sell(); } } // Nursery Rhyme num = 6; lyrics = (function() { var results; results = []; while (num -= 1) { results.push(`${num} little monkeys, jumping on the bed. One fell out and bumped his head.`); } return results; })(); // Econ 101varlyricsnumifthisstudyingEconomicswhilesupply>demandbuywhile!supply>demandsell// Nursery Rhymenum=6lyrics=functionvarresultsresults=whilenum-=1resultspush`${num}little monkeys, jumping on the bed. One fell out and bumped his head.`returnresults \t lyrics.join(\"\\n\") \t lyrics.join(\"\\n\") \t lyrics.join(\"\\n\") \t \t For readability, the until keyword is equivalent to while not, and the loop keyword is equivalent to while true.untilwhile notloopwhile trueWhen using a JavaScript loop to generate functions, it’s common to insert a closure wrapper in order to ensure that loop variables are closed over, and all the generated functions don’t just share the final values. CoffeeScript provides the do keyword, which immediately invokes a passed function, forwarding any arguments.do for filename in list do (filename) -> if filename not in ['.DS_Store', 'Thumbs.db', 'ehthumbs.db'] fs.readFile filename, (err, contents) -> compile filename, contents.toString() for filename in list do (filename) -> if filename not in ['.DS_Store', 'Thumbs.db', 'ehthumbs.db'] fs.readFile filename, (err, contents) -> compile filename, contents.toString() var filename, i, len; for (i = 0, len = list.length; i < len; i++) { filename = list[i]; (function(filename) { if (filename !== '.DS_Store' && filename !== 'Thumbs.db' && filename !== 'ehthumbs.db') { return fs.readFile(filename, function(err, contents) { return compile(filename, contents.toString()); }); } })(filename); } var filename, i, len; for (i = 0, len = list.length; i < len; i++) { filename = list[i]; (function(filename) { if (filename !== '.DS_Store' && filename !== 'Thumbs.db' && filename !== 'ehthumbs.db') { return fs.readFile(filename, function(err, contents) { return compile(filename, contents.toString()); }); } })(filename); } for filename in list do (filename) -> if filename not in ['.DS_Store', 'Thumbs.db', 'ehthumbs.db'] fs.readFile filename, (err, contents) -> compile filename, contents.toString() for filename in list do (filename) -> if filename not in ['.DS_Store', 'Thumbs.db', 'ehthumbs.db'] fs.readFile filename, (err, contents) -> compile filename, contents.toString() var filename, i, len; for (i = 0, len = list.length; i < len; i++) { filename = list[i]; (function(filename) { if (filename !== '.DS_Store' && filename !== 'Thumbs.db' && filename !== 'ehthumbs.db') { return fs.readFile(filename, function(err, contents) { return compile(filename, contents.toString()); }); } })(filename); } var filename, i, len; for (i = 0, len = list.length; i < len; i++) { filename = list[i]; (function(filename) { if (filename !== '.DS_Store' && filename !== 'Thumbs.db' && filename !== 'ehthumbs.db') { return fs.readFile(filename, function(err, contents) { return compile(filename, contents.toString()); }); } })(filename); } for filename in list do (filename) -> if filename not in ['.DS_Store', 'Thumbs.db', 'ehthumbs.db'] fs.readFile filename, (err, contents) -> compile filename, contents.toString() for filename in list do (filename) -> if filename not in ['.DS_Store', 'Thumbs.db', 'ehthumbs.db'] fs.readFile filename, (err, contents) -> compile filename, contents.toString() for filename in list do (filename) -> if filename not in ['.DS_Store', 'Thumbs.db', 'ehthumbs.db'] fs.readFile filename, (err, contents) -> compile filename, contents.toString() for filename in list do (filename) -> if filename not in ['.DS_Store', 'Thumbs.db', 'ehthumbs.db'] fs.readFile filename, (err, contents) -> compile filename, contents.toString() forfilenameinlistdo(filename)->iffilenamenotin['.DS_Store','Thumbs.db','ehthumbs.db']fs.readFilefilename,(err,contents)->compilefilename,contents.toString() var filename, i, len; for (i = 0, len = list.length; i < len; i++) { filename = list[i]; (function(filename) { if (filename !== '.DS_Store' && filename !== 'Thumbs.db' && filename !== 'ehthumbs.db') { return fs.readFile(filename, function(err, contents) { return compile(filename, contents.toString()); }); } })(filename); } var filename, i, len; for (i = 0, len = list.length; i < len; i++) { filename = list[i]; (function(filename) { if (filename !== '.DS_Store' && filename !== 'Thumbs.db' && filename !== 'ehthumbs.db') { return fs.readFile(filename, function(err, contents) { return compile(filename, contents.toString()); }); } })(filename); } var filename, i, len; for (i = 0, len = list.length; i < len; i++) { filename = list[i]; (function(filename) { if (filename !== '.DS_Store' && filename !== 'Thumbs.db' && filename !== 'ehthumbs.db') { return fs.readFile(filename, function(err, contents) { return compile(filename, contents.toString()); }); } })(filename); } var filename, i, len; for (i = 0, len = list.length; i < len; i++) { filename = list[i]; (function(filename) { if (filename !== '.DS_Store' && filename !== 'Thumbs.db' && filename !== 'ehthumbs.db') { return fs.readFile(filename, function(err, contents) { return compile(filename, contents.toString()); }); } })(filename); } varfilenameilenfori=0len=listlengthi if student.excellentWork \"A+\" else if student.okayStuff if student.triedHard then \"B\" else \"B-\" else \"C\" eldest = if 24 > 21 then \"Liz\" else \"Ike\" grade = (student) -> if student.excellentWork \"A+\" else if student.okayStuff if student.triedHard then \"B\" else \"B-\" else \"C\" eldest = if 24 > 21 then \"Liz\" else \"Ike\" var eldest, grade; grade = function(student) { if (student.excellentWork) { return \"A+\"; } else if (student.okayStuff) { if (student.triedHard) { return \"B\"; } else { return \"B-\"; } } else { return \"C\"; } }; eldest = 24 > 21 ? \"Liz\" : \"Ike\"; var eldest, grade; grade = function(student) { if (student.excellentWork) { return \"A+\"; } else if (student.okayStuff) { if (student.triedHard) { return \"B\"; } else { return \"B-\"; } } else { return \"C\"; } }; eldest = 24 > 21 ? \"Liz\" : \"Ike\"; \t eldest grade = (student) -> if student.excellentWork \"A+\" else if student.okayStuff if student.triedHard then \"B\" else \"B-\" else \"C\" eldest = if 24 > 21 then \"Liz\" else \"Ike\" grade = (student) -> if student.excellentWork \"A+\" else if student.okayStuff if student.triedHard then \"B\" else \"B-\" else \"C\" eldest = if 24 > 21 then \"Liz\" else \"Ike\" var eldest, grade; grade = function(student) { if (student.excellentWork) { return \"A+\"; } else if (student.okayStuff) { if (student.triedHard) { return \"B\"; } else { return \"B-\"; } } else { return \"C\"; } }; eldest = 24 > 21 ? \"Liz\" : \"Ike\"; var eldest, grade; grade = function(student) { if (student.excellentWork) { return \"A+\"; } else if (student.okayStuff) { if (student.triedHard) { return \"B\"; } else { return \"B-\"; } } else { return \"C\"; } }; eldest = 24 > 21 ? \"Liz\" : \"Ike\"; grade = (student) -> if student.excellentWork \"A+\" else if student.okayStuff if student.triedHard then \"B\" else \"B-\" else \"C\" eldest = if 24 > 21 then \"Liz\" else \"Ike\" grade = (student) -> if student.excellentWork \"A+\" else if student.okayStuff if student.triedHard then \"B\" else \"B-\" else \"C\" eldest = if 24 > 21 then \"Liz\" else \"Ike\" grade = (student) -> if student.excellentWork \"A+\" else if student.okayStuff if student.triedHard then \"B\" else \"B-\" else \"C\" eldest = if 24 > 21 then \"Liz\" else \"Ike\" grade = (student) -> if student.excellentWork \"A+\" else if student.okayStuff if student.triedHard then \"B\" else \"B-\" else \"C\" eldest = if 24 > 21 then \"Liz\" else \"Ike\" grade=(student)->ifstudent.excellentWork\"A+\" elseifstudent.okayStuff ifstudent.triedHardthen\"B\"else\"B-\" else\"C\"eldest=if24>21then\"Liz\"else\"Ike\" var eldest, grade; grade = function(student) { if (student.excellentWork) { return \"A+\"; } else if (student.okayStuff) { if (student.triedHard) { return \"B\"; } else { return \"B-\"; } } else { return \"C\"; } }; eldest = 24 > 21 ? \"Liz\" : \"Ike\"; var eldest, grade; grade = function(student) { if (student.excellentWork) { return \"A+\"; } else if (student.okayStuff) { if (student.triedHard) { return \"B\"; } else { return \"B-\"; } } else { return \"C\"; } }; eldest = 24 > 21 ? \"Liz\" : \"Ike\"; var eldest, grade; grade = function(student) { if (student.excellentWork) { return \"A+\"; } else if (student.okayStuff) { if (student.triedHard) { return \"B\"; } else { return \"B-\"; } } else { return \"C\"; } }; eldest = 24 > 21 ? \"Liz\" : \"Ike\"; var eldest, grade; grade = function(student) { if (student.excellentWork) { return \"A+\"; } else if (student.okayStuff) { if (student.triedHard) { return \"B\"; } else { return \"B-\"; } } else { return \"C\"; } }; eldest = 24 > 21 ? \"Liz\" : \"Ike\"; vareldestgradegrade=functionstudentifstudentexcellentWorkreturn\"A+\"elseifstudentokayStuffifstudenttriedHardreturn\"B\"elsereturn\"B-\"elsereturn\"C\"eldest=24>21?\"Liz\"\"Ike\" \t eldest \t eldest \t eldest \t \t Even though functions will always return their final value, it’s both possible and encouraged to return early from a function body writing out the explicit return (return value), when you know that you’re done.return valueBecause variable declarations occur at the top of scope, assignment can be used within expressions, even for variables that haven’t been seen before: six = (one = 1) + (two = 2) + (three = 3) six = (one = 1) + (two = 2) + (three = 3) var one, six, three, two; six = (one = 1) + (two = 2) + (three = 3); var one, six, three, two; six = (one = 1) + (two = 2) + (three = 3); \t six six = (one = 1) + (two = 2) + (three = 3) six = (one = 1) + (two = 2) + (three = 3) var one, six, three, two; six = (one = 1) + (two = 2) + (three = 3); var one, six, three, two; six = (one = 1) + (two = 2) + (three = 3); six = (one = 1) + (two = 2) + (three = 3) six = (one = 1) + (two = 2) + (three = 3) six = (one = 1) + (two = 2) + (three = 3) six = (one = 1) + (two = 2) + (three = 3) six=(one=1)+(two=2)+(three=3) var one, six, three, two; six = (one = 1) + (two = 2) + (three = 3); var one, six, three, two; six = (one = 1) + (two = 2) + (three = 3); var one, six, three, two; six = (one = 1) + (two = 2) + (three = 3); var one, six, three, two; six = (one = 1) + (two = 2) + (three = 3); varonesixthreetwosix=one=1+two=2+three=3 \t six \t six \t six \t \t Things that would otherwise be statements in JavaScript, when used as part of an expression in CoffeeScript, are converted into expressions by wrapping them in a closure. This lets you do useful things, like assign the result of a comprehension to a variable: # The first ten global properties. globals = (name for name of window)[0...10] # The first ten global properties. globals = (name for name of window)[0...10] // The first ten global properties. var globals, name; globals = ((function() { var results; results = []; for (name in window) { results.push(name); } return results; })()).slice(0, 10); // The first ten global properties. var globals, name; globals = ((function() { var results; results = []; for (name in window) { results.push(name); } return results; })()).slice(0, 10); \t globals # The first ten global properties. globals = (name for name of window)[0...10] # The first ten global properties. globals = (name for name of window)[0...10] // The first ten global properties. var globals, name; globals = ((function() { var results; results = []; for (name in window) { results.push(name); } return results; })()).slice(0, 10); // The first ten global properties. var globals, name; globals = ((function() { var results; results = []; for (name in window) { results.push(name); } return results; })()).slice(0, 10); # The first ten global properties. globals = (name for name of window)[0...10] # The first ten global properties. globals = (name for name of window)[0...10] # The first ten global properties. globals = (name for name of window)[0...10] # The first ten global properties. globals = (name for name of window)[0...10] # The first ten global properties.globals=(namefornameofwindow)[0...10] // The first ten global properties. var globals, name; globals = ((function() { var results; results = []; for (name in window) { results.push(name); } return results; })()).slice(0, 10); // The first ten global properties. var globals, name; globals = ((function() { var results; results = []; for (name in window) { results.push(name); } return results; })()).slice(0, 10); // The first ten global properties. var globals, name; globals = ((function() { var results; results = []; for (name in window) { results.push(name); } return results; })()).slice(0, 10); // The first ten global properties. var globals, name; globals = ((function() { var results; results = []; for (name in window) { results.push(name); } return results; })()).slice(0, 10); // The first ten global properties.varglobalsnameglobals=functionvarresultsresults=fornameinwindowresultspushnamereturnresultsslice010 \t globals \t globals \t globals \t \t As well as silly things, like passing a try/catch statement directly into a function call:trycatch alert( try nonexistent / undefined catch error \"And the error is ... #{error}\" ) alert( try nonexistent / undefined catch error \"And the error is ... #{error}\" ) var error; alert((function() { try { return nonexistent / void 0; } catch (error1) { error = error1; return `And the error is ... ${error}`; } })()); var error; alert((function() { try { return nonexistent / void 0; } catch (error1) { error = error1; return `And the error is ... ${error}`; } })()); \t alert( try nonexistent / undefined catch error \"And the error is ... #{error}\" ) alert( try nonexistent / undefined catch error \"And the error is ... #{error}\" ) var error; alert((function() { try { return nonexistent / void 0; } catch (error1) { error = error1; return `And the error is ... ${error}`; } })()); var error; alert((function() { try { return nonexistent / void 0; } catch (error1) { error = error1; return `And the error is ... ${error}`; } })()); alert( try nonexistent / undefined catch error \"And the error is ... #{error}\" ) alert( try nonexistent / undefined catch error \"And the error is ... #{error}\" ) alert( try nonexistent / undefined catch error \"And the error is ... #{error}\" ) alert( try nonexistent / undefined catch error \"And the error is ... #{error}\" ) alert(try nonexistent/undefined catcherror\"And the error is ... #{error}\") var error; alert((function() { try { return nonexistent / void 0; } catch (error1) { error = error1; return `And the error is ... ${error}`; } })()); var error; alert((function() { try { return nonexistent / void 0; } catch (error1) { error = error1; return `And the error is ... ${error}`; } })()); var error; alert((function() { try { return nonexistent / void 0; } catch (error1) { error = error1; return `And the error is ... ${error}`; } })()); var error; alert((function() { try { return nonexistent / void 0; } catch (error1) { error = error1; return `And the error is ... ${error}`; } })()); varerroralertfunctiontryreturnnonexistent/void0catcherror1error=error1return`And the error is ... ${error}` \t \t \t \t \t There are a handful of statements in JavaScript that can’t be meaningfully converted into expressions, namely break, continue, and return. If you make use of them within a block of code, CoffeeScript won’t try to perform the conversion.breakcontinuereturn","dataLevel":1,"level":2,"parent":"language"},{"section":"operators","title":"Operators and Aliases","content":"Because the == operator frequently causes undesirable coercion, is intransitive, and has a different meaning than in other languages, CoffeeScript compiles == into ===, and != into !==. In addition, is compiles into ===, and isnt into !==.=======!=!==is===isnt!==You can use not as an alias for !.not!For logic, and compiles to &&, and or into ||.and&&or||Instead of a newline or semicolon, then can be used to separate conditions from expressions, in while, if/else, and switch/when statements.thenwhileifelseswitchwhenAs in YAML, on and yes are the same as boolean true, while off and no are boolean false.YAMLonyestrueoffnofalseunless can be used as the inverse of if.unlessifAs a shortcut for this.property, you can use @property.this.property@propertyYou can use in to test for array presence, and of to test for JavaScript object-key presence.inofIn a for loop, from compiles to the ES2015 of. (Yes, it’s unfortunate; the CoffeeScript of predates the ES2015 of.)forfromES2015 ofofofofTo simplify math expressions, ** can be used for exponentiation and // performs floor division. % works just like in JavaScript, while %% provides “dividend dependent modulo”:**//%%%“dividend dependent modulo” -7 % 5 == -2 # The remainder of 7 / 5 -7 %% 5 == 3 # n %% 5 is always between 0 and 4 tabs.selectTabAtIndex((tabs.currentIndex - count) %% tabs.length) -7 % 5 == -2 # The remainder of 7 / 5 -7 %% 5 == 3 # n %% 5 is always between 0 and 4 tabs.selectTabAtIndex((tabs.currentIndex - count) %% tabs.length) var modulo = function(a, b) { return (+a % (b = +b) + b) % b; }; -7 % 5 === -2; // The remainder of 7 / 5 modulo(-7, 5) === 3; // n %% 5 is always between 0 and 4 tabs.selectTabAtIndex(modulo(tabs.currentIndex - count, tabs.length)); var modulo = function(a, b) { return (+a % (b = +b) + b) % b; }; -7 % 5 === -2; // The remainder of 7 / 5 modulo(-7, 5) === 3; // n %% 5 is always between 0 and 4 tabs.selectTabAtIndex(modulo(tabs.currentIndex - count, tabs.length)); -7 % 5 == -2 # The remainder of 7 / 5 -7 %% 5 == 3 # n %% 5 is always between 0 and 4 tabs.selectTabAtIndex((tabs.currentIndex - count) %% tabs.length) -7 % 5 == -2 # The remainder of 7 / 5 -7 %% 5 == 3 # n %% 5 is always between 0 and 4 tabs.selectTabAtIndex((tabs.currentIndex - count) %% tabs.length) var modulo = function(a, b) { return (+a % (b = +b) + b) % b; }; -7 % 5 === -2; // The remainder of 7 / 5 modulo(-7, 5) === 3; // n %% 5 is always between 0 and 4 tabs.selectTabAtIndex(modulo(tabs.currentIndex - count, tabs.length)); var modulo = function(a, b) { return (+a % (b = +b) + b) % b; }; -7 % 5 === -2; // The remainder of 7 / 5 modulo(-7, 5) === 3; // n %% 5 is always between 0 and 4 tabs.selectTabAtIndex(modulo(tabs.currentIndex - count, tabs.length)); -7 % 5 == -2 # The remainder of 7 / 5 -7 %% 5 == 3 # n %% 5 is always between 0 and 4 tabs.selectTabAtIndex((tabs.currentIndex - count) %% tabs.length) -7 % 5 == -2 # The remainder of 7 / 5 -7 %% 5 == 3 # n %% 5 is always between 0 and 4 tabs.selectTabAtIndex((tabs.currentIndex - count) %% tabs.length) -7 % 5 == -2 # The remainder of 7 / 5 -7 %% 5 == 3 # n %% 5 is always between 0 and 4 tabs.selectTabAtIndex((tabs.currentIndex - count) %% tabs.length) -7 % 5 == -2 # The remainder of 7 / 5 -7 %% 5 == 3 # n %% 5 is always between 0 and 4 tabs.selectTabAtIndex((tabs.currentIndex - count) %% tabs.length) -7%5==-2# The remainder of 7 / 5-7%%5==3# n %% 5 is always between 0 and 4tabs.selectTabAtIndex((tabs.currentIndex-count)%%tabs.length) var modulo = function(a, b) { return (+a % (b = +b) + b) % b; }; -7 % 5 === -2; // The remainder of 7 / 5 modulo(-7, 5) === 3; // n %% 5 is always between 0 and 4 tabs.selectTabAtIndex(modulo(tabs.currentIndex - count, tabs.length)); var modulo = function(a, b) { return (+a % (b = +b) + b) % b; }; -7 % 5 === -2; // The remainder of 7 / 5 modulo(-7, 5) === 3; // n %% 5 is always between 0 and 4 tabs.selectTabAtIndex(modulo(tabs.currentIndex - count, tabs.length)); var modulo = function(a, b) { return (+a % (b = +b) + b) % b; }; -7 % 5 === -2; // The remainder of 7 / 5 modulo(-7, 5) === 3; // n %% 5 is always between 0 and 4 tabs.selectTabAtIndex(modulo(tabs.currentIndex - count, tabs.length)); var modulo = function(a, b) { return (+a % (b = +b) + b) % b; }; -7 % 5 === -2; // The remainder of 7 / 5 modulo(-7, 5) === 3; // n %% 5 is always between 0 and 4 tabs.selectTabAtIndex(modulo(tabs.currentIndex - count, tabs.length)); varmodulo=functionabreturn+a%b=+b+b%b-7%5===-2// The remainder of 7 / 5modulo-75===3// n %% 5 is always between 0 and 4tabsselectTabAtIndexmodulotabscurrentIndex-counttabslengthAll together now: CoffeeScript JavaScript is === isnt !== not ! and && or || true, yes, on true false, no, off  false @, this this a in b [].indexOf.call(b, a) >= 0 a of b a in b for a from b for (a of b) a ** b a ** b a // b Math.floor(a / b) a %% b (a % b + b) % b CoffeeScript JavaScript CoffeeScript JavaScript CoffeeScriptJavaScript is === isnt !== not ! and && or || true, yes, on true false, no, off  false @, this this a in b [].indexOf.call(b, a) >= 0 a of b a in b for a from b for (a of b) a ** b a ** b a // b Math.floor(a / b) a %% b (a % b + b) % b is === isis====== isnt !== isntisnt!==!== not ! notnot!! and && andand&&&& or || oror|||| true, yes, on true true, yes, ontrueyesontruetrue false, no, off  false false, no, off falsenoofffalsefalse @, this this @, this@thisthisthis a in b [].indexOf.call(b, a) >= 0 a in ba in b[].indexOf.call(b, a) >= 0[].indexOf.call(b, a) >= 0 a of b a in b a of ba of ba in ba in b for a from b for (a of b) for a from bfor a from bfor (a of b)for (a of b) a ** b a ** b a ** ba ** ba ** ba ** b a // b Math.floor(a / b) a // ba // bMath.floor(a / b)Math.floor(a / b) a %% b (a % b + b) % b a %% ba %% b(a % b + b) % b(a % b + b) % b launch() if ignition is on volume = 10 if band isnt SpinalTap letTheWildRumpusBegin() unless answer is no if car.speed < limit then accelerate() winner = yes if pick in [47, 92, 13] print inspect \"My name is #{@name}\" launch() if ignition is on volume = 10 if band isnt SpinalTap letTheWildRumpusBegin() unless answer is no if car.speed < limit then accelerate() winner = yes if pick in [47, 92, 13] print inspect \"My name is #{@name}\" var volume, winner; if (ignition === true) { launch(); } if (band !== SpinalTap) { volume = 10; } if (answer !== false) { letTheWildRumpusBegin(); } if (car.speed < limit) { accelerate(); } if (pick === 47 || pick === 92 || pick === 13) { winner = true; } print(inspect(`My name is ${this.name}`)); var volume, winner; if (ignition === true) { launch(); } if (band !== SpinalTap) { volume = 10; } if (answer !== false) { letTheWildRumpusBegin(); } if (car.speed < limit) { accelerate(); } if (pick === 47 || pick === 92 || pick === 13) { winner = true; } print(inspect(`My name is ${this.name}`)); launch() if ignition is on volume = 10 if band isnt SpinalTap letTheWildRumpusBegin() unless answer is no if car.speed < limit then accelerate() winner = yes if pick in [47, 92, 13] print inspect \"My name is #{@name}\" launch() if ignition is on volume = 10 if band isnt SpinalTap letTheWildRumpusBegin() unless answer is no if car.speed < limit then accelerate() winner = yes if pick in [47, 92, 13] print inspect \"My name is #{@name}\" var volume, winner; if (ignition === true) { launch(); } if (band !== SpinalTap) { volume = 10; } if (answer !== false) { letTheWildRumpusBegin(); } if (car.speed < limit) { accelerate(); } if (pick === 47 || pick === 92 || pick === 13) { winner = true; } print(inspect(`My name is ${this.name}`)); var volume, winner; if (ignition === true) { launch(); } if (band !== SpinalTap) { volume = 10; } if (answer !== false) { letTheWildRumpusBegin(); } if (car.speed < limit) { accelerate(); } if (pick === 47 || pick === 92 || pick === 13) { winner = true; } print(inspect(`My name is ${this.name}`)); launch() if ignition is on volume = 10 if band isnt SpinalTap letTheWildRumpusBegin() unless answer is no if car.speed < limit then accelerate() winner = yes if pick in [47, 92, 13] print inspect \"My name is #{@name}\" launch() if ignition is on volume = 10 if band isnt SpinalTap letTheWildRumpusBegin() unless answer is no if car.speed < limit then accelerate() winner = yes if pick in [47, 92, 13] print inspect \"My name is #{@name}\" launch() if ignition is on volume = 10 if band isnt SpinalTap letTheWildRumpusBegin() unless answer is no if car.speed < limit then accelerate() winner = yes if pick in [47, 92, 13] print inspect \"My name is #{@name}\" launch() if ignition is on volume = 10 if band isnt SpinalTap letTheWildRumpusBegin() unless answer is no if car.speed < limit then accelerate() winner = yes if pick in [47, 92, 13] print inspect \"My name is #{@name}\" launch()ifignitionisonvolume=10ifbandisntSpinalTapletTheWildRumpusBegin()unlessanswerisnoifcar.speed $ '.box' .fadeIn 'fast' .addClass 'show' .css 'background', 'white' $ 'body' .click (e) -> $ '.box' .fadeIn 'fast' .addClass 'show' .css 'background', 'white' $('body').click(function(e) { return $('.box').fadeIn('fast').addClass('show'); }).css('background', 'white'); $('body').click(function(e) { return $('.box').fadeIn('fast').addClass('show'); }).css('background', 'white'); $ 'body' .click (e) -> $ '.box' .fadeIn 'fast' .addClass 'show' .css 'background', 'white' $ 'body' .click (e) -> $ '.box' .fadeIn 'fast' .addClass 'show' .css 'background', 'white' $('body').click(function(e) { return $('.box').fadeIn('fast').addClass('show'); }).css('background', 'white'); $('body').click(function(e) { return $('.box').fadeIn('fast').addClass('show'); }).css('background', 'white'); $ 'body' .click (e) -> $ '.box' .fadeIn 'fast' .addClass 'show' .css 'background', 'white' $ 'body' .click (e) -> $ '.box' .fadeIn 'fast' .addClass 'show' .css 'background', 'white' $ 'body' .click (e) -> $ '.box' .fadeIn 'fast' .addClass 'show' .css 'background', 'white' $ 'body' .click (e) -> $ '.box' .fadeIn 'fast' .addClass 'show' .css 'background', 'white' $'body'.click(e)->$'.box'.fadeIn'fast'.addClass'show'.css'background','white' $('body').click(function(e) { return $('.box').fadeIn('fast').addClass('show'); }).css('background', 'white'); $('body').click(function(e) { return $('.box').fadeIn('fast').addClass('show'); }).css('background', 'white'); $('body').click(function(e) { return $('.box').fadeIn('fast').addClass('show'); }).css('background', 'white'); $('body').click(function(e) { return $('.box').fadeIn('fast').addClass('show'); }).css('background', 'white'); $'body'clickfunctionereturn$'.box'fadeIn'fast'addClass'show'css'background''white'","dataLevel":1,"level":2,"parent":"language"},{"section":"destructuring","title":"Destructuring Assignment","content":"Just like JavaScript (since ES2015), CoffeeScript has destructuring assignment syntax. When you assign an array or object literal to a value, CoffeeScript breaks up and matches both sides against each other, assigning the values on the right to the variables on the left. In the simplest case, it can be used for parallel assignment: theBait = 1000 theSwitch = 0 [theBait, theSwitch] = [theSwitch, theBait] theBait = 1000 theSwitch = 0 [theBait, theSwitch] = [theSwitch, theBait] var theBait, theSwitch; theBait = 1000; theSwitch = 0; [theBait, theSwitch] = [theSwitch, theBait]; var theBait, theSwitch; theBait = 1000; theSwitch = 0; [theBait, theSwitch] = [theSwitch, theBait]; \t theBait theBait = 1000 theSwitch = 0 [theBait, theSwitch] = [theSwitch, theBait] theBait = 1000 theSwitch = 0 [theBait, theSwitch] = [theSwitch, theBait] var theBait, theSwitch; theBait = 1000; theSwitch = 0; [theBait, theSwitch] = [theSwitch, theBait]; var theBait, theSwitch; theBait = 1000; theSwitch = 0; [theBait, theSwitch] = [theSwitch, theBait]; theBait = 1000 theSwitch = 0 [theBait, theSwitch] = [theSwitch, theBait] theBait = 1000 theSwitch = 0 [theBait, theSwitch] = [theSwitch, theBait] theBait = 1000 theSwitch = 0 [theBait, theSwitch] = [theSwitch, theBait] theBait = 1000 theSwitch = 0 [theBait, theSwitch] = [theSwitch, theBait] theBait=1000theSwitch=0[theBait,theSwitch]=[theSwitch,theBait] var theBait, theSwitch; theBait = 1000; theSwitch = 0; [theBait, theSwitch] = [theSwitch, theBait]; var theBait, theSwitch; theBait = 1000; theSwitch = 0; [theBait, theSwitch] = [theSwitch, theBait]; var theBait, theSwitch; theBait = 1000; theSwitch = 0; [theBait, theSwitch] = [theSwitch, theBait]; var theBait, theSwitch; theBait = 1000; theSwitch = 0; [theBait, theSwitch] = [theSwitch, theBait]; vartheBaittheSwitchtheBait=1000theSwitch=0theBaittheSwitch=theSwitchtheBait \t theBait \t theBait \t theBait \t \t But it’s also helpful for dealing with functions that return multiple values. weatherReport = (location) -> # Make an Ajax request to fetch the weather... [location, 72, \"Mostly Sunny\"] [city, temp, forecast] = weatherReport \"Berkeley, CA\" weatherReport = (location) -> # Make an Ajax request to fetch the weather... [location, 72, \"Mostly Sunny\"] [city, temp, forecast] = weatherReport \"Berkeley, CA\" var city, forecast, temp, weatherReport; weatherReport = function(location) { // Make an Ajax request to fetch the weather... return [location, 72, \"Mostly Sunny\"]; }; [city, temp, forecast] = weatherReport(\"Berkeley, CA\"); var city, forecast, temp, weatherReport; weatherReport = function(location) { // Make an Ajax request to fetch the weather... return [location, 72, \"Mostly Sunny\"]; }; [city, temp, forecast] = weatherReport(\"Berkeley, CA\"); \t forecast weatherReport = (location) -> # Make an Ajax request to fetch the weather... [location, 72, \"Mostly Sunny\"] [city, temp, forecast] = weatherReport \"Berkeley, CA\" weatherReport = (location) -> # Make an Ajax request to fetch the weather... [location, 72, \"Mostly Sunny\"] [city, temp, forecast] = weatherReport \"Berkeley, CA\" var city, forecast, temp, weatherReport; weatherReport = function(location) { // Make an Ajax request to fetch the weather... return [location, 72, \"Mostly Sunny\"]; }; [city, temp, forecast] = weatherReport(\"Berkeley, CA\"); var city, forecast, temp, weatherReport; weatherReport = function(location) { // Make an Ajax request to fetch the weather... return [location, 72, \"Mostly Sunny\"]; }; [city, temp, forecast] = weatherReport(\"Berkeley, CA\"); weatherReport = (location) -> # Make an Ajax request to fetch the weather... [location, 72, \"Mostly Sunny\"] [city, temp, forecast] = weatherReport \"Berkeley, CA\" weatherReport = (location) -> # Make an Ajax request to fetch the weather... [location, 72, \"Mostly Sunny\"] [city, temp, forecast] = weatherReport \"Berkeley, CA\" weatherReport = (location) -> # Make an Ajax request to fetch the weather... [location, 72, \"Mostly Sunny\"] [city, temp, forecast] = weatherReport \"Berkeley, CA\" weatherReport = (location) -> # Make an Ajax request to fetch the weather... [location, 72, \"Mostly Sunny\"] [city, temp, forecast] = weatherReport \"Berkeley, CA\" weatherReport=(location)-># Make an Ajax request to fetch the weather...[location,72,\"Mostly Sunny\"][city,temp,forecast]=weatherReport\"Berkeley, CA\" var city, forecast, temp, weatherReport; weatherReport = function(location) { // Make an Ajax request to fetch the weather... return [location, 72, \"Mostly Sunny\"]; }; [city, temp, forecast] = weatherReport(\"Berkeley, CA\"); var city, forecast, temp, weatherReport; weatherReport = function(location) { // Make an Ajax request to fetch the weather... return [location, 72, \"Mostly Sunny\"]; }; [city, temp, forecast] = weatherReport(\"Berkeley, CA\"); var city, forecast, temp, weatherReport; weatherReport = function(location) { // Make an Ajax request to fetch the weather... return [location, 72, \"Mostly Sunny\"]; }; [city, temp, forecast] = weatherReport(\"Berkeley, CA\"); var city, forecast, temp, weatherReport; weatherReport = function(location) { // Make an Ajax request to fetch the weather... return [location, 72, \"Mostly Sunny\"]; }; [city, temp, forecast] = weatherReport(\"Berkeley, CA\"); varcityforecasttempweatherReportweatherReport=functionlocation// Make an Ajax request to fetch the weather...returnlocation72\"Mostly Sunny\"citytempforecast=weatherReport\"Berkeley, CA\" \t forecast \t forecast \t forecast \t \t Destructuring assignment can be used with any depth of array and object nesting, to help pull out deeply nested properties. futurists = sculptor: \"Umberto Boccioni\" painter: \"Vladimir Burliuk\" poet: name: \"F.T. Marinetti\" address: [ \"Via Roma 42R\" \"Bellagio, Italy 22021\" ] {sculptor} = futurists {poet: {name, address: [street, city]}} = futurists futurists = sculptor: \"Umberto Boccioni\" painter: \"Vladimir Burliuk\" poet: name: \"F.T. Marinetti\" address: [ \"Via Roma 42R\" \"Bellagio, Italy 22021\" ] {sculptor} = futurists {poet: {name, address: [street, city]}} = futurists var city, futurists, name, sculptor, street; futurists = { sculptor: \"Umberto Boccioni\", painter: \"Vladimir Burliuk\", poet: { name: \"F.T. Marinetti\", address: [\"Via Roma 42R\", \"Bellagio, Italy 22021\"] } }; ({sculptor} = futurists); ({ poet: { name, address: [street, city] } } = futurists); var city, futurists, name, sculptor, street; futurists = { sculptor: \"Umberto Boccioni\", painter: \"Vladimir Burliuk\", poet: { name: \"F.T. Marinetti\", address: [\"Via Roma 42R\", \"Bellagio, Italy 22021\"] } }; ({sculptor} = futurists); ({ poet: { name, address: [street, city] } } = futurists); \t name + \"-\" + street futurists = sculptor: \"Umberto Boccioni\" painter: \"Vladimir Burliuk\" poet: name: \"F.T. Marinetti\" address: [ \"Via Roma 42R\" \"Bellagio, Italy 22021\" ] {sculptor} = futurists {poet: {name, address: [street, city]}} = futurists futurists = sculptor: \"Umberto Boccioni\" painter: \"Vladimir Burliuk\" poet: name: \"F.T. Marinetti\" address: [ \"Via Roma 42R\" \"Bellagio, Italy 22021\" ] {sculptor} = futurists {poet: {name, address: [street, city]}} = futurists var city, futurists, name, sculptor, street; futurists = { sculptor: \"Umberto Boccioni\", painter: \"Vladimir Burliuk\", poet: { name: \"F.T. Marinetti\", address: [\"Via Roma 42R\", \"Bellagio, Italy 22021\"] } }; ({sculptor} = futurists); ({ poet: { name, address: [street, city] } } = futurists); var city, futurists, name, sculptor, street; futurists = { sculptor: \"Umberto Boccioni\", painter: \"Vladimir Burliuk\", poet: { name: \"F.T. Marinetti\", address: [\"Via Roma 42R\", \"Bellagio, Italy 22021\"] } }; ({sculptor} = futurists); ({ poet: { name, address: [street, city] } } = futurists); futurists = sculptor: \"Umberto Boccioni\" painter: \"Vladimir Burliuk\" poet: name: \"F.T. Marinetti\" address: [ \"Via Roma 42R\" \"Bellagio, Italy 22021\" ] {sculptor} = futurists {poet: {name, address: [street, city]}} = futurists futurists = sculptor: \"Umberto Boccioni\" painter: \"Vladimir Burliuk\" poet: name: \"F.T. Marinetti\" address: [ \"Via Roma 42R\" \"Bellagio, Italy 22021\" ] {sculptor} = futurists {poet: {name, address: [street, city]}} = futurists futurists = sculptor: \"Umberto Boccioni\" painter: \"Vladimir Burliuk\" poet: name: \"F.T. Marinetti\" address: [ \"Via Roma 42R\" \"Bellagio, Italy 22021\" ] {sculptor} = futurists {poet: {name, address: [street, city]}} = futurists futurists = sculptor: \"Umberto Boccioni\" painter: \"Vladimir Burliuk\" poet: name: \"F.T. Marinetti\" address: [ \"Via Roma 42R\" \"Bellagio, Italy 22021\" ] {sculptor} = futurists {poet: {name, address: [street, city]}} = futurists futurists= sculptor:\"Umberto Boccioni\"painter:\"Vladimir Burliuk\"poet: name:\"F.T. Marinetti\"address:[\"Via Roma 42R\"\"Bellagio, Italy 22021\" ]{sculptor}=futurists{poet:{name,address:[street,city]}}=futurists var city, futurists, name, sculptor, street; futurists = { sculptor: \"Umberto Boccioni\", painter: \"Vladimir Burliuk\", poet: { name: \"F.T. Marinetti\", address: [\"Via Roma 42R\", \"Bellagio, Italy 22021\"] } }; ({sculptor} = futurists); ({ poet: { name, address: [street, city] } } = futurists); var city, futurists, name, sculptor, street; futurists = { sculptor: \"Umberto Boccioni\", painter: \"Vladimir Burliuk\", poet: { name: \"F.T. Marinetti\", address: [\"Via Roma 42R\", \"Bellagio, Italy 22021\"] } }; ({sculptor} = futurists); ({ poet: { name, address: [street, city] } } = futurists); var city, futurists, name, sculptor, street; futurists = { sculptor: \"Umberto Boccioni\", painter: \"Vladimir Burliuk\", poet: { name: \"F.T. Marinetti\", address: [\"Via Roma 42R\", \"Bellagio, Italy 22021\"] } }; ({sculptor} = futurists); ({ poet: { name, address: [street, city] } } = futurists); var city, futurists, name, sculptor, street; futurists = { sculptor: \"Umberto Boccioni\", painter: \"Vladimir Burliuk\", poet: { name: \"F.T. Marinetti\", address: [\"Via Roma 42R\", \"Bellagio, Italy 22021\"] } }; ({sculptor} = futurists); ({ poet: { name, address: [street, city] } } = futurists); varcityfuturistsnamesculptorstreetfuturists=sculptor\"Umberto Boccioni\"painter\"Vladimir Burliuk\"poetname\"F.T. Marinetti\"address\"Via Roma 42R\"\"Bellagio, Italy 22021\"sculptor=futuristspoetnameaddressstreetcity=futurists \t name + \"-\" + street \t name + \"-\" + street \t name + \"-\" + street \t \t Destructuring assignment can even be combined with splats. tag = \"\" [open, contents..., close] = tag.split(\"\") tag = \"\" [open, contents..., close] = tag.split(\"\") var close, contents, open, ref, tag, splice = [].splice; tag = \"\"; ref = tag.split(\"\"), [open, ...contents] = ref, [close] = splice.call(contents, -1); var close, contents, open, ref, tag, splice = [].splice; tag = \"\"; ref = tag.split(\"\"), [open, ...contents] = ref, [close] = splice.call(contents, -1); \t contents.join(\"\") tag = \"\" [open, contents..., close] = tag.split(\"\") tag = \"\" [open, contents..., close] = tag.split(\"\") var close, contents, open, ref, tag, splice = [].splice; tag = \"\"; ref = tag.split(\"\"), [open, ...contents] = ref, [close] = splice.call(contents, -1); var close, contents, open, ref, tag, splice = [].splice; tag = \"\"; ref = tag.split(\"\"), [open, ...contents] = ref, [close] = splice.call(contents, -1); tag = \"\" [open, contents..., close] = tag.split(\"\") tag = \"\" [open, contents..., close] = tag.split(\"\") tag = \"\" [open, contents..., close] = tag.split(\"\") tag = \"\" [open, contents..., close] = tag.split(\"\") tag=\"\"[open,contents...,close]=tag.split(\"\") var close, contents, open, ref, tag, splice = [].splice; tag = \"\"; ref = tag.split(\"\"), [open, ...contents] = ref, [close] = splice.call(contents, -1); var close, contents, open, ref, tag, splice = [].splice; tag = \"\"; ref = tag.split(\"\"), [open, ...contents] = ref, [close] = splice.call(contents, -1); var close, contents, open, ref, tag, splice = [].splice; tag = \"\"; ref = tag.split(\"\"), [open, ...contents] = ref, [close] = splice.call(contents, -1); var close, contents, open, ref, tag, splice = [].splice; tag = \"\"; ref = tag.split(\"\"), [open, ...contents] = ref, [close] = splice.call(contents, -1); varclosecontentsopenreftagsplice=splicetag=\"\"ref=tagsplit\"\"open...contents=refclose=splicecallcontents-1 \t contents.join(\"\") \t contents.join(\"\") \t contents.join(\"\") \t \t Expansion can be used to retrieve elements from the end of an array without having to assign the rest of its values. It works in function parameter lists as well. text = \"Every literary critic believes he will outwit history and have the last word\" [first, ..., last] = text.split \" \" text = \"Every literary critic believes he will outwit history and have the last word\" [first, ..., last] = text.split \" \" var first, last, ref, text, slice = [].slice; text = \"Every literary critic believes he will outwit history and have the last word\"; ref = text.split(\" \"), [first] = ref, [last] = slice.call(ref, -1); var first, last, ref, text, slice = [].slice; text = \"Every literary critic believes he will outwit history and have the last word\"; ref = text.split(\" \"), [first] = ref, [last] = slice.call(ref, -1); \t first + \" \" + last text = \"Every literary critic believes he will outwit history and have the last word\" [first, ..., last] = text.split \" \" text = \"Every literary critic believes he will outwit history and have the last word\" [first, ..., last] = text.split \" \" var first, last, ref, text, slice = [].slice; text = \"Every literary critic believes he will outwit history and have the last word\"; ref = text.split(\" \"), [first] = ref, [last] = slice.call(ref, -1); var first, last, ref, text, slice = [].slice; text = \"Every literary critic believes he will outwit history and have the last word\"; ref = text.split(\" \"), [first] = ref, [last] = slice.call(ref, -1); text = \"Every literary critic believes he will outwit history and have the last word\" [first, ..., last] = text.split \" \" text = \"Every literary critic believes he will outwit history and have the last word\" [first, ..., last] = text.split \" \" text = \"Every literary critic believes he will outwit history and have the last word\" [first, ..., last] = text.split \" \" text = \"Every literary critic believes he will outwit history and have the last word\" [first, ..., last] = text.split \" \" text=\"Every literary critic believes he will outwit history and have the last word\"[first,...,last]=text.split\" \" var first, last, ref, text, slice = [].slice; text = \"Every literary critic believes he will outwit history and have the last word\"; ref = text.split(\" \"), [first] = ref, [last] = slice.call(ref, -1); var first, last, ref, text, slice = [].slice; text = \"Every literary critic believes he will outwit history and have the last word\"; ref = text.split(\" \"), [first] = ref, [last] = slice.call(ref, -1); var first, last, ref, text, slice = [].slice; text = \"Every literary critic believes he will outwit history and have the last word\"; ref = text.split(\" \"), [first] = ref, [last] = slice.call(ref, -1); var first, last, ref, text, slice = [].slice; text = \"Every literary critic believes he will outwit history and have the last word\"; ref = text.split(\" \"), [first] = ref, [last] = slice.call(ref, -1); varfirstlastreftextslice=slicetext=\"Every literary critic believes he will outwit history and have the last word\"ref=textsplit\" \"first=reflast=slicecallref-1 \t first + \" \" + last \t first + \" \" + last \t first + \" \" + last \t \t Destructuring assignment is also useful when combined with class constructors to assign properties to your instance from an options object passed to the constructor. class Person constructor: (options) -> {@name, @age, @height = 'average'} = options tim = new Person name: 'Tim', age: 4 class Person constructor: (options) -> {@name, @age, @height = 'average'} = options tim = new Person name: 'Tim', age: 4 var Person, tim; Person = class Person { constructor(options) { ({name: this.name, age: this.age, height: this.height = 'average'} = options); } }; tim = new Person({ name: 'Tim', age: 4 }); var Person, tim; Person = class Person { constructor(options) { ({name: this.name, age: this.age, height: this.height = 'average'} = options); } }; tim = new Person({ name: 'Tim', age: 4 }); \t tim.age + \" \" + tim.height class Person constructor: (options) -> {@name, @age, @height = 'average'} = options tim = new Person name: 'Tim', age: 4 class Person constructor: (options) -> {@name, @age, @height = 'average'} = options tim = new Person name: 'Tim', age: 4 var Person, tim; Person = class Person { constructor(options) { ({name: this.name, age: this.age, height: this.height = 'average'} = options); } }; tim = new Person({ name: 'Tim', age: 4 }); var Person, tim; Person = class Person { constructor(options) { ({name: this.name, age: this.age, height: this.height = 'average'} = options); } }; tim = new Person({ name: 'Tim', age: 4 }); class Person constructor: (options) -> {@name, @age, @height = 'average'} = options tim = new Person name: 'Tim', age: 4 class Person constructor: (options) -> {@name, @age, @height = 'average'} = options tim = new Person name: 'Tim', age: 4 class Person constructor: (options) -> {@name, @age, @height = 'average'} = options tim = new Person name: 'Tim', age: 4 class Person constructor: (options) -> {@name, @age, @height = 'average'} = options tim = new Person name: 'Tim', age: 4 classPersonconstructor:(options)->{@name,@age,@height='average'}=optionstim=newPersonname:'Tim',age:4 var Person, tim; Person = class Person { constructor(options) { ({name: this.name, age: this.age, height: this.height = 'average'} = options); } }; tim = new Person({ name: 'Tim', age: 4 }); var Person, tim; Person = class Person { constructor(options) { ({name: this.name, age: this.age, height: this.height = 'average'} = options); } }; tim = new Person({ name: 'Tim', age: 4 }); var Person, tim; Person = class Person { constructor(options) { ({name: this.name, age: this.age, height: this.height = 'average'} = options); } }; tim = new Person({ name: 'Tim', age: 4 }); var Person, tim; Person = class Person { constructor(options) { ({name: this.name, age: this.age, height: this.height = 'average'} = options); } }; tim = new Person({ name: 'Tim', age: 4 }); varPersontimPerson=classPersonconstructoroptionsnamethisnameagethisageheightthisheight='average'=optionstim=newPersonname'Tim'age4 \t tim.age + \" \" + tim.height \t tim.age + \" \" + tim.height \t tim.age + \" \" + tim.height \t \t The above example also demonstrates that if properties are missing in the destructured object or array, you can, just like in JavaScript, provide defaults. Note though that unlike with the existential operator, the default is only applied with the value is missing or undefined—passing null will set a value of null, not the default.undefinedpassing null will set a value of nullnullnull","dataLevel":1,"level":2,"parent":"language"},{"section":"fat-arrow","title":"Bound (Fat Arrow) Functions","content":"Bound (Fat Arrow) FunctionsIn JavaScript, the this keyword is dynamically scoped to mean the object that the current function is attached to. If you pass a function as a callback or attach it to a different object, the original value of this will be lost. If you’re not familiar with this behavior, this Digital Web article gives a good overview of the quirks.thisthisthis Digital Web articleThe fat arrow => can be used to both define a function, and to bind it to the current value of this, right on the spot. This is helpful when using callback-based libraries like Prototype or jQuery, for creating iterator functions to pass to each, or event-handler functions to use with on. Functions created with the fat arrow are able to access properties of the this where they’re defined.=>thiseachonthis Account = (customer, cart) -> @customer = customer @cart = cart $('.shopping_cart').on 'click', (event) => @customer.purchase @cart Account = (customer, cart) -> @customer = customer @cart = cart $('.shopping_cart').on 'click', (event) => @customer.purchase @cart var Account; Account = function(customer, cart) { this.customer = customer; this.cart = cart; return $('.shopping_cart').on('click', (event) => { return this.customer.purchase(this.cart); }); }; var Account; Account = function(customer, cart) { this.customer = customer; this.cart = cart; return $('.shopping_cart').on('click', (event) => { return this.customer.purchase(this.cart); }); }; Account = (customer, cart) -> @customer = customer @cart = cart $('.shopping_cart').on 'click', (event) => @customer.purchase @cart Account = (customer, cart) -> @customer = customer @cart = cart $('.shopping_cart').on 'click', (event) => @customer.purchase @cart var Account; Account = function(customer, cart) { this.customer = customer; this.cart = cart; return $('.shopping_cart').on('click', (event) => { return this.customer.purchase(this.cart); }); }; var Account; Account = function(customer, cart) { this.customer = customer; this.cart = cart; return $('.shopping_cart').on('click', (event) => { return this.customer.purchase(this.cart); }); }; Account = (customer, cart) -> @customer = customer @cart = cart $('.shopping_cart').on 'click', (event) => @customer.purchase @cart Account = (customer, cart) -> @customer = customer @cart = cart $('.shopping_cart').on 'click', (event) => @customer.purchase @cart Account = (customer, cart) -> @customer = customer @cart = cart $('.shopping_cart').on 'click', (event) => @customer.purchase @cart Account = (customer, cart) -> @customer = customer @cart = cart $('.shopping_cart').on 'click', (event) => @customer.purchase @cart Account=(customer,cart)->@customer=customer@cart=cart$('.shopping_cart').on'click',(event)=>@customer.purchase@cart var Account; Account = function(customer, cart) { this.customer = customer; this.cart = cart; return $('.shopping_cart').on('click', (event) => { return this.customer.purchase(this.cart); }); }; var Account; Account = function(customer, cart) { this.customer = customer; this.cart = cart; return $('.shopping_cart').on('click', (event) => { return this.customer.purchase(this.cart); }); }; var Account; Account = function(customer, cart) { this.customer = customer; this.cart = cart; return $('.shopping_cart').on('click', (event) => { return this.customer.purchase(this.cart); }); }; var Account; Account = function(customer, cart) { this.customer = customer; this.cart = cart; return $('.shopping_cart').on('click', (event) => { return this.customer.purchase(this.cart); }); }; varAccountAccount=functioncustomercartthiscustomer=customerthiscart=cartreturn$'.shopping_cart'on'click'event=>returnthiscustomerpurchasethiscartIf we had used -> in the callback above, @customer would have referred to the undefined “customer” property of the DOM element, and trying to call purchase() on it would have raised an exception.->@customerpurchase()The fat arrow was one of the most popular features of CoffeeScript, and ES2015 adopted it; so CoffeeScript 2 compiles => to ES =>.adopted it=>=>","dataLevel":1,"level":2,"parent":"language"},{"section":"generators","title":"Generator Functions","content":"CoffeeScript supports ES2015 generator functions through the yield keyword. There’s no function*(){} nonsense — a generator in CoffeeScript is simply a function that yields.generator functionsyieldfunction*(){} perfectSquares = -> num = 0 loop num += 1 yield num * num return window.ps or= perfectSquares() perfectSquares = -> num = 0 loop num += 1 yield num * num return window.ps or= perfectSquares() var perfectSquares; perfectSquares = function*() { var num; num = 0; while (true) { num += 1; yield num * num; } }; window.ps || (window.ps = perfectSquares()); var perfectSquares; perfectSquares = function*() { var num; num = 0; while (true) { num += 1; yield num * num; } }; window.ps || (window.ps = perfectSquares()); \t ps.next().value perfectSquares = -> num = 0 loop num += 1 yield num * num return window.ps or= perfectSquares() perfectSquares = -> num = 0 loop num += 1 yield num * num return window.ps or= perfectSquares() var perfectSquares; perfectSquares = function*() { var num; num = 0; while (true) { num += 1; yield num * num; } }; window.ps || (window.ps = perfectSquares()); var perfectSquares; perfectSquares = function*() { var num; num = 0; while (true) { num += 1; yield num * num; } }; window.ps || (window.ps = perfectSquares()); perfectSquares = -> num = 0 loop num += 1 yield num * num return window.ps or= perfectSquares() perfectSquares = -> num = 0 loop num += 1 yield num * num return window.ps or= perfectSquares() perfectSquares = -> num = 0 loop num += 1 yield num * num return window.ps or= perfectSquares() perfectSquares = -> num = 0 loop num += 1 yield num * num return window.ps or= perfectSquares() perfectSquares=->num=0loopnum+=1yieldnum*num returnwindow.psor=perfectSquares() var perfectSquares; perfectSquares = function*() { var num; num = 0; while (true) { num += 1; yield num * num; } }; window.ps || (window.ps = perfectSquares()); var perfectSquares; perfectSquares = function*() { var num; num = 0; while (true) { num += 1; yield num * num; } }; window.ps || (window.ps = perfectSquares()); var perfectSquares; perfectSquares = function*() { var num; num = 0; while (true) { num += 1; yield num * num; } }; window.ps || (window.ps = perfectSquares()); var perfectSquares; perfectSquares = function*() { var num; num = 0; while (true) { num += 1; yield num * num; } }; window.ps || (window.ps = perfectSquares()); varperfectSquaresperfectSquares=function*varnumnum=0whiletruenum+=1yieldnum*numwindowps||windowps=perfectSquares \t ps.next().value \t ps.next().value \t ps.next().value \t \t yield* is called yield from, and yield return may be used if you need to force a generator that doesn’t yield.yield*yield fromyield returnYou can iterate over a generator function using for…from.for…from fibonacci = -> [previous, current] = [1, 1] loop [previous, current] = [current, previous + current] yield current return getFibonacciNumbers = (length) -> results = [1] for n from fibonacci() results.push n break if results.length is length results fibonacci = -> [previous, current] = [1, 1] loop [previous, current] = [current, previous + current] yield current return getFibonacciNumbers = (length) -> results = [1] for n from fibonacci() results.push n break if results.length is length results var fibonacci, getFibonacciNumbers; fibonacci = function*() { var current, previous; [previous, current] = [1, 1]; while (true) { [previous, current] = [current, previous + current]; yield current; } }; getFibonacciNumbers = function(length) { var n, ref, results; results = [1]; ref = fibonacci(); for (n of ref) { results.push(n); if (results.length === length) { break; } } return results; }; var fibonacci, getFibonacciNumbers; fibonacci = function*() { var current, previous; [previous, current] = [1, 1]; while (true) { [previous, current] = [current, previous + current]; yield current; } }; getFibonacciNumbers = function(length) { var n, ref, results; results = [1]; ref = fibonacci(); for (n of ref) { results.push(n); if (results.length === length) { break; } } return results; }; \t getFibonacciNumbers(10) fibonacci = -> [previous, current] = [1, 1] loop [previous, current] = [current, previous + current] yield current return getFibonacciNumbers = (length) -> results = [1] for n from fibonacci() results.push n break if results.length is length results fibonacci = -> [previous, current] = [1, 1] loop [previous, current] = [current, previous + current] yield current return getFibonacciNumbers = (length) -> results = [1] for n from fibonacci() results.push n break if results.length is length results var fibonacci, getFibonacciNumbers; fibonacci = function*() { var current, previous; [previous, current] = [1, 1]; while (true) { [previous, current] = [current, previous + current]; yield current; } }; getFibonacciNumbers = function(length) { var n, ref, results; results = [1]; ref = fibonacci(); for (n of ref) { results.push(n); if (results.length === length) { break; } } return results; }; var fibonacci, getFibonacciNumbers; fibonacci = function*() { var current, previous; [previous, current] = [1, 1]; while (true) { [previous, current] = [current, previous + current]; yield current; } }; getFibonacciNumbers = function(length) { var n, ref, results; results = [1]; ref = fibonacci(); for (n of ref) { results.push(n); if (results.length === length) { break; } } return results; }; fibonacci = -> [previous, current] = [1, 1] loop [previous, current] = [current, previous + current] yield current return getFibonacciNumbers = (length) -> results = [1] for n from fibonacci() results.push n break if results.length is length results fibonacci = -> [previous, current] = [1, 1] loop [previous, current] = [current, previous + current] yield current return getFibonacciNumbers = (length) -> results = [1] for n from fibonacci() results.push n break if results.length is length results fibonacci = -> [previous, current] = [1, 1] loop [previous, current] = [current, previous + current] yield current return getFibonacciNumbers = (length) -> results = [1] for n from fibonacci() results.push n break if results.length is length results fibonacci = -> [previous, current] = [1, 1] loop [previous, current] = [current, previous + current] yield current return getFibonacciNumbers = (length) -> results = [1] for n from fibonacci() results.push n break if results.length is length results fibonacci=->[previous,current]=[1,1]loop[previous,current]=[current,previous+current]yieldcurrent returngetFibonacciNumbers=(length)->results=[1]fornfromfibonacci()results.pushnbreakifresults.lengthislength results var fibonacci, getFibonacciNumbers; fibonacci = function*() { var current, previous; [previous, current] = [1, 1]; while (true) { [previous, current] = [current, previous + current]; yield current; } }; getFibonacciNumbers = function(length) { var n, ref, results; results = [1]; ref = fibonacci(); for (n of ref) { results.push(n); if (results.length === length) { break; } } return results; }; var fibonacci, getFibonacciNumbers; fibonacci = function*() { var current, previous; [previous, current] = [1, 1]; while (true) { [previous, current] = [current, previous + current]; yield current; } }; getFibonacciNumbers = function(length) { var n, ref, results; results = [1]; ref = fibonacci(); for (n of ref) { results.push(n); if (results.length === length) { break; } } return results; }; var fibonacci, getFibonacciNumbers; fibonacci = function*() { var current, previous; [previous, current] = [1, 1]; while (true) { [previous, current] = [current, previous + current]; yield current; } }; getFibonacciNumbers = function(length) { var n, ref, results; results = [1]; ref = fibonacci(); for (n of ref) { results.push(n); if (results.length === length) { break; } } return results; }; var fibonacci, getFibonacciNumbers; fibonacci = function*() { var current, previous; [previous, current] = [1, 1]; while (true) { [previous, current] = [current, previous + current]; yield current; } }; getFibonacciNumbers = function(length) { var n, ref, results; results = [1]; ref = fibonacci(); for (n of ref) { results.push(n); if (results.length === length) { break; } } return results; }; varfibonaccigetFibonacciNumbersfibonacci=function*varcurrentpreviouspreviouscurrent=11whiletruepreviouscurrent=currentprevious+currentyieldcurrentgetFibonacciNumbers=functionlengthvarnrefresultsresults=1ref=fibonaccifornofrefresultspushnifresultslength===lengthbreakreturnresults \t getFibonacciNumbers(10) \t getFibonacciNumbers(10) \t getFibonacciNumbers(10) \t \t ","dataLevel":1,"level":2,"parent":"language"},{"section":"async-functions","title":"Async Functions","content":"ES2017’s async functions are supported through the await keyword. Like with generators, there’s no need for an async keyword; an async function in CoffeeScript is simply a function that awaits.async functionsawaitasyncSimilar to how yield return forces a generator, await return may be used to force a function to be async.yield returnawait return # Your browser must support async/await and speech synthesis # to run this example. sleep = (ms) -> new Promise (resolve) -> window.setTimeout resolve, ms say = (text) -> window.speechSynthesis.cancel() window.speechSynthesis.speak new SpeechSynthesisUtterance text countdown = (seconds) -> for i in [seconds..1] say i await sleep 1000 # wait one second say \"Blastoff!\" countdown 3 # Your browser must support async/await and speech synthesis # to run this example. sleep = (ms) -> new Promise (resolve) -> window.setTimeout resolve, ms say = (text) -> window.speechSynthesis.cancel() window.speechSynthesis.speak new SpeechSynthesisUtterance text countdown = (seconds) -> for i in [seconds..1] say i await sleep 1000 # wait one second say \"Blastoff!\" countdown 3 // Your browser must support async/await and speech synthesis // to run this example. var countdown, say, sleep; sleep = function(ms) { return new Promise(function(resolve) { return window.setTimeout(resolve, ms); }); }; say = function(text) { window.speechSynthesis.cancel(); return window.speechSynthesis.speak(new SpeechSynthesisUtterance(text)); }; countdown = async function(seconds) { var i, j, ref; for (i = j = ref = seconds; (ref <= 1 ? j <= 1 : j >= 1); i = ref <= 1 ? ++j : --j) { say(i); await sleep(1000); // wait one second } return say(\"Blastoff!\"); }; countdown(3); // Your browser must support async/await and speech synthesis // to run this example. var countdown, say, sleep; sleep = function(ms) { return new Promise(function(resolve) { return window.setTimeout(resolve, ms); }); }; say = function(text) { window.speechSynthesis.cancel(); return window.speechSynthesis.speak(new SpeechSynthesisUtterance(text)); }; countdown = async function(seconds) { var i, j, ref; for (i = j = ref = seconds; (ref <= 1 ? j <= 1 : j >= 1); i = ref <= 1 ? ++j : --j) { say(i); await sleep(1000); // wait one second } return say(\"Blastoff!\"); }; countdown(3); \t # Your browser must support async/await and speech synthesis # to run this example. sleep = (ms) -> new Promise (resolve) -> window.setTimeout resolve, ms say = (text) -> window.speechSynthesis.cancel() window.speechSynthesis.speak new SpeechSynthesisUtterance text countdown = (seconds) -> for i in [seconds..1] say i await sleep 1000 # wait one second say \"Blastoff!\" countdown 3 # Your browser must support async/await and speech synthesis # to run this example. sleep = (ms) -> new Promise (resolve) -> window.setTimeout resolve, ms say = (text) -> window.speechSynthesis.cancel() window.speechSynthesis.speak new SpeechSynthesisUtterance text countdown = (seconds) -> for i in [seconds..1] say i await sleep 1000 # wait one second say \"Blastoff!\" countdown 3 // Your browser must support async/await and speech synthesis // to run this example. var countdown, say, sleep; sleep = function(ms) { return new Promise(function(resolve) { return window.setTimeout(resolve, ms); }); }; say = function(text) { window.speechSynthesis.cancel(); return window.speechSynthesis.speak(new SpeechSynthesisUtterance(text)); }; countdown = async function(seconds) { var i, j, ref; for (i = j = ref = seconds; (ref <= 1 ? j <= 1 : j >= 1); i = ref <= 1 ? ++j : --j) { say(i); await sleep(1000); // wait one second } return say(\"Blastoff!\"); }; countdown(3); // Your browser must support async/await and speech synthesis // to run this example. var countdown, say, sleep; sleep = function(ms) { return new Promise(function(resolve) { return window.setTimeout(resolve, ms); }); }; say = function(text) { window.speechSynthesis.cancel(); return window.speechSynthesis.speak(new SpeechSynthesisUtterance(text)); }; countdown = async function(seconds) { var i, j, ref; for (i = j = ref = seconds; (ref <= 1 ? j <= 1 : j >= 1); i = ref <= 1 ? ++j : --j) { say(i); await sleep(1000); // wait one second } return say(\"Blastoff!\"); }; countdown(3); # Your browser must support async/await and speech synthesis # to run this example. sleep = (ms) -> new Promise (resolve) -> window.setTimeout resolve, ms say = (text) -> window.speechSynthesis.cancel() window.speechSynthesis.speak new SpeechSynthesisUtterance text countdown = (seconds) -> for i in [seconds..1] say i await sleep 1000 # wait one second say \"Blastoff!\" countdown 3 # Your browser must support async/await and speech synthesis # to run this example. sleep = (ms) -> new Promise (resolve) -> window.setTimeout resolve, ms say = (text) -> window.speechSynthesis.cancel() window.speechSynthesis.speak new SpeechSynthesisUtterance text countdown = (seconds) -> for i in [seconds..1] say i await sleep 1000 # wait one second say \"Blastoff!\" countdown 3 # Your browser must support async/await and speech synthesis # to run this example. sleep = (ms) -> new Promise (resolve) -> window.setTimeout resolve, ms say = (text) -> window.speechSynthesis.cancel() window.speechSynthesis.speak new SpeechSynthesisUtterance text countdown = (seconds) -> for i in [seconds..1] say i await sleep 1000 # wait one second say \"Blastoff!\" countdown 3 # Your browser must support async/await and speech synthesis # to run this example. sleep = (ms) -> new Promise (resolve) -> window.setTimeout resolve, ms say = (text) -> window.speechSynthesis.cancel() window.speechSynthesis.speak new SpeechSynthesisUtterance text countdown = (seconds) -> for i in [seconds..1] say i await sleep 1000 # wait one second say \"Blastoff!\" countdown 3 # Your browser must support async/await and speech synthesis# to run this example.sleep=(ms)->newPromise(resolve)->window.setTimeoutresolve,mssay=(text)->window.speechSynthesis.cancel()window.speechSynthesis.speaknewSpeechSynthesisUtterancetextcountdown=(seconds)->foriin[seconds..1]sayiawaitsleep1000# wait one second say\"Blastoff!\"countdown3 // Your browser must support async/await and speech synthesis // to run this example. var countdown, say, sleep; sleep = function(ms) { return new Promise(function(resolve) { return window.setTimeout(resolve, ms); }); }; say = function(text) { window.speechSynthesis.cancel(); return window.speechSynthesis.speak(new SpeechSynthesisUtterance(text)); }; countdown = async function(seconds) { var i, j, ref; for (i = j = ref = seconds; (ref <= 1 ? j <= 1 : j >= 1); i = ref <= 1 ? ++j : --j) { say(i); await sleep(1000); // wait one second } return say(\"Blastoff!\"); }; countdown(3); // Your browser must support async/await and speech synthesis // to run this example. var countdown, say, sleep; sleep = function(ms) { return new Promise(function(resolve) { return window.setTimeout(resolve, ms); }); }; say = function(text) { window.speechSynthesis.cancel(); return window.speechSynthesis.speak(new SpeechSynthesisUtterance(text)); }; countdown = async function(seconds) { var i, j, ref; for (i = j = ref = seconds; (ref <= 1 ? j <= 1 : j >= 1); i = ref <= 1 ? ++j : --j) { say(i); await sleep(1000); // wait one second } return say(\"Blastoff!\"); }; countdown(3); // Your browser must support async/await and speech synthesis // to run this example. var countdown, say, sleep; sleep = function(ms) { return new Promise(function(resolve) { return window.setTimeout(resolve, ms); }); }; say = function(text) { window.speechSynthesis.cancel(); return window.speechSynthesis.speak(new SpeechSynthesisUtterance(text)); }; countdown = async function(seconds) { var i, j, ref; for (i = j = ref = seconds; (ref <= 1 ? j <= 1 : j >= 1); i = ref <= 1 ? ++j : --j) { say(i); await sleep(1000); // wait one second } return say(\"Blastoff!\"); }; countdown(3); // Your browser must support async/await and speech synthesis // to run this example. var countdown, say, sleep; sleep = function(ms) { return new Promise(function(resolve) { return window.setTimeout(resolve, ms); }); }; say = function(text) { window.speechSynthesis.cancel(); return window.speechSynthesis.speak(new SpeechSynthesisUtterance(text)); }; countdown = async function(seconds) { var i, j, ref; for (i = j = ref = seconds; (ref <= 1 ? j <= 1 : j >= 1); i = ref <= 1 ? ++j : --j) { say(i); await sleep(1000); // wait one second } return say(\"Blastoff!\"); }; countdown(3); // Your browser must support async/await and speech synthesis// to run this example.varcountdownsaysleepsleep=functionmsreturnnewPromisefunctionresolvereturnwindowsetTimeoutresolvemssay=functiontextwindowspeechSynthesiscancelreturnwindowspeechSynthesisspeaknewSpeechSynthesisUtterancetextcountdown=asyncfunctionsecondsvarijreffori=j=ref=secondsref<=1?j<=1j>=1i=ref<=1?++j--jsayiawaitsleep1000// wait one secondreturnsay\"Blastoff!\"countdown3 \t \t \t \t \t ","dataLevel":1,"level":2,"parent":"language"},{"section":"classes","title":"Classes","content":"CoffeeScript 1 provided the class and extends keywords as syntactic sugar for working with prototypal functions. With ES2015, JavaScript has adopted those keywords; so CoffeeScript 2 compiles its class and extends keywords to ES2015 classes.classextendsclassextends class Animal constructor: (@name) -> move: (meters) -> alert @name + \" moved #{meters}m.\" class Snake extends Animal move: -> alert \"Slithering...\" super 5 class Horse extends Animal move: -> alert \"Galloping...\" super 45 sam = new Snake \"Sammy the Python\" tom = new Horse \"Tommy the Palomino\" sam.move() tom.move() class Animal constructor: (@name) -> move: (meters) -> alert @name + \" moved #{meters}m.\" class Snake extends Animal move: -> alert \"Slithering...\" super 5 class Horse extends Animal move: -> alert \"Galloping...\" super 45 sam = new Snake \"Sammy the Python\" tom = new Horse \"Tommy the Palomino\" sam.move() tom.move() var Animal, Horse, Snake, sam, tom; Animal = class Animal { constructor(name) { this.name = name; } move(meters) { return alert(this.name + ` moved ${meters}m.`); } }; Snake = class Snake extends Animal { move() { alert(\"Slithering...\"); return super.move(5); } }; Horse = class Horse extends Animal { move() { alert(\"Galloping...\"); return super.move(45); } }; sam = new Snake(\"Sammy the Python\"); tom = new Horse(\"Tommy the Palomino\"); sam.move(); tom.move(); var Animal, Horse, Snake, sam, tom; Animal = class Animal { constructor(name) { this.name = name; } move(meters) { return alert(this.name + ` moved ${meters}m.`); } }; Snake = class Snake extends Animal { move() { alert(\"Slithering...\"); return super.move(5); } }; Horse = class Horse extends Animal { move() { alert(\"Galloping...\"); return super.move(45); } }; sam = new Snake(\"Sammy the Python\"); tom = new Horse(\"Tommy the Palomino\"); sam.move(); tom.move(); \t class Animal constructor: (@name) -> move: (meters) -> alert @name + \" moved #{meters}m.\" class Snake extends Animal move: -> alert \"Slithering...\" super 5 class Horse extends Animal move: -> alert \"Galloping...\" super 45 sam = new Snake \"Sammy the Python\" tom = new Horse \"Tommy the Palomino\" sam.move() tom.move() class Animal constructor: (@name) -> move: (meters) -> alert @name + \" moved #{meters}m.\" class Snake extends Animal move: -> alert \"Slithering...\" super 5 class Horse extends Animal move: -> alert \"Galloping...\" super 45 sam = new Snake \"Sammy the Python\" tom = new Horse \"Tommy the Palomino\" sam.move() tom.move() var Animal, Horse, Snake, sam, tom; Animal = class Animal { constructor(name) { this.name = name; } move(meters) { return alert(this.name + ` moved ${meters}m.`); } }; Snake = class Snake extends Animal { move() { alert(\"Slithering...\"); return super.move(5); } }; Horse = class Horse extends Animal { move() { alert(\"Galloping...\"); return super.move(45); } }; sam = new Snake(\"Sammy the Python\"); tom = new Horse(\"Tommy the Palomino\"); sam.move(); tom.move(); var Animal, Horse, Snake, sam, tom; Animal = class Animal { constructor(name) { this.name = name; } move(meters) { return alert(this.name + ` moved ${meters}m.`); } }; Snake = class Snake extends Animal { move() { alert(\"Slithering...\"); return super.move(5); } }; Horse = class Horse extends Animal { move() { alert(\"Galloping...\"); return super.move(45); } }; sam = new Snake(\"Sammy the Python\"); tom = new Horse(\"Tommy the Palomino\"); sam.move(); tom.move(); class Animal constructor: (@name) -> move: (meters) -> alert @name + \" moved #{meters}m.\" class Snake extends Animal move: -> alert \"Slithering...\" super 5 class Horse extends Animal move: -> alert \"Galloping...\" super 45 sam = new Snake \"Sammy the Python\" tom = new Horse \"Tommy the Palomino\" sam.move() tom.move() class Animal constructor: (@name) -> move: (meters) -> alert @name + \" moved #{meters}m.\" class Snake extends Animal move: -> alert \"Slithering...\" super 5 class Horse extends Animal move: -> alert \"Galloping...\" super 45 sam = new Snake \"Sammy the Python\" tom = new Horse \"Tommy the Palomino\" sam.move() tom.move() class Animal constructor: (@name) -> move: (meters) -> alert @name + \" moved #{meters}m.\" class Snake extends Animal move: -> alert \"Slithering...\" super 5 class Horse extends Animal move: -> alert \"Galloping...\" super 45 sam = new Snake \"Sammy the Python\" tom = new Horse \"Tommy the Palomino\" sam.move() tom.move() class Animal constructor: (@name) -> move: (meters) -> alert @name + \" moved #{meters}m.\" class Snake extends Animal move: -> alert \"Slithering...\" super 5 class Horse extends Animal move: -> alert \"Galloping...\" super 45 sam = new Snake \"Sammy the Python\" tom = new Horse \"Tommy the Palomino\" sam.move() tom.move() classAnimalconstructor:(@name)-> move:(meters)->alert@name+\" moved #{meters}m.\"classSnakeextendsAnimalmove:->alert\"Slithering...\"super5classHorseextendsAnimalmove:->alert\"Galloping...\"super45sam=newSnake\"Sammy the Python\"tom=newHorse\"Tommy the Palomino\"sam.move()tom.move() var Animal, Horse, Snake, sam, tom; Animal = class Animal { constructor(name) { this.name = name; } move(meters) { return alert(this.name + ` moved ${meters}m.`); } }; Snake = class Snake extends Animal { move() { alert(\"Slithering...\"); return super.move(5); } }; Horse = class Horse extends Animal { move() { alert(\"Galloping...\"); return super.move(45); } }; sam = new Snake(\"Sammy the Python\"); tom = new Horse(\"Tommy the Palomino\"); sam.move(); tom.move(); var Animal, Horse, Snake, sam, tom; Animal = class Animal { constructor(name) { this.name = name; } move(meters) { return alert(this.name + ` moved ${meters}m.`); } }; Snake = class Snake extends Animal { move() { alert(\"Slithering...\"); return super.move(5); } }; Horse = class Horse extends Animal { move() { alert(\"Galloping...\"); return super.move(45); } }; sam = new Snake(\"Sammy the Python\"); tom = new Horse(\"Tommy the Palomino\"); sam.move(); tom.move(); var Animal, Horse, Snake, sam, tom; Animal = class Animal { constructor(name) { this.name = name; } move(meters) { return alert(this.name + ` moved ${meters}m.`); } }; Snake = class Snake extends Animal { move() { alert(\"Slithering...\"); return super.move(5); } }; Horse = class Horse extends Animal { move() { alert(\"Galloping...\"); return super.move(45); } }; sam = new Snake(\"Sammy the Python\"); tom = new Horse(\"Tommy the Palomino\"); sam.move(); tom.move(); var Animal, Horse, Snake, sam, tom; Animal = class Animal { constructor(name) { this.name = name; } move(meters) { return alert(this.name + ` moved ${meters}m.`); } }; Snake = class Snake extends Animal { move() { alert(\"Slithering...\"); return super.move(5); } }; Horse = class Horse extends Animal { move() { alert(\"Galloping...\"); return super.move(45); } }; sam = new Snake(\"Sammy the Python\"); tom = new Horse(\"Tommy the Palomino\"); sam.move(); tom.move(); varAnimalHorseSnakesamtomAnimal=classAnimalconstructornamethisname=namemovemetersreturnalertthisname+` moved ${meters}m.`Snake=classSnakeextendsAnimalmovealert\"Slithering...\"returnsupermove5Horse=classHorseextendsAnimalmovealert\"Galloping...\"returnsupermove45sam=newSnake\"Sammy the Python\"tom=newHorse\"Tommy the Palomino\"sammovetommove \t \t \t \t \t Static methods can be defined using @ before the method name:@ class Teenager @say: (speech) -> words = speech.split ' ' fillers = ['uh', 'um', 'like', 'actually', 'so', 'maybe'] output = [] for word, index in words output.push word output.push fillers[Math.floor(Math.random() * fillers.length)] unless index is words.length - 1 output.join ', ' class Teenager @say: (speech) -> words = speech.split ' ' fillers = ['uh', 'um', 'like', 'actually', 'so', 'maybe'] output = [] for word, index in words output.push word output.push fillers[Math.floor(Math.random() * fillers.length)] unless index is words.length - 1 output.join ', ' var Teenager; Teenager = class Teenager { static say(speech) { var fillers, i, index, len, output, word, words; words = speech.split(' '); fillers = ['uh', 'um', 'like', 'actually', 'so', 'maybe']; output = []; for (index = i = 0, len = words.length; i < len; index = ++i) { word = words[index]; output.push(word); if (index !== words.length - 1) { output.push(fillers[Math.floor(Math.random() * fillers.length)]); } } return output.join(', '); } }; var Teenager; Teenager = class Teenager { static say(speech) { var fillers, i, index, len, output, word, words; words = speech.split(' '); fillers = ['uh', 'um', 'like', 'actually', 'so', 'maybe']; output = []; for (index = i = 0, len = words.length; i < len; index = ++i) { word = words[index]; output.push(word); if (index !== words.length - 1) { output.push(fillers[Math.floor(Math.random() * fillers.length)]); } } return output.join(', '); } }; \t Teenager.say(\"Are we there yet?\") class Teenager @say: (speech) -> words = speech.split ' ' fillers = ['uh', 'um', 'like', 'actually', 'so', 'maybe'] output = [] for word, index in words output.push word output.push fillers[Math.floor(Math.random() * fillers.length)] unless index is words.length - 1 output.join ', ' class Teenager @say: (speech) -> words = speech.split ' ' fillers = ['uh', 'um', 'like', 'actually', 'so', 'maybe'] output = [] for word, index in words output.push word output.push fillers[Math.floor(Math.random() * fillers.length)] unless index is words.length - 1 output.join ', ' var Teenager; Teenager = class Teenager { static say(speech) { var fillers, i, index, len, output, word, words; words = speech.split(' '); fillers = ['uh', 'um', 'like', 'actually', 'so', 'maybe']; output = []; for (index = i = 0, len = words.length; i < len; index = ++i) { word = words[index]; output.push(word); if (index !== words.length - 1) { output.push(fillers[Math.floor(Math.random() * fillers.length)]); } } return output.join(', '); } }; var Teenager; Teenager = class Teenager { static say(speech) { var fillers, i, index, len, output, word, words; words = speech.split(' '); fillers = ['uh', 'um', 'like', 'actually', 'so', 'maybe']; output = []; for (index = i = 0, len = words.length; i < len; index = ++i) { word = words[index]; output.push(word); if (index !== words.length - 1) { output.push(fillers[Math.floor(Math.random() * fillers.length)]); } } return output.join(', '); } }; class Teenager @say: (speech) -> words = speech.split ' ' fillers = ['uh', 'um', 'like', 'actually', 'so', 'maybe'] output = [] for word, index in words output.push word output.push fillers[Math.floor(Math.random() * fillers.length)] unless index is words.length - 1 output.join ', ' class Teenager @say: (speech) -> words = speech.split ' ' fillers = ['uh', 'um', 'like', 'actually', 'so', 'maybe'] output = [] for word, index in words output.push word output.push fillers[Math.floor(Math.random() * fillers.length)] unless index is words.length - 1 output.join ', ' class Teenager @say: (speech) -> words = speech.split ' ' fillers = ['uh', 'um', 'like', 'actually', 'so', 'maybe'] output = [] for word, index in words output.push word output.push fillers[Math.floor(Math.random() * fillers.length)] unless index is words.length - 1 output.join ', ' class Teenager @say: (speech) -> words = speech.split ' ' fillers = ['uh', 'um', 'like', 'actually', 'so', 'maybe'] output = [] for word, index in words output.push word output.push fillers[Math.floor(Math.random() * fillers.length)] unless index is words.length - 1 output.join ', ' classTeenager@say:(speech)->words=speech.split' 'fillers=['uh','um','like','actually','so','maybe']output=[]forword,indexinwordsoutput.pushwordoutput.pushfillers[Math.floor(Math.random()*fillers.length)]unlessindexiswords.length-1 output.join', ' var Teenager; Teenager = class Teenager { static say(speech) { var fillers, i, index, len, output, word, words; words = speech.split(' '); fillers = ['uh', 'um', 'like', 'actually', 'so', 'maybe']; output = []; for (index = i = 0, len = words.length; i < len; index = ++i) { word = words[index]; output.push(word); if (index !== words.length - 1) { output.push(fillers[Math.floor(Math.random() * fillers.length)]); } } return output.join(', '); } }; var Teenager; Teenager = class Teenager { static say(speech) { var fillers, i, index, len, output, word, words; words = speech.split(' '); fillers = ['uh', 'um', 'like', 'actually', 'so', 'maybe']; output = []; for (index = i = 0, len = words.length; i < len; index = ++i) { word = words[index]; output.push(word); if (index !== words.length - 1) { output.push(fillers[Math.floor(Math.random() * fillers.length)]); } } return output.join(', '); } }; var Teenager; Teenager = class Teenager { static say(speech) { var fillers, i, index, len, output, word, words; words = speech.split(' '); fillers = ['uh', 'um', 'like', 'actually', 'so', 'maybe']; output = []; for (index = i = 0, len = words.length; i < len; index = ++i) { word = words[index]; output.push(word); if (index !== words.length - 1) { output.push(fillers[Math.floor(Math.random() * fillers.length)]); } } return output.join(', '); } }; var Teenager; Teenager = class Teenager { static say(speech) { var fillers, i, index, len, output, word, words; words = speech.split(' '); fillers = ['uh', 'um', 'like', 'actually', 'so', 'maybe']; output = []; for (index = i = 0, len = words.length; i < len; index = ++i) { word = words[index]; output.push(word); if (index !== words.length - 1) { output.push(fillers[Math.floor(Math.random() * fillers.length)]); } } return output.join(', '); } }; varTeenagerTeenager=classTeenagerstaticsayspeechvarfillersiindexlenoutputwordwordswords=speechsplit' 'fillers='uh''um''like''actually''so''maybe'output=forindex=i=0len=wordslengthi this.replace /_/g, \"-\" String::dasherize = -> this.replace /_/g, \"-\" String.prototype.dasherize = function() { return this.replace(/_/g, \"-\"); }; String.prototype.dasherize = function() { return this.replace(/_/g, \"-\"); }; \t \"one_two\".dasherize() String::dasherize = -> this.replace /_/g, \"-\" String::dasherize = -> this.replace /_/g, \"-\" String.prototype.dasherize = function() { return this.replace(/_/g, \"-\"); }; String.prototype.dasherize = function() { return this.replace(/_/g, \"-\"); }; String::dasherize = -> this.replace /_/g, \"-\" String::dasherize = -> this.replace /_/g, \"-\" String::dasherize = -> this.replace /_/g, \"-\" String::dasherize = -> this.replace /_/g, \"-\" String::dasherize=->this.replace/_/g,\"-\" String.prototype.dasherize = function() { return this.replace(/_/g, \"-\"); }; String.prototype.dasherize = function() { return this.replace(/_/g, \"-\"); }; String.prototype.dasherize = function() { return this.replace(/_/g, \"-\"); }; String.prototype.dasherize = function() { return this.replace(/_/g, \"-\"); }; Stringprototypedasherize=functionreturnthisreplace/_/g\"-\" \t \"one_two\".dasherize() \t \"one_two\".dasherize() \t \"one_two\".dasherize() \t \t ","dataLevel":1,"level":2,"parent":"language"},{"section":"switch","title":"Switch/When/Else","content":"switch statements in JavaScript are a bit awkward. You need to remember to break at the end of every case statement to avoid accidentally falling through to the default case. CoffeeScript prevents accidental fall-through, and can convert the switch into a returnable, assignable expression. The format is: switch condition, when clauses, else the default case.switchbreakcaseswitchswitchwhenelseAs in Ruby, switch statements in CoffeeScript can take multiple values for each when clause. If any of the values match, the clause runs.switchwhen switch day when \"Mon\" then go work when \"Tue\" then go relax when \"Thu\" then go iceFishing when \"Fri\", \"Sat\" if day is bingoDay go bingo go dancing when \"Sun\" then go church else go work switch day when \"Mon\" then go work when \"Tue\" then go relax when \"Thu\" then go iceFishing when \"Fri\", \"Sat\" if day is bingoDay go bingo go dancing when \"Sun\" then go church else go work switch (day) { case \"Mon\": go(work); break; case \"Tue\": go(relax); break; case \"Thu\": go(iceFishing); break; case \"Fri\": case \"Sat\": if (day === bingoDay) { go(bingo); go(dancing); } break; case \"Sun\": go(church); break; default: go(work); } switch (day) { case \"Mon\": go(work); break; case \"Tue\": go(relax); break; case \"Thu\": go(iceFishing); break; case \"Fri\": case \"Sat\": if (day === bingoDay) { go(bingo); go(dancing); } break; case \"Sun\": go(church); break; default: go(work); } switch day when \"Mon\" then go work when \"Tue\" then go relax when \"Thu\" then go iceFishing when \"Fri\", \"Sat\" if day is bingoDay go bingo go dancing when \"Sun\" then go church else go work switch day when \"Mon\" then go work when \"Tue\" then go relax when \"Thu\" then go iceFishing when \"Fri\", \"Sat\" if day is bingoDay go bingo go dancing when \"Sun\" then go church else go work switch (day) { case \"Mon\": go(work); break; case \"Tue\": go(relax); break; case \"Thu\": go(iceFishing); break; case \"Fri\": case \"Sat\": if (day === bingoDay) { go(bingo); go(dancing); } break; case \"Sun\": go(church); break; default: go(work); } switch (day) { case \"Mon\": go(work); break; case \"Tue\": go(relax); break; case \"Thu\": go(iceFishing); break; case \"Fri\": case \"Sat\": if (day === bingoDay) { go(bingo); go(dancing); } break; case \"Sun\": go(church); break; default: go(work); } switch day when \"Mon\" then go work when \"Tue\" then go relax when \"Thu\" then go iceFishing when \"Fri\", \"Sat\" if day is bingoDay go bingo go dancing when \"Sun\" then go church else go work switch day when \"Mon\" then go work when \"Tue\" then go relax when \"Thu\" then go iceFishing when \"Fri\", \"Sat\" if day is bingoDay go bingo go dancing when \"Sun\" then go church else go work switch day when \"Mon\" then go work when \"Tue\" then go relax when \"Thu\" then go iceFishing when \"Fri\", \"Sat\" if day is bingoDay go bingo go dancing when \"Sun\" then go church else go work switch day when \"Mon\" then go work when \"Tue\" then go relax when \"Thu\" then go iceFishing when \"Fri\", \"Sat\" if day is bingoDay go bingo go dancing when \"Sun\" then go church else go work switchdaywhen\"Mon\"thengoworkwhen\"Tue\"thengorelaxwhen\"Thu\"thengoiceFishingwhen\"Fri\",\"Sat\" ifdayisbingoDaygobingogodancing when\"Sun\"thengochurchelsegowork switch (day) { case \"Mon\": go(work); break; case \"Tue\": go(relax); break; case \"Thu\": go(iceFishing); break; case \"Fri\": case \"Sat\": if (day === bingoDay) { go(bingo); go(dancing); } break; case \"Sun\": go(church); break; default: go(work); } switch (day) { case \"Mon\": go(work); break; case \"Tue\": go(relax); break; case \"Thu\": go(iceFishing); break; case \"Fri\": case \"Sat\": if (day === bingoDay) { go(bingo); go(dancing); } break; case \"Sun\": go(church); break; default: go(work); } switch (day) { case \"Mon\": go(work); break; case \"Tue\": go(relax); break; case \"Thu\": go(iceFishing); break; case \"Fri\": case \"Sat\": if (day === bingoDay) { go(bingo); go(dancing); } break; case \"Sun\": go(church); break; default: go(work); } switch (day) { case \"Mon\": go(work); break; case \"Tue\": go(relax); break; case \"Thu\": go(iceFishing); break; case \"Fri\": case \"Sat\": if (day === bingoDay) { go(bingo); go(dancing); } break; case \"Sun\": go(church); break; default: go(work); } switchdaycase\"Mon\"goworkbreakcase\"Tue\"gorelaxbreakcase\"Thu\"goiceFishingbreakcase\"Fri\"case\"Sat\"ifday===bingoDaygobingogodancingbreakcase\"Sun\"gochurchbreakdefaultgoworkswitch statements can also be used without a control expression, turning them in to a cleaner alternative to if/else chains.switchifelse score = 76 grade = switch when score < 60 then 'F' when score < 70 then 'D' when score < 80 then 'C' when score < 90 then 'B' else 'A' # grade == 'C' score = 76 grade = switch when score < 60 then 'F' when score < 70 then 'D' when score < 80 then 'C' when score < 90 then 'B' else 'A' # grade == 'C' var grade, score; score = 76; grade = (function() { switch (false) { case !(score < 60): return 'F'; case !(score < 70): return 'D'; case !(score < 80): return 'C'; case !(score < 90): return 'B'; default: return 'A'; } })(); // grade == 'C' var grade, score; score = 76; grade = (function() { switch (false) { case !(score < 60): return 'F'; case !(score < 70): return 'D'; case !(score < 80): return 'C'; case !(score < 90): return 'B'; default: return 'A'; } })(); // grade == 'C' score = 76 grade = switch when score < 60 then 'F' when score < 70 then 'D' when score < 80 then 'C' when score < 90 then 'B' else 'A' # grade == 'C' score = 76 grade = switch when score < 60 then 'F' when score < 70 then 'D' when score < 80 then 'C' when score < 90 then 'B' else 'A' # grade == 'C' var grade, score; score = 76; grade = (function() { switch (false) { case !(score < 60): return 'F'; case !(score < 70): return 'D'; case !(score < 80): return 'C'; case !(score < 90): return 'B'; default: return 'A'; } })(); // grade == 'C' var grade, score; score = 76; grade = (function() { switch (false) { case !(score < 60): return 'F'; case !(score < 70): return 'D'; case !(score < 80): return 'C'; case !(score < 90): return 'B'; default: return 'A'; } })(); // grade == 'C' score = 76 grade = switch when score < 60 then 'F' when score < 70 then 'D' when score < 80 then 'C' when score < 90 then 'B' else 'A' # grade == 'C' score = 76 grade = switch when score < 60 then 'F' when score < 70 then 'D' when score < 80 then 'C' when score < 90 then 'B' else 'A' # grade == 'C' score = 76 grade = switch when score < 60 then 'F' when score < 70 then 'D' when score < 80 then 'C' when score < 90 then 'B' else 'A' # grade == 'C' score = 76 grade = switch when score < 60 then 'F' when score < 70 then 'D' when score < 80 then 'C' when score < 90 then 'B' else 'A' # grade == 'C' score=76grade=switchwhenscore<60then'F'whenscore<70then'D'whenscore<80then'C'whenscore<90then'B'else'A'# grade == 'C' var grade, score; score = 76; grade = (function() { switch (false) { case !(score < 60): return 'F'; case !(score < 70): return 'D'; case !(score < 80): return 'C'; case !(score < 90): return 'B'; default: return 'A'; } })(); // grade == 'C' var grade, score; score = 76; grade = (function() { switch (false) { case !(score < 60): return 'F'; case !(score < 70): return 'D'; case !(score < 80): return 'C'; case !(score < 90): return 'B'; default: return 'A'; } })(); // grade == 'C' var grade, score; score = 76; grade = (function() { switch (false) { case !(score < 60): return 'F'; case !(score < 70): return 'D'; case !(score < 80): return 'C'; case !(score < 90): return 'B'; default: return 'A'; } })(); // grade == 'C' var grade, score; score = 76; grade = (function() { switch (false) { case !(score < 60): return 'F'; case !(score < 70): return 'D'; case !(score < 80): return 'C'; case !(score < 90): return 'B'; default: return 'A'; } })(); // grade == 'C' vargradescorescore=76grade=functionswitchfalsecase!score<60return'F'case!score<70return'D'case!score<80return'C'case!score<90return'B'defaultreturn'A'// grade == 'C'","dataLevel":1,"level":2,"parent":"language"},{"section":"try","title":"Try/Catch/Finally","content":"try expressions have the same semantics as try statements in JavaScript, though in CoffeeScript, you may omit both the catch and finally parts. The catch part may also omit the error parameter if it is not needed.trytryboth try allHellBreaksLoose() catsAndDogsLivingTogether() catch error print error finally cleanUp() try allHellBreaksLoose() catsAndDogsLivingTogether() catch error print error finally cleanUp() var error; try { allHellBreaksLoose(); catsAndDogsLivingTogether(); } catch (error1) { error = error1; print(error); } finally { cleanUp(); } var error; try { allHellBreaksLoose(); catsAndDogsLivingTogether(); } catch (error1) { error = error1; print(error); } finally { cleanUp(); } try allHellBreaksLoose() catsAndDogsLivingTogether() catch error print error finally cleanUp() try allHellBreaksLoose() catsAndDogsLivingTogether() catch error print error finally cleanUp() var error; try { allHellBreaksLoose(); catsAndDogsLivingTogether(); } catch (error1) { error = error1; print(error); } finally { cleanUp(); } var error; try { allHellBreaksLoose(); catsAndDogsLivingTogether(); } catch (error1) { error = error1; print(error); } finally { cleanUp(); } try allHellBreaksLoose() catsAndDogsLivingTogether() catch error print error finally cleanUp() try allHellBreaksLoose() catsAndDogsLivingTogether() catch error print error finally cleanUp() try allHellBreaksLoose() catsAndDogsLivingTogether() catch error print error finally cleanUp() try allHellBreaksLoose() catsAndDogsLivingTogether() catch error print error finally cleanUp() tryallHellBreaksLoose()catsAndDogsLivingTogether()catcherrorprinterrorfinallycleanUp() var error; try { allHellBreaksLoose(); catsAndDogsLivingTogether(); } catch (error1) { error = error1; print(error); } finally { cleanUp(); } var error; try { allHellBreaksLoose(); catsAndDogsLivingTogether(); } catch (error1) { error = error1; print(error); } finally { cleanUp(); } var error; try { allHellBreaksLoose(); catsAndDogsLivingTogether(); } catch (error1) { error = error1; print(error); } finally { cleanUp(); } var error; try { allHellBreaksLoose(); catsAndDogsLivingTogether(); } catch (error1) { error = error1; print(error); } finally { cleanUp(); } varerrortryallHellBreaksLoosecatsAndDogsLivingTogethercatcherror1error=error1printerrorfinallycleanUp","dataLevel":1,"level":2,"parent":"language"},{"section":"comparisons","title":"Chained Comparisons","content":"CoffeeScript borrows chained comparisons from Python — making it easy to test if a value falls within a certain range.chained comparisons cholesterol = 127 healthy = 200 > cholesterol > 60 cholesterol = 127 healthy = 200 > cholesterol > 60 var cholesterol, healthy; cholesterol = 127; healthy = (200 > cholesterol && cholesterol > 60); var cholesterol, healthy; cholesterol = 127; healthy = (200 > cholesterol && cholesterol > 60); \t healthy cholesterol = 127 healthy = 200 > cholesterol > 60 cholesterol = 127 healthy = 200 > cholesterol > 60 var cholesterol, healthy; cholesterol = 127; healthy = (200 > cholesterol && cholesterol > 60); var cholesterol, healthy; cholesterol = 127; healthy = (200 > cholesterol && cholesterol > 60); cholesterol = 127 healthy = 200 > cholesterol > 60 cholesterol = 127 healthy = 200 > cholesterol > 60 cholesterol = 127 healthy = 200 > cholesterol > 60 cholesterol = 127 healthy = 200 > cholesterol > 60 cholesterol=127healthy=200>cholesterol>60 var cholesterol, healthy; cholesterol = 127; healthy = (200 > cholesterol && cholesterol > 60); var cholesterol, healthy; cholesterol = 127; healthy = (200 > cholesterol && cholesterol > 60); var cholesterol, healthy; cholesterol = 127; healthy = (200 > cholesterol && cholesterol > 60); var cholesterol, healthy; cholesterol = 127; healthy = (200 > cholesterol && cholesterol > 60); varcholesterolhealthycholesterol=127healthy=200>cholesterol&&cholesterol>60 \t healthy \t healthy \t healthy \t \t ","dataLevel":1,"level":2,"parent":"language"},{"section":"regexes","title":"Block Regular Expressions","content":"Similar to block strings and comments, CoffeeScript supports block regexes — extended regular expressions that ignore internal whitespace and can contain comments and interpolation. Modeled after Perl’s /x modifier, CoffeeScript’s block regexes are delimited by /// and go a long way towards making complex regular expressions readable. To quote from the CoffeeScript source:/x/// NUMBER = /// ^ 0b[01]+ | # binary ^ 0o[0-7]+ | # octal ^ 0x[\\da-f]+ | # hex ^ \\d*\\.?\\d+ (?:e[+-]?\\d+)? # decimal ///i NUMBER = /// ^ 0b[01]+ | # binary ^ 0o[0-7]+ | # octal ^ 0x[\\da-f]+ | # hex ^ \\d*\\.?\\d+ (?:e[+-]?\\d+)? # decimal ///i var NUMBER; NUMBER = /^0b[01]+|^0o[0-7]+|^0x[\\da-f]+|^\\d*\\.?\\d+(?:e[+-]?\\d+)?/i; // binary // octal // hex // decimal var NUMBER; NUMBER = /^0b[01]+|^0o[0-7]+|^0x[\\da-f]+|^\\d*\\.?\\d+(?:e[+-]?\\d+)?/i; // binary // octal // hex // decimal NUMBER = /// ^ 0b[01]+ | # binary ^ 0o[0-7]+ | # octal ^ 0x[\\da-f]+ | # hex ^ \\d*\\.?\\d+ (?:e[+-]?\\d+)? # decimal ///i NUMBER = /// ^ 0b[01]+ | # binary ^ 0o[0-7]+ | # octal ^ 0x[\\da-f]+ | # hex ^ \\d*\\.?\\d+ (?:e[+-]?\\d+)? # decimal ///i var NUMBER; NUMBER = /^0b[01]+|^0o[0-7]+|^0x[\\da-f]+|^\\d*\\.?\\d+(?:e[+-]?\\d+)?/i; // binary // octal // hex // decimal var NUMBER; NUMBER = /^0b[01]+|^0o[0-7]+|^0x[\\da-f]+|^\\d*\\.?\\d+(?:e[+-]?\\d+)?/i; // binary // octal // hex // decimal NUMBER = /// ^ 0b[01]+ | # binary ^ 0o[0-7]+ | # octal ^ 0x[\\da-f]+ | # hex ^ \\d*\\.?\\d+ (?:e[+-]?\\d+)? # decimal ///i NUMBER = /// ^ 0b[01]+ | # binary ^ 0o[0-7]+ | # octal ^ 0x[\\da-f]+ | # hex ^ \\d*\\.?\\d+ (?:e[+-]?\\d+)? # decimal ///i NUMBER = /// ^ 0b[01]+ | # binary ^ 0o[0-7]+ | # octal ^ 0x[\\da-f]+ | # hex ^ \\d*\\.?\\d+ (?:e[+-]?\\d+)? # decimal ///i NUMBER = /// ^ 0b[01]+ | # binary ^ 0o[0-7]+ | # octal ^ 0x[\\da-f]+ | # hex ^ \\d*\\.?\\d+ (?:e[+-]?\\d+)? # decimal ///i NUMBER=/// ^0b[01]+|# binary^0o[0-7]+|# octal^0x[\\da-f]+|# hex^\\d*\\.?\\d+(?:e[+-]?\\d+)?# decimal///i var NUMBER; NUMBER = /^0b[01]+|^0o[0-7]+|^0x[\\da-f]+|^\\d*\\.?\\d+(?:e[+-]?\\d+)?/i; // binary // octal // hex // decimal var NUMBER; NUMBER = /^0b[01]+|^0o[0-7]+|^0x[\\da-f]+|^\\d*\\.?\\d+(?:e[+-]?\\d+)?/i; // binary // octal // hex // decimal var NUMBER; NUMBER = /^0b[01]+|^0o[0-7]+|^0x[\\da-f]+|^\\d*\\.?\\d+(?:e[+-]?\\d+)?/i; // binary // octal // hex // decimal var NUMBER; NUMBER = /^0b[01]+|^0o[0-7]+|^0x[\\da-f]+|^\\d*\\.?\\d+(?:e[+-]?\\d+)?/i; // binary // octal // hex // decimal varNUMBERNUMBER=/^0b[01]+|^0o[0-7]+|^0x[\\da-f]+|^\\d*\\.?\\d+(?:e[+-]?\\d+)?/i// binary// octal// hex// decimal","dataLevel":1,"level":2,"parent":"language"},{"section":"tagged-template-literals","title":"Tagged Template Literals","content":"CoffeeScript supports ES2015 tagged template literals, which enable customized string interpolation. If you immediately prefix a string with a function name (no space between the two), CoffeeScript will output this “function plus string” combination as an ES2015 tagged template literal, which will behave accordingly: the function is called, with the parameters being the input text and expression parts that make up the interpolated string. The function can then assemble these parts into an output string, providing custom string interpolation.ES2015 tagged template literalsbehave accordingly upperCaseExpr = (textParts, expressions...) -> textParts.reduce (text, textPart, i) -> text + expressions[i - 1].toUpperCase() + textPart greet = (name, adjective) -> upperCaseExpr\"\"\" Hi #{name}. You look #{adjective}! \"\"\" upperCaseExpr = (textParts, expressions...) -> textParts.reduce (text, textPart, i) -> text + expressions[i - 1].toUpperCase() + textPart greet = (name, adjective) -> upperCaseExpr\"\"\" Hi #{name}. You look #{adjective}! \"\"\" var greet, upperCaseExpr; upperCaseExpr = function(textParts, ...expressions) { return textParts.reduce(function(text, textPart, i) { return text + expressions[i - 1].toUpperCase() + textPart; }); }; greet = function(name, adjective) { return upperCaseExpr`Hi ${name}. You look ${adjective}!`; }; var greet, upperCaseExpr; upperCaseExpr = function(textParts, ...expressions) { return textParts.reduce(function(text, textPart, i) { return text + expressions[i - 1].toUpperCase() + textPart; }); }; greet = function(name, adjective) { return upperCaseExpr`Hi ${name}. You look ${adjective}!`; }; \t greet(\"greg\", \"awesome\") upperCaseExpr = (textParts, expressions...) -> textParts.reduce (text, textPart, i) -> text + expressions[i - 1].toUpperCase() + textPart greet = (name, adjective) -> upperCaseExpr\"\"\" Hi #{name}. You look #{adjective}! \"\"\" upperCaseExpr = (textParts, expressions...) -> textParts.reduce (text, textPart, i) -> text + expressions[i - 1].toUpperCase() + textPart greet = (name, adjective) -> upperCaseExpr\"\"\" Hi #{name}. You look #{adjective}! \"\"\" var greet, upperCaseExpr; upperCaseExpr = function(textParts, ...expressions) { return textParts.reduce(function(text, textPart, i) { return text + expressions[i - 1].toUpperCase() + textPart; }); }; greet = function(name, adjective) { return upperCaseExpr`Hi ${name}. You look ${adjective}!`; }; var greet, upperCaseExpr; upperCaseExpr = function(textParts, ...expressions) { return textParts.reduce(function(text, textPart, i) { return text + expressions[i - 1].toUpperCase() + textPart; }); }; greet = function(name, adjective) { return upperCaseExpr`Hi ${name}. You look ${adjective}!`; }; upperCaseExpr = (textParts, expressions...) -> textParts.reduce (text, textPart, i) -> text + expressions[i - 1].toUpperCase() + textPart greet = (name, adjective) -> upperCaseExpr\"\"\" Hi #{name}. You look #{adjective}! \"\"\" upperCaseExpr = (textParts, expressions...) -> textParts.reduce (text, textPart, i) -> text + expressions[i - 1].toUpperCase() + textPart greet = (name, adjective) -> upperCaseExpr\"\"\" Hi #{name}. You look #{adjective}! \"\"\" upperCaseExpr = (textParts, expressions...) -> textParts.reduce (text, textPart, i) -> text + expressions[i - 1].toUpperCase() + textPart greet = (name, adjective) -> upperCaseExpr\"\"\" Hi #{name}. You look #{adjective}! \"\"\" upperCaseExpr = (textParts, expressions...) -> textParts.reduce (text, textPart, i) -> text + expressions[i - 1].toUpperCase() + textPart greet = (name, adjective) -> upperCaseExpr\"\"\" Hi #{name}. You look #{adjective}! \"\"\" upperCaseExpr=(textParts,expressions...)->textParts.reduce(text,textPart,i)->text+expressions[i-1].toUpperCase()+textPartgreet=(name,adjective)->upperCaseExpr\"\"\" Hi #{name}. You look #{adjective}! \"\"\" var greet, upperCaseExpr; upperCaseExpr = function(textParts, ...expressions) { return textParts.reduce(function(text, textPart, i) { return text + expressions[i - 1].toUpperCase() + textPart; }); }; greet = function(name, adjective) { return upperCaseExpr`Hi ${name}. You look ${adjective}!`; }; var greet, upperCaseExpr; upperCaseExpr = function(textParts, ...expressions) { return textParts.reduce(function(text, textPart, i) { return text + expressions[i - 1].toUpperCase() + textPart; }); }; greet = function(name, adjective) { return upperCaseExpr`Hi ${name}. You look ${adjective}!`; }; var greet, upperCaseExpr; upperCaseExpr = function(textParts, ...expressions) { return textParts.reduce(function(text, textPart, i) { return text + expressions[i - 1].toUpperCase() + textPart; }); }; greet = function(name, adjective) { return upperCaseExpr`Hi ${name}. You look ${adjective}!`; }; var greet, upperCaseExpr; upperCaseExpr = function(textParts, ...expressions) { return textParts.reduce(function(text, textPart, i) { return text + expressions[i - 1].toUpperCase() + textPart; }); }; greet = function(name, adjective) { return upperCaseExpr`Hi ${name}. You look ${adjective}!`; }; vargreetupperCaseExprupperCaseExpr=functiontextParts...expressionsreturntextPartsreducefunctiontexttextPartireturntext+expressionsi-1toUpperCase+textPartgreet=functionnameadjectivereturnupperCaseExpr`Hi ${name}. You look ${adjective}!` \t greet(\"greg\", \"awesome\") \t greet(\"greg\", \"awesome\") \t greet(\"greg\", \"awesome\") \t \t ","dataLevel":1,"level":2,"parent":"language"},{"section":"modules","title":"Modules","content":"ES2015 modules are supported in CoffeeScript, with very similar import and export syntax:importexport import 'local-file.coffee' import 'coffeescript' import _ from 'underscore' import * as underscore from 'underscore' import { now } from 'underscore' import { now as currentTimestamp } from 'underscore' import { first, last } from 'underscore' import utilityBelt, { each } from 'underscore' export default Math export square = (x) -> x * x export class Mathematics least: (x, y) -> if x < y then x else y export { sqrt } export { sqrt as squareRoot } export { Mathematics as default, sqrt as squareRoot } export * from 'underscore' export { max, min } from 'underscore' import 'local-file.coffee' import 'coffeescript' import _ from 'underscore' import * as underscore from 'underscore' import { now } from 'underscore' import { now as currentTimestamp } from 'underscore' import { first, last } from 'underscore' import utilityBelt, { each } from 'underscore' export default Math export square = (x) -> x * x export class Mathematics least: (x, y) -> if x < y then x else y export { sqrt } export { sqrt as squareRoot } export { Mathematics as default, sqrt as squareRoot } export * from 'underscore' export { max, min } from 'underscore' import 'local-file.coffee'; import 'coffeescript'; import _ from 'underscore'; import * as underscore from 'underscore'; import { now } from 'underscore'; import { now as currentTimestamp } from 'underscore'; import { first, last } from 'underscore'; import utilityBelt, { each } from 'underscore'; export default Math; export var square = function(x) { return x * x; }; export var Mathematics = class Mathematics { least(x, y) { if (x < y) { return x; } else { return y; } } }; export { sqrt }; export { sqrt as squareRoot }; export { Mathematics as default, sqrt as squareRoot }; export * from 'underscore'; export { max, min } from 'underscore'; import 'local-file.coffee'; import 'coffeescript'; import _ from 'underscore'; import * as underscore from 'underscore'; import { now } from 'underscore'; import { now as currentTimestamp } from 'underscore'; import { first, last } from 'underscore'; import utilityBelt, { each } from 'underscore'; export default Math; export var square = function(x) { return x * x; }; export var Mathematics = class Mathematics { least(x, y) { if (x < y) { return x; } else { return y; } } }; export { sqrt }; export { sqrt as squareRoot }; export { Mathematics as default, sqrt as squareRoot }; export * from 'underscore'; export { max, min } from 'underscore'; import 'local-file.coffee' import 'coffeescript' import _ from 'underscore' import * as underscore from 'underscore' import { now } from 'underscore' import { now as currentTimestamp } from 'underscore' import { first, last } from 'underscore' import utilityBelt, { each } from 'underscore' export default Math export square = (x) -> x * x export class Mathematics least: (x, y) -> if x < y then x else y export { sqrt } export { sqrt as squareRoot } export { Mathematics as default, sqrt as squareRoot } export * from 'underscore' export { max, min } from 'underscore' import 'local-file.coffee' import 'coffeescript' import _ from 'underscore' import * as underscore from 'underscore' import { now } from 'underscore' import { now as currentTimestamp } from 'underscore' import { first, last } from 'underscore' import utilityBelt, { each } from 'underscore' export default Math export square = (x) -> x * x export class Mathematics least: (x, y) -> if x < y then x else y export { sqrt } export { sqrt as squareRoot } export { Mathematics as default, sqrt as squareRoot } export * from 'underscore' export { max, min } from 'underscore' import 'local-file.coffee'; import 'coffeescript'; import _ from 'underscore'; import * as underscore from 'underscore'; import { now } from 'underscore'; import { now as currentTimestamp } from 'underscore'; import { first, last } from 'underscore'; import utilityBelt, { each } from 'underscore'; export default Math; export var square = function(x) { return x * x; }; export var Mathematics = class Mathematics { least(x, y) { if (x < y) { return x; } else { return y; } } }; export { sqrt }; export { sqrt as squareRoot }; export { Mathematics as default, sqrt as squareRoot }; export * from 'underscore'; export { max, min } from 'underscore'; import 'local-file.coffee'; import 'coffeescript'; import _ from 'underscore'; import * as underscore from 'underscore'; import { now } from 'underscore'; import { now as currentTimestamp } from 'underscore'; import { first, last } from 'underscore'; import utilityBelt, { each } from 'underscore'; export default Math; export var square = function(x) { return x * x; }; export var Mathematics = class Mathematics { least(x, y) { if (x < y) { return x; } else { return y; } } }; export { sqrt }; export { sqrt as squareRoot }; export { Mathematics as default, sqrt as squareRoot }; export * from 'underscore'; export { max, min } from 'underscore'; import 'local-file.coffee' import 'coffeescript' import _ from 'underscore' import * as underscore from 'underscore' import { now } from 'underscore' import { now as currentTimestamp } from 'underscore' import { first, last } from 'underscore' import utilityBelt, { each } from 'underscore' export default Math export square = (x) -> x * x export class Mathematics least: (x, y) -> if x < y then x else y export { sqrt } export { sqrt as squareRoot } export { Mathematics as default, sqrt as squareRoot } export * from 'underscore' export { max, min } from 'underscore' import 'local-file.coffee' import 'coffeescript' import _ from 'underscore' import * as underscore from 'underscore' import { now } from 'underscore' import { now as currentTimestamp } from 'underscore' import { first, last } from 'underscore' import utilityBelt, { each } from 'underscore' export default Math export square = (x) -> x * x export class Mathematics least: (x, y) -> if x < y then x else y export { sqrt } export { sqrt as squareRoot } export { Mathematics as default, sqrt as squareRoot } export * from 'underscore' export { max, min } from 'underscore' import 'local-file.coffee' import 'coffeescript' import _ from 'underscore' import * as underscore from 'underscore' import { now } from 'underscore' import { now as currentTimestamp } from 'underscore' import { first, last } from 'underscore' import utilityBelt, { each } from 'underscore' export default Math export square = (x) -> x * x export class Mathematics least: (x, y) -> if x < y then x else y export { sqrt } export { sqrt as squareRoot } export { Mathematics as default, sqrt as squareRoot } export * from 'underscore' export { max, min } from 'underscore' import 'local-file.coffee' import 'coffeescript' import _ from 'underscore' import * as underscore from 'underscore' import { now } from 'underscore' import { now as currentTimestamp } from 'underscore' import { first, last } from 'underscore' import utilityBelt, { each } from 'underscore' export default Math export square = (x) -> x * x export class Mathematics least: (x, y) -> if x < y then x else y export { sqrt } export { sqrt as squareRoot } export { Mathematics as default, sqrt as squareRoot } export * from 'underscore' export { max, min } from 'underscore' import'local-file.coffee'import'coffeescript'import_from'underscore'import*asunderscorefrom'underscore'import{now}from'underscore'import{nowascurrentTimestamp}from'underscore'import{first,last}from'underscore'importutilityBelt,{each}from'underscore'exportdefaultMathexportsquare=(x)->x*xexportclassMathematicsleast:(x,y)->ifx. You can interpolate CoffeeScript code inside a tag using { and }. To avoid compiler errors, when using < and > to mean “less than” or “greater than,” you should wrap the operators in spaces to distinguish them from XML tags. So i < len, not i{}<>i < leni renderStarRating = ({ rating, maxStars }) -> var renderStarRating; renderStarRating = function({rating, maxStars}) { var emptyStar, wholeStar; return ; }; var renderStarRating; renderStarRating = function({rating, maxStars}) { var emptyStar, wholeStar; return ; }; renderStarRating = ({ rating, maxStars }) -> renderStarRating = ({ rating, maxStars }) -> var renderStarRating; renderStarRating = function({rating, maxStars}) { var emptyStar, wholeStar; return ; }; var renderStarRating; renderStarRating = function({rating, maxStars}) { var emptyStar, wholeStar; return ; }; renderStarRating = ({ rating, maxStars }) -> renderStarRating = ({ rating, maxStars }) -> renderStarRating = ({ rating, maxStars }) -> renderStarRating = ({ rating, maxStars }) -> renderStarRating=({rating,maxStars})-> {forwholeStarin[0...Math.floor(rating)] }{ifrating%1isnt0 }{foremptyStarin[Math.ceil(rating)...maxStars] } var renderStarRating; renderStarRating = function({rating, maxStars}) { var emptyStar, wholeStar; return ; }; var renderStarRating; renderStarRating = function({rating, maxStars}) { var emptyStar, wholeStar; return ; }; var renderStarRating; renderStarRating = function({rating, maxStars}) { var emptyStar, wholeStar; return ; }; var renderStarRating; renderStarRating = function({rating, maxStars}) { var emptyStar, wholeStar; return ; }; varrenderStarRatingrenderStarRating=functionratingmaxStarsvaremptyStarwholeStarreturn{(function() {var i, ref, results;results = [];for (wholeStar = i = 0, ref = Math.floor(rating); (0 <= ref ? i < ref : i > ref); wholeStar = 0 <= ref ? ++i : --i) {results.push();}return results;})()}{(rating % 1 !== 0 ? : void 0)}{(function() {var i, ref, ref1, results;results = [];for (emptyStar = i = ref = Math.ceil(rating), ref1 = maxStars; (ref <= ref1 ? i < ref1 : i > ref1); emptyStar = ref <= ref1 ? ++i : --i) {results.push();}return results;})()};};Older plugins or forks of CoffeeScript supported JSX syntax and referred to it as CSX or CJSX. They also often used a .cjsx file extension, but this is no longer necessary; regular .coffee will do..cjsx.coffee","dataLevel":1,"level":2,"parent":"language"},{"section":"type-annotations","title":"Type Annotations","content":"Static type checking can be achieved in CoffeeScript by using Flow’s Comment Types syntax:FlowComment Types syntax # @flow ###:: type Obj = { num: number, }; ### fn = (str ###: string ###, obj ###: Obj ###) ###: string ### -> str + obj.num # @flow ###:: type Obj = { num: number, }; ### fn = (str ###: string ###, obj ###: Obj ###) ###: string ### -> str + obj.num // @flow /*:: type Obj = { num: number, }; */ var fn; fn = function(str/*: string */, obj/*: Obj */)/*: string */ { return str + obj.num; }; // @flow /*:: type Obj = { num: number, }; */ var fn; fn = function(str/*: string */, obj/*: Obj */)/*: string */ { return str + obj.num; }; # @flow ###:: type Obj = { num: number, }; ### fn = (str ###: string ###, obj ###: Obj ###) ###: string ### -> str + obj.num # @flow ###:: type Obj = { num: number, }; ### fn = (str ###: string ###, obj ###: Obj ###) ###: string ### -> str + obj.num // @flow /*:: type Obj = { num: number, }; */ var fn; fn = function(str/*: string */, obj/*: Obj */)/*: string */ { return str + obj.num; }; // @flow /*:: type Obj = { num: number, }; */ var fn; fn = function(str/*: string */, obj/*: Obj */)/*: string */ { return str + obj.num; }; # @flow ###:: type Obj = { num: number, }; ### fn = (str ###: string ###, obj ###: Obj ###) ###: string ### -> str + obj.num # @flow ###:: type Obj = { num: number, }; ### fn = (str ###: string ###, obj ###: Obj ###) ###: string ### -> str + obj.num # @flow ###:: type Obj = { num: number, }; ### fn = (str ###: string ###, obj ###: Obj ###) ###: string ### -> str + obj.num # @flow ###:: type Obj = { num: number, }; ### fn = (str ###: string ###, obj ###: Obj ###) ###: string ### -> str + obj.num # @flow###::type Obj = { num: number,};###fn=(str###: string ###,obj###: Obj ###)###: string ###->str+obj.num // @flow /*:: type Obj = { num: number, }; */ var fn; fn = function(str/*: string */, obj/*: Obj */)/*: string */ { return str + obj.num; }; // @flow /*:: type Obj = { num: number, }; */ var fn; fn = function(str/*: string */, obj/*: Obj */)/*: string */ { return str + obj.num; }; // @flow /*:: type Obj = { num: number, }; */ var fn; fn = function(str/*: string */, obj/*: Obj */)/*: string */ { return str + obj.num; }; // @flow /*:: type Obj = { num: number, }; */ var fn; fn = function(str/*: string */, obj/*: Obj */)/*: string */ { return str + obj.num; }; // @flow/*::type Obj = { num: number,};*/varfnfn=functionstr/*: string */obj/*: Obj *//*: string */returnstr+objnumCoffeeScript does not do any type checking itself; the JavaScript output you see above needs to get passed to Flow for it to validate your code. We expect most people will use a build tool for this, but here’s how to do it the simplest way possible using the CoffeeScript and Flow command-line tools, assuming you’ve already installed Flow and the latest CoffeeScript in your project folder:build toolCoffeeScriptFlowinstalled Flowlatest CoffeeScriptcoffee --bare --no-header --compile app.coffee && npm run flow coffee --bare --no-header --compile app.coffee && npm run flow coffee --bare --no-header --compile app.coffee && npm run flow --bare and --no-header are important because Flow requires the first line of the file to be the comment // @flow. If you configure your build chain to compile CoffeeScript and pass the result to Flow in-memory, you can get better performance than this example; and a proper build tool should be able to watch your CoffeeScript files and recompile and type-check them for you on save.--bare--no-header// @flowIf you know of another way to achieve static type checking with CoffeeScript, please create an issue and let us know.create an issue","dataLevel":1,"level":1,"parent":false},{"section":"literate","title":"Literate CoffeeScript","content":"Besides being used as an ordinary programming language, CoffeeScript may also be written in “literate” mode. If you name your file with a .litcoffee extension, you can write it as a Markdown document — a document that also happens to be executable CoffeeScript code. The compiler will treat any indented blocks (Markdown’s way of indicating source code) as executable code, and ignore the rest as comments. Code blocks must also be separated from comments by at least one blank line..litcoffeeJust for kicks, a little bit of the compiler is currently implemented in this fashion: See it as a document, raw, and properly highlighted in a text editor.as a documentrawproperly highlighted in a text editorA few caveats: Code blocks need to maintain consistent indentation relative to each other. When the compiler parses your Literate CoffeeScript file, it first discards all the non-code block lines and then parses the remainder as a regular CoffeeScript file. Therefore the code blocks need to be written as if the comment lines don’t exist, with consistent indentation (including whether they are indented with tabs or spaces). Along those lines, code blocks within list items or blockquotes are not treated as executable code. Since list items and blockquotes imply their own indentation, it would be ambiguous how to treat indentation between successive code blocks when some are within these other blocks and some are not. List items can be at most only one paragraph long. The second paragraph of a list item would be indented after a blank line, and therefore indistinguishable from a code block. Code blocks need to maintain consistent indentation relative to each other. When the compiler parses your Literate CoffeeScript file, it first discards all the non-code block lines and then parses the remainder as a regular CoffeeScript file. Therefore the code blocks need to be written as if the comment lines don’t exist, with consistent indentation (including whether they are indented with tabs or spaces).Along those lines, code blocks within list items or blockquotes are not treated as executable code. Since list items and blockquotes imply their own indentation, it would be ambiguous how to treat indentation between successive code blocks when some are within these other blocks and some are not.List items can be at most only one paragraph long. The second paragraph of a list item would be indented after a blank line, and therefore indistinguishable from a code block.","dataLevel":1,"level":1,"parent":false},{"section":"source-maps","title":"Source Maps","content":"CoffeeScript includes support for generating source maps, a way to tell your JavaScript engine what part of your CoffeeScript program matches up with the code being evaluated. Browsers that support it can automatically use source maps to show your original source code in the debugger. To generate source maps alongside your JavaScript files, pass the --map or -m flag to the compiler.--map-mFor a full introduction to source maps, how they work, and how to hook them up in your browser, read the HTML5 Tutorial.HTML5 Tutorial","dataLevel":1,"level":1,"parent":false},{"section":"cake","title":"Cake, and Cakefiles","content":"CoffeeScript includes a (very) simple build system similar to Make and Rake. Naturally, it’s called Cake, and is used for the tasks that build and test the CoffeeScript language itself. Tasks are defined in a file named Cakefile, and can be invoked by running cake [task] from within the directory. To print a list of all the tasks and options, just type cake.MakeRakeCakefilecake [task]cakeTask definitions are written in CoffeeScript, so you can put arbitrary code in your Cakefile. Define a task with a name, a long description, and the function to invoke when the task is run. If your task takes a command-line option, you can define the option with short and long flags, and it will be made available in the options object. Here’s a task that uses the Node.js API to rebuild CoffeeScript’s parser:options fs = require 'fs' option '-o', '--output [DIR]', 'directory for compiled code' task 'build:parser', 'rebuild the Jison parser', (options) -> require 'jison' code = require('./lib/grammar').parser.generate() dir = options.output or 'lib' fs.writeFile \"#{dir}/parser.js\", code fs = require 'fs' option '-o', '--output [DIR]', 'directory for compiled code' task 'build:parser', 'rebuild the Jison parser', (options) -> require 'jison' code = require('./lib/grammar').parser.generate() dir = options.output or 'lib' fs.writeFile \"#{dir}/parser.js\", code var fs; fs = require('fs'); option('-o', '--output [DIR]', 'directory for compiled code'); task('build:parser', 'rebuild the Jison parser', function(options) { var code, dir; require('jison'); code = require('./lib/grammar').parser.generate(); dir = options.output || 'lib'; return fs.writeFile(`${dir}/parser.js`, code); }); var fs; fs = require('fs'); option('-o', '--output [DIR]', 'directory for compiled code'); task('build:parser', 'rebuild the Jison parser', function(options) { var code, dir; require('jison'); code = require('./lib/grammar').parser.generate(); dir = options.output || 'lib'; return fs.writeFile(`${dir}/parser.js`, code); }); fs = require 'fs' option '-o', '--output [DIR]', 'directory for compiled code' task 'build:parser', 'rebuild the Jison parser', (options) -> require 'jison' code = require('./lib/grammar').parser.generate() dir = options.output or 'lib' fs.writeFile \"#{dir}/parser.js\", code fs = require 'fs' option '-o', '--output [DIR]', 'directory for compiled code' task 'build:parser', 'rebuild the Jison parser', (options) -> require 'jison' code = require('./lib/grammar').parser.generate() dir = options.output or 'lib' fs.writeFile \"#{dir}/parser.js\", code var fs; fs = require('fs'); option('-o', '--output [DIR]', 'directory for compiled code'); task('build:parser', 'rebuild the Jison parser', function(options) { var code, dir; require('jison'); code = require('./lib/grammar').parser.generate(); dir = options.output || 'lib'; return fs.writeFile(`${dir}/parser.js`, code); }); var fs; fs = require('fs'); option('-o', '--output [DIR]', 'directory for compiled code'); task('build:parser', 'rebuild the Jison parser', function(options) { var code, dir; require('jison'); code = require('./lib/grammar').parser.generate(); dir = options.output || 'lib'; return fs.writeFile(`${dir}/parser.js`, code); }); fs = require 'fs' option '-o', '--output [DIR]', 'directory for compiled code' task 'build:parser', 'rebuild the Jison parser', (options) -> require 'jison' code = require('./lib/grammar').parser.generate() dir = options.output or 'lib' fs.writeFile \"#{dir}/parser.js\", code fs = require 'fs' option '-o', '--output [DIR]', 'directory for compiled code' task 'build:parser', 'rebuild the Jison parser', (options) -> require 'jison' code = require('./lib/grammar').parser.generate() dir = options.output or 'lib' fs.writeFile \"#{dir}/parser.js\", code fs = require 'fs' option '-o', '--output [DIR]', 'directory for compiled code' task 'build:parser', 'rebuild the Jison parser', (options) -> require 'jison' code = require('./lib/grammar').parser.generate() dir = options.output or 'lib' fs.writeFile \"#{dir}/parser.js\", code fs = require 'fs' option '-o', '--output [DIR]', 'directory for compiled code' task 'build:parser', 'rebuild the Jison parser', (options) -> require 'jison' code = require('./lib/grammar').parser.generate() dir = options.output or 'lib' fs.writeFile \"#{dir}/parser.js\", code fs=require'fs'option'-o','--output [DIR]','directory for compiled code'task'build:parser','rebuild the Jison parser',(options)->require'jison'code=require('./lib/grammar').parser.generate()dir=options.outputor'lib'fs.writeFile\"#{dir}/parser.js\",code var fs; fs = require('fs'); option('-o', '--output [DIR]', 'directory for compiled code'); task('build:parser', 'rebuild the Jison parser', function(options) { var code, dir; require('jison'); code = require('./lib/grammar').parser.generate(); dir = options.output || 'lib'; return fs.writeFile(`${dir}/parser.js`, code); }); var fs; fs = require('fs'); option('-o', '--output [DIR]', 'directory for compiled code'); task('build:parser', 'rebuild the Jison parser', function(options) { var code, dir; require('jison'); code = require('./lib/grammar').parser.generate(); dir = options.output || 'lib'; return fs.writeFile(`${dir}/parser.js`, code); }); var fs; fs = require('fs'); option('-o', '--output [DIR]', 'directory for compiled code'); task('build:parser', 'rebuild the Jison parser', function(options) { var code, dir; require('jison'); code = require('./lib/grammar').parser.generate(); dir = options.output || 'lib'; return fs.writeFile(`${dir}/parser.js`, code); }); var fs; fs = require('fs'); option('-o', '--output [DIR]', 'directory for compiled code'); task('build:parser', 'rebuild the Jison parser', function(options) { var code, dir; require('jison'); code = require('./lib/grammar').parser.generate(); dir = options.output || 'lib'; return fs.writeFile(`${dir}/parser.js`, code); }); varfsfs=require'fs'option'-o''--output [DIR]''directory for compiled code'task'build:parser''rebuild the Jison parser'functionoptionsvarcodedirrequire'jison'code=require'./lib/grammar'parsergeneratedir=optionsoutput||'lib'returnfswriteFile`${dir}/parser.js`codeIf you need to invoke one task before another — for example, running build before test, you can use the invoke function: invoke 'build'. Cake tasks are a minimal way to expose your CoffeeScript functions to the command line, so don’t expect any fanciness built-in. If you need dependencies, or async callbacks, it’s best to put them in your code itself — not the cake task.buildtestinvokeinvoke 'build'don’t expect any fanciness built-in","dataLevel":1,"level":1,"parent":false},{"section":"scripts","title":"\"text/coffeescript\" Script Tags","content":"\"text/coffeescript\"While it’s not recommended for serious use, CoffeeScripts may be included directly within the browser using - - + + diff --git a/documentation/site/search.css b/documentation/site/search.css new file mode 100644 index 0000000000..390b9fe701 --- /dev/null +++ b/documentation/site/search.css @@ -0,0 +1,709 @@ +#cs-search-input-navbar { + border-radius: 0; + background: transparent; + border-width: 0 0 1px 0; + border-color: #666; + padding-left: calc(20px + .75rem); +} +#searchIcon { + position: absolute; + display: inline-block; + bottom: 5px; + left: 0px; + width: 20px; +} +#searchIcon path { + fill: #ccc; +} + +#cs-search-input-navbar:focus { + padding-left: 0.75rem; + color: #eee; + background: rgba(255,255,255,.3); +} + +#cs-search-input-navbar:focus + #searchIcon { + display: none; +} + +.cs-autocomplete.cs-autocomplete-right .ds-dropdown-menu { + right: 0 !important; + left: inherit !important; +} + +.cs-autocomplete.cs-autocomplete-right .ds-dropdown-menu:before { + right: 48px; +} + +.cs-autocomplete.cs-autocomplete-left .ds-dropdown-menu { + left: 0 !important; + right: inherit !important; +} + +.cs-autocomplete.cs-autocomplete-left .ds-dropdown-menu:before { + left: 48px; +} + +.cs-autocomplete .ds-dropdown-menu { + position: relative; + top: -6px; + border-radius: 4px; + margin: 6px 0 0; + padding: 0; + text-align: left; + height: auto; + position: relative; + background: transparent; + border: none; + z-index: 999; + max-width: 600px; + min-width: 400px; + -webkit-box-shadow: 0 1px 0 0 rgba(0, 0, 0, 0.2), 0 2px 3px 0 rgba(0, 0, 0, 0.1); + box-shadow: 0 1px 0 0 rgba(0, 0, 0, 0.2), 0 2px 3px 0 rgba(0, 0, 0, 0.1); +} + +.cs-autocomplete .ds-dropdown-menu:before { + display: block; + position: absolute; + content: ''; + width: 14px; + height: 14px; + background: #fff; + z-index: 1000; + top: -7px; + border-top: 1px solid #efebe9; + border-right: 1px solid #efebe9; + -webkit-transform: rotate(-45deg); + transform: rotate(-45deg); + border-radius: 2px; +} + +.cs-autocomplete .ds-dropdown-menu .ds-suggestions { + position: relative; + z-index: 1000; + margin-top: 8px; +} + +.cs-autocomplete .ds-dropdown-menu .ds-suggestion { + cursor: pointer; +} + +.cs-autocomplete .ds-dropdown-menu .ds-suggestion.ds-cursor .cs-docsearch-suggestion.suggestion-layout-simple { + background-color: rgba(27, 94, 32, 0.05); +} + +.cs-autocomplete .ds-dropdown-menu .ds-suggestion.ds-cursor .cs-docsearch-suggestion:not(.suggestion-layout-simple) .cs-docsearch-suggestion--content { + background-color: rgba(27, 94, 32, 0.05); +} + +.cs-autocomplete .ds-dropdown-menu [class^="ds-dataset-"] { + position: relative; + border: solid 1px #efebe9; + background: #fff; + border-radius: 4px; + overflow: auto; + padding: 0 8px 8px; +} + +.cs-autocomplete .ds-dropdown-menu * { + -webkit-box-sizing: border-box; + box-sizing: border-box; +} + +.cs-autocomplete .cs-docsearch-suggestion { + position: relative; + padding: 0 8px; + background: #fff; + color: #0b140f; + overflow: hidden; +} + +.cs-autocomplete .cs-docsearch-suggestion--highlight { + color: #020502; + background: rgba(118, 158, 121, 0.1); + padding: 0.1em 0.05em; +} + +.cs-autocomplete .cs-docsearch-suggestion--category-header .cs-docsearch-suggestion--category-header-lvl0 .cs-docsearch-suggestion--highlight, +.cs-autocomplete .cs-docsearch-suggestion--category-header .cs-docsearch-suggestion--category-header-lvl1 .cs-docsearch-suggestion--highlight { + color: inherit; + background: inherit; +} + +.cs-autocomplete .cs-docsearch-suggestion--text .cs-docsearch-suggestion--highlight { + padding: 0 0 1px; + background: inherit; + -webkit-box-shadow: inset 0 -2px 0 0 rgba(27, 94, 32, 0.8); + box-shadow: inset 0 -2px 0 0 rgba(27, 94, 32, 0.8); + color: inherit; +} + +.cs-autocomplete .cs-docsearch-suggestion--content { + display: block; + position: relative; + padding: 6px 12px; + cursor: pointer; +} + + +.cs-autocomplete .cs-docsearch-suggestion--category-header { + position: relative; + border-bottom: 1px solid #ddd; + display: none; + margin-top: 8px; + padding: 4px 0; + font-size: 1em; + color: #2f2625; +} + +.cs-autocomplete .cs-docsearch-suggestion--wrapper { + width: 100%; + float: left; + padding: 8px 0 0 0; +} + + + + +.cs-autocomplete .cs-docsearch-suggestion--subcategory-inline { + display: none; +} + +.cs-autocomplete .cs-docsearch-suggestion--title { + margin-bottom: 4px; + color: #0b140f; + font-size: 0.9em; + font-weight: bold; +} + +.cs-autocomplete .cs-docsearch-suggestion--text { + display: block; + line-height: 1.2em; + font-size: 0.85em; + color: #3f4145; +} + +.cs-autocomplete .cs-docsearch-suggestion--no-results { + width: 100%; + padding: 8px 0; + text-align: center; + font-size: 1.2em; +} + +.cs-autocomplete .cs-docsearch-suggestion--no-results::before { + display: none; +} + +.cs-autocomplete .cs-docsearch-suggestion code { + padding: 1px 5px; + font-size: 90%; + border: none; + color: #222222; + background-color: #EBEBEB; + border-radius: 3px; + font-family: Menlo,Monaco,Consolas,"Courier New",monospace; +} + +.cs-autocomplete .cs-docsearch-suggestion code .cs-docsearch-suggestion--highlight { + background: none; +} + +.cs-autocomplete .cs-docsearch-suggestion.cs-docsearch-suggestion__main .cs-docsearch-suggestion--category-header { + display: block; +} + +.cs-autocomplete .cs-docsearch-suggestion.cs-docsearch-suggestion__secondary { + display: block; +} + + +@media all and (max-width: 768px) { + .cs-autocomplete .cs-docsearch-suggestion .cs-docsearch-suggestion--content { + display: inline-block; + width: auto; + text-align: left; + padding: 0; + } +} + +.cs-autocomplete .suggestion-layout-simple.cs-docsearch-suggestion { + border-bottom: solid 1px #eee; + padding: 8px; + margin: 0; +} + +.cs-autocomplete .suggestion-layout-simple .cs-docsearch-suggestion--content { + width: 100%; + padding: 0; +} + +.cs-autocomplete .suggestion-layout-simple .cs-docsearch-suggestion--category-header { + margin: 0; + padding: 0; + display: block; + width: 100%; + border: none; +} + +.cs-autocomplete .suggestion-layout-simple .cs-docsearch-suggestion--category-header-lvl0 { + opacity: .6; + font-size: 0.85em; +} + +.cs-autocomplete .suggestion-layout-simple .cs-docsearch-suggestion--category-header-lvl1 { + opacity: .6; + font-size: 0.85em; +} + +.cs-autocomplete .suggestion-layout-simple .cs-docsearch-suggestion--category-header-lvl1::before { + background-image: url('data:image/svg+xml;utf8,'); + content: ''; + width: 10px; + height: 10px; + display: inline-block; +} + +.cs-autocomplete .suggestion-layout-simple .cs-docsearch-suggestion--wrapper { + width: 100%; + float: left; + margin: 0; + padding: 0; +} + +.cs-autocomplete .suggestion-layout-simple .cs-docsearch-suggestion--duplicate-content, .cs-autocomplete .suggestion-layout-simple .cs-docsearch-suggestion--subcategory-inline { + display: none !important; +} + +.cs-autocomplete .suggestion-layout-simple .cs-docsearch-suggestion--title { + margin: 0; + color: #1b5e20; + font-size: 0.9em; + font-weight: normal; +} + +.cs-autocomplete .suggestion-layout-simple .cs-docsearch-suggestion--title::before { + content: "#"; + font-weight: bold; + color: #1b5e20; + display: inline-block; +} + +.cs-autocomplete .suggestion-layout-simple .cs-docsearch-suggestion--text { + margin: 4px 0 0; + display: block; + line-height: 1.4em; + padding: 5.33333px 8px; + background: #f8f8f8; + font-size: 0.85em; + opacity: .8; +} + +.cs-autocomplete .suggestion-layout-simple .cs-docsearch-suggestion--text .cs-docsearch-suggestion--highlight { + color: #1a1b1d; + font-weight: bold; + -webkit-box-shadow: none; + box-shadow: none; +} + +.cs-autocomplete .cs-docsearch-footer { + width: 110px; + height: 20px; + z-index: 2000; + margin-top: 10.66667px; + float: right; + font-size: 0; + line-height: 0; +} + + +/* + * Search input; see search.css for most of the styling of the dropdown + */ + +.cs-search-form { + font-family: 'Lato'; +} +.cs-search-form-sidebar { + min-width: 100%; + margin: 0.7em 1.2em 0.7em 0.7em; +} +.cs-search-form-sidebar .cs-autocomplete { + width: calc(100% - 1.9em); +} + +.cs-search-input { + appearance: none; + -webkit-appearance: none; + background-image: url('data:image/svg+xml;utf8,'); + background-size: 1em 1em; + background-repeat: no-repeat; + background-position-y: center; + background-position-x: 0.5em; + padding-left: 2em; + color: #2f2625; +} + +.cs-search-form-sidebar .cs-autocomplete .ds-dropdown-menu { + min-width: 100%; + max-width: 100%; +} + +/* + +.cs-autocomplete.cs-autocomplete-right .ds-dropdown-menu { + right: 0 !important; + left: inherit !important; +} + +.cs-autocomplete.cs-autocomplete-right .ds-dropdown-menu:before { + right: 48px; +} + +.cs-autocomplete.cs-autocomplete-left .ds-dropdown-menu { + left: 0 !important; + right: inherit !important; +} + +.cs-autocomplete.cs-autocomplete-left .ds-dropdown-menu:before { + left: 48px; +} + +.cs-autocomplete .ds-dropdown-menu { + position: relative; + top: -6px; + border-radius: 4px; + margin: 6px 0 0; + padding: 0; + text-align: left; + height: auto; + position: relative; + background: transparent; + border: none; + z-index: 999; + max-width: 600px; + min-width: 500px; + -webkit-box-shadow: 0 1px 0 0 rgba(0, 0, 0, 0.2), 0 2px 3px 0 rgba(0, 0, 0, 0.1); + box-shadow: 0 1px 0 0 rgba(0, 0, 0, 0.2), 0 2px 3px 0 rgba(0, 0, 0, 0.1); +} + +.cs-autocomplete .ds-dropdown-menu:before { + display: block; + position: absolute; + content: ''; + width: 14px; + height: 14px; + background: #fff; + z-index: 1000; + top: -7px; + border-top: 1px solid #efebe9; + border-right: 1px solid #efebe9; + -webkit-transform: rotate(-45deg); + transform: rotate(-45deg); + border-radius: 2px; +} + +.cs-autocomplete .ds-dropdown-menu .ds-suggestions { + position: relative; + z-index: 1000; + margin-top: 8px; +} + +.cs-autocomplete .ds-dropdown-menu .ds-suggestion { + cursor: pointer; +} + +.cs-autocomplete .ds-dropdown-menu .ds-suggestion.ds-cursor .cs-docsearch-suggestion.suggestion-layout-simple { + background-color: rgba(27, 94, 32, 0.05); +} + +.cs-autocomplete .ds-dropdown-menu .ds-suggestion.ds-cursor .cs-docsearch-suggestion:not(.suggestion-layout-simple) .cs-docsearch-suggestion--content { + background-color: rgba(27, 94, 32, 0.05); +} + +.cs-autocomplete .ds-dropdown-menu [class^="ds-dataset-"] { + position: relative; + border: solid 1px #efebe9; + background: #fff; + border-radius: 4px; + overflow: auto; + padding: 0 8px 8px; +} + +.cs-autocomplete .ds-dropdown-menu * { + -webkit-box-sizing: border-box; + box-sizing: border-box; +} + +.cs-autocomplete .cs-docsearch-suggestion { + position: relative; + padding: 0 8px; + background: #fff; + color: #0b140f; + overflow: hidden; +} + +.cs-autocomplete .cs-docsearch-suggestion--highlight { + color: #020502; + background: rgba(118, 158, 121, 0.1); + padding: 0.1em 0.05em; +} + +.cs-autocomplete .cs-docsearch-suggestion--category-header .cs-docsearch-suggestion--category-header-lvl0 .cs-docsearch-suggestion--highlight, +.cs-autocomplete .cs-docsearch-suggestion--category-header .cs-docsearch-suggestion--category-header-lvl1 .cs-docsearch-suggestion--highlight { + color: inherit; + background: inherit; +} + +.cs-autocomplete .cs-docsearch-suggestion--text .cs-docsearch-suggestion--highlight { + padding: 0 0 1px; + background: inherit; + -webkit-box-shadow: inset 0 -2px 0 0 rgba(27, 94, 32, 0.8); + box-shadow: inset 0 -2px 0 0 rgba(27, 94, 32, 0.8); + color: inherit; +} + +.cs-autocomplete .cs-docsearch-suggestion--content { + display: block; + float: right; + width: 70%; + position: relative; + padding: 5.33333px 0 5.33333px 10.66667px; + cursor: pointer; +} + +.cs-autocomplete .cs-docsearch-suggestion--content:before { + content: ''; + position: absolute; + display: block; + top: 0; + height: 100%; + width: 1px; + background: #ddd; + left: -1px; +} + +.cs-autocomplete .cs-docsearch-suggestion--category-header { + position: relative; + border-bottom: 1px solid #ddd; + display: none; + margin-top: 8px; + padding: 4px 0; + font-size: 1em; + color: #2f2625; +} + +.cs-autocomplete .cs-docsearch-suggestion--wrapper { + width: 100%; + float: left; + padding: 8px 0 0 0; +} + +.cs-autocomplete .cs-docsearch-suggestion--subcategory-column { + float: left; + width: 30%; + padding-left: 0; + text-align: right; + position: relative; + padding: 5.33333px 10.66667px; + color: #a29f9c; + font-size: 0.9em; + word-wrap: break-word; +} + +.cs-autocomplete .cs-docsearch-suggestion--subcategory-column:before { + content: ''; + position: absolute; + display: block; + top: 0; + height: 100%; + width: 1px; + background: #ddd; + right: 0; +} + +.cs-autocomplete .cs-docsearch-suggestion--subcategory-column .cs-docsearch-suggestion--highlight { + background-color: inherit; + color: inherit; +} + +.cs-autocomplete .cs-docsearch-suggestion--subcategory-inline { + display: none; +} + +.cs-autocomplete .cs-docsearch-suggestion--title { + margin-bottom: 4px; + color: #0b140f; + font-size: 0.9em; + font-weight: bold; +} + +.cs-autocomplete .cs-docsearch-suggestion--text { + display: block; + line-height: 1.2em; + font-size: 0.85em; + color: #3f4145; +} + +.cs-autocomplete .cs-docsearch-suggestion--no-results { + width: 100%; + padding: 8px 0; + text-align: center; + font-size: 1.2em; +} + +.cs-autocomplete .cs-docsearch-suggestion--no-results::before { + display: none; +} + +.cs-autocomplete .cs-docsearch-suggestion code { + padding: 1px 5px; + font-size: 90%; + border: none; + color: #222222; + background-color: #EBEBEB; + border-radius: 3px; + font-family: Menlo,Monaco,Consolas,"Courier New",monospace; +} + +.cs-autocomplete .cs-docsearch-suggestion code .cs-docsearch-suggestion--highlight { + background: none; +} + +.cs-autocomplete .cs-docsearch-suggestion.cs-docsearch-suggestion__main .cs-docsearch-suggestion--category-header { + display: block; +} + +.cs-autocomplete .cs-docsearch-suggestion.cs-docsearch-suggestion__secondary { + display: block; +} + +@media all and (min-width: 768px) { + .cs-autocomplete .cs-docsearch-suggestion .cs-docsearch-suggestion--subcategory-column { + display: block; + } +} + +@media all and (max-width: 768px) { + .cs-autocomplete .cs-docsearch-suggestion .cs-docsearch-suggestion--subcategory-column { + display: inline-block; + width: auto; + text-align: left; + float: left; + padding: 0; + color: #02060C; + font-size: 0.9em; + font-weight: bold; + text-align: left; + opacity: 0.5; + } + .cs-autocomplete .cs-docsearch-suggestion .cs-docsearch-suggestion--subcategory-column:before { + display: none; + } + .cs-autocomplete .cs-docsearch-suggestion .cs-docsearch-suggestion--subcategory-column:after { + content: "|"; + } + .cs-autocomplete .cs-docsearch-suggestion .cs-docsearch-suggestion--content { + display: inline-block; + width: auto; + text-align: left; + float: left; + padding: 0; + } + .cs-autocomplete .cs-docsearch-suggestion .cs-docsearch-suggestion--content:before { + display: none; + } +} + +.cs-autocomplete .suggestion-layout-simple.cs-docsearch-suggestion { + border-bottom: solid 1px #eee; + padding: 8px; + margin: 0; +} + +.cs-autocomplete .suggestion-layout-simple .cs-docsearch-suggestion--content { + width: 100%; + padding: 0; +} + +.cs-autocomplete .suggestion-layout-simple .cs-docsearch-suggestion--content::before { + display: none; +} + +.cs-autocomplete .suggestion-layout-simple .cs-docsearch-suggestion--category-header { + margin: 0; + padding: 0; + display: block; + width: 100%; + border: none; +} + +.cs-autocomplete .suggestion-layout-simple .cs-docsearch-suggestion--category-header-lvl0 { + opacity: .6; + font-size: 0.85em; +} + +.cs-autocomplete .suggestion-layout-simple .cs-docsearch-suggestion--category-header-lvl1 { + opacity: .6; + font-size: 0.85em; +} + +.cs-autocomplete .suggestion-layout-simple .cs-docsearch-suggestion--category-header-lvl1::before { + background-image: url('data:image/svg+xml;utf8,'); + content: ''; + width: 10px; + height: 10px; + display: inline-block; +} + +.cs-autocomplete .suggestion-layout-simple .cs-docsearch-suggestion--wrapper { + width: 100%; + float: left; + margin: 0; + padding: 0; +} + +.cs-autocomplete .suggestion-layout-simple .cs-docsearch-suggestion--duplicate-content, .cs-autocomplete .suggestion-layout-simple .cs-docsearch-suggestion--subcategory-inline { + display: none !important; +} + +.cs-autocomplete .suggestion-layout-simple .cs-docsearch-suggestion--title { + margin: 0; + color: #1b5e20; + font-size: 0.9em; + font-weight: normal; +} + +.cs-autocomplete .suggestion-layout-simple .cs-docsearch-suggestion--title::before { + content: "#"; + font-weight: bold; + color: #1b5e20; + display: inline-block; +} + +.cs-autocomplete .suggestion-layout-simple .cs-docsearch-suggestion--text { + margin: 4px 0 0; + display: block; + line-height: 1.4em; + padding: 5.33333px 8px; + background: #f8f8f8; + font-size: 0.85em; + opacity: .8; +} + +.cs-autocomplete .suggestion-layout-simple .cs-docsearch-suggestion--text .cs-docsearch-suggestion--highlight { + color: #1a1b1d; + font-weight: bold; + -webkit-box-shadow: none; + box-shadow: none; +} + +.cs-autocomplete .cs-docsearch-footer { + width: 110px; + height: 20px; + z-index: 2000; + margin-top: 10.66667px; + float: right; + font-size: 0; + line-height: 0; +} +*/ \ No newline at end of file diff --git a/documentation/site/search.svg b/documentation/site/search.svg new file mode 100644 index 0000000000..22f5cf424c --- /dev/null +++ b/documentation/site/search.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/documentation/site/sidebar.html b/documentation/site/sidebar.html index 1beaa815a1..6eb1d77122 100644 --- a/documentation/site/sidebar.html +++ b/documentation/site/sidebar.html @@ -1,5 +1,10 @@