Permalink
Browse files

Docs improvements: content in Markdown, organization into subtemplate…

…s, fixed tests (#4401)

* Replace tiny bitmaps with base64-encoded URIs

* Optimize SVGs; replace logo PNG with SVG

* Modernize favicon

* Embed CSS; a bit unorthodox, but we’re a single page so there’s no point in separate .css files and their separate HTTP requests

* Documentation is now markdown, converted to HTML on compilation

* Render the examples when we’re rendering index.html; they compile so quickly that there’s no need to pre-render them and save the intermediate .js files

* Split apart index.html into components that Cakefile assembles, so that we can add in logic to include different files for v1 versus v2

* Split building index.html and building test.html into two tasks; collapse the parts of `releaseHeader` into one compact function

* Move include logic into templates

* Get error messages tests to work in the browser

* Update output index.html

* Split body into nav and body

* Watch subtemplates

* Revert "Split body into nav and body"

This reverts commit ec9e559.

* Add marked

* Update gitignore

* Use idiomatic markdown output for code blocks (<pre><code>)

* Handle ids within the template, not in the Cakefile; remove marked’s auto-generated and conflicting ids

* Move the `codeFor` function into versioned folders, so that v1 and v2 docs can have different example code blocks/editors

* Update packages, including new highlight.js which supports our newer keywords and triple backticks (docs output is unchanged)
  • Loading branch information...
1 parent be0f1cb commit e620434a2e1f913153a93656aab869453a536cd4 @GeoffreyBooth GeoffreyBooth committed on GitHub Dec 16, 2016
Showing with 4,127 additions and 5,373 deletions.
  1. +1 −3 .gitignore
  2. +90 −93 Cakefile
  3. +0 −1 docs/v1/.gitignore
  4. +1,183 −2,729 docs/v1/index.html
  5. +1,197 −0 docs/v1/test.html
  6. +15 −2,529 documentation/index.html
  7. +13 −0 documentation/sections/books.md
  8. +11 −0 documentation/sections/cake.md
  9. +508 −0 documentation/sections/changelog.md
  10. +5 −0 documentation/sections/chat.md
  11. +20 −0 documentation/sections/classes.md
  12. +7 −0 documentation/sections/comparisons.md
  13. +9 −0 documentation/sections/conditionals.md
  14. +39 −0 documentation/sections/destructuring.md
  15. +21 −0 documentation/sections/embedded.md
  16. +11 −0 documentation/sections/examples.md
  17. +17 −0 documentation/sections/existential_operator.md
  18. +29 −0 documentation/sections/expressions.md
  19. +27 −0 documentation/sections/fat_arrow.md
  20. +13 −0 documentation/sections/functions.md
  21. +7 −0 documentation/sections/heregexes.md
  22. +27 −0 documentation/sections/installation.md
  23. +11 −0 documentation/sections/introduction.md
  24. +10 −0 documentation/sections/language.md
  25. +15 −0 documentation/sections/lexical_scope.md
  26. +7 −0 documentation/sections/literate.md
  27. +47 −0 documentation/sections/loops.md
  28. +11 −0 documentation/sections/modules.md
  29. +19 −0 documentation/sections/objects_and_arrays.md
  30. +149 −0 documentation/sections/operators.md
  31. +7 −0 documentation/sections/overview.md
  32. +23 −0 documentation/sections/resources.md
  33. +5 −0 documentation/sections/screencasts.md
  34. +7 −0 documentation/sections/scripts.md
  35. +15 −0 documentation/sections/slices.md
  36. +5 −0 documentation/sections/source_maps.md
  37. +7 −0 documentation/sections/splats.md
  38. +27 −0 documentation/sections/strings.md
  39. +15 −0 documentation/sections/switch.md
  40. +9 −0 documentation/sections/tagged_template_literals.md
  41. +7 −0 documentation/sections/try.md
  42. +179 −0 documentation/sections/usage.md
  43. +2 −0 documentation/test.html
  44. +155 −0 documentation/v1/body.html
  45. +25 −0 documentation/v1/code.coffee
  46. +92 −0 documentation/v1/docs.coffee
  47. +13 −8 documentation/{css → v1}/docs.css
  48. +6 −0 documentation/v1/scripts.html
  49. +4 −0 documentation/v1/styles.html
  50. +2 −8 documentation/{css → v1}/tomorrow.css
  51. +3 −2 package.json
View
@@ -3,8 +3,6 @@ presentation
test.coffee
test.litcoffee
parser.output
-test/fixtures/underscore
test/*.js
-examples/beautiful_code/parse.coffee
-*.gem
/node_modules
+npm-debug.log
View
@@ -25,7 +25,7 @@ header = """
"""
# Used in folder names like docs/v1
-majorVersion = CoffeeScript.VERSION.split('.')[0]
+majorVersion = parseInt CoffeeScript.VERSION.split('.')[0], 10
# Build the CoffeeScript language from source.
build = (cb) ->
@@ -132,74 +132,96 @@ task 'build:browser', 'rebuild the merged script for inclusion in the browser',
task 'doc:site', 'watch and continually rebuild the documentation for the website', ->
+ # Constants
+ indexFile = 'documentation/index.html'
+ versionedSourceFolder = "documentation/v#{majorVersion}"
+ sectionsSourceFolder = 'documentation/sections'
+ examplesSourceFolder = 'documentation/examples'
+ outputFolder = "docs/v#{majorVersion}"
+
# Helpers
- css = fs.readFileSync('./documentation/css/docs.css', 'utf-8') + '\n' +
- fs.readFileSync('./documentation/css/tomorrow.css', 'utf-8')
-
- logo = fs.readFileSync './documentation/images/logo.svg', 'utf-8'
-
- codeFor = ->
- counter = 0
- hljs = require 'highlight.js'
- hljs.configure classPrefix: ''
- (file, executable = false, showLoad = true) ->
- counter++
- return unless fs.existsSync "docs/v#{majorVersion}/examples/#{file}.js"
- cs = fs.readFileSync "documentation/examples/#{file}.coffee", 'utf-8'
- js = fs.readFileSync "docs/v#{majorVersion}/examples/#{file}.js", 'utf-8'
- js = js.replace /^\/\/ generated.*?\n/i, ''
-
- cshtml = "<pre><code>#{hljs.highlight('coffeescript', cs).value}</code></pre>"
- # Temporary fix until highlight.js adds support for newer CoffeeScript keywords
- # Added in https://github.com/isagalaev/highlight.js/pull/1357, awaiting release
- if file in ['generator_iteration', 'generators', 'modules']
- cshtml = cshtml.replace /(yield|import|export|from|as|default) /g, '<span class="keyword">$1</span> '
- jshtml = "<pre><code>#{hljs.highlight('javascript', js).value}</code></pre>"
- append = if executable is yes then '' else "alert(#{executable});".replace /"/g, '&quot;'
- if executable and executable isnt yes
- cs.replace /(\S)\s*\Z/m, "$1\n\nalert #{executable}"
- run = if executable is true then 'run' else "run: #{executable}"
- name = "example#{counter}"
- script = "<script>window.#{name} = #{JSON.stringify cs}</script>"
- load = if showLoad then "<div class='minibutton load' onclick='javascript: loadConsole(#{name});'>load</div>" else ''
- button = if executable then """<div class="minibutton ok" onclick="javascript: #{js.replace /"/g, '&quot;'};#{append}">#{run}</div>""" else ''
- "<div class='code'>#{cshtml}#{jshtml}#{script}#{load}#{button}<br class='clear' /></div>"
-
- monthNames = [
- 'January'
- 'February'
- 'March'
- 'April'
- 'May'
- 'June'
- 'July'
- 'August'
- 'September'
- 'October'
- 'November'
- 'December'
- ]
-
- formatDate = (date) ->
- date.replace /^(\d\d\d\d)-(\d\d)-(\d\d)$/, (match, $1, $2, $3) ->
- "#{monthNames[$2 - 1]} #{+$3}, #{$1}"
-
- releaseHeader = (date, version, prevVersion) -> """
- <div class="anchor" id="#{version}"></div>
- <b class="header">
- #{prevVersion and "<a href=\"https://github.com/jashkenas/coffeescript/compare/#{prevVersion}...#{version}\">#{version}</a>" or version}
- <span class="timestamp"> &mdash; <time datetime="#{date}">#{formatDate date}</time></span>
- </b>
- """
+ releaseHeader = (date, version, prevVersion) ->
+ monthNames = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']
+
+ formatDate = (date) ->
+ date.replace /^(\d\d\d\d)-(\d\d)-(\d\d)$/, (match, $1, $2, $3) ->
+ "#{monthNames[$2 - 1]} #{+$3}, #{$1}"
+
+ """
+ <div class="anchor" id="#{version}"></div>
+ <h2 class="header">
+ #{prevVersion and "<a href=\"https://github.com/jashkenas/coffeescript/compare/#{prevVersion}...#{version}\">#{version}</a>" or version}
+ <span class="timestamp"> &mdash; <time datetime="#{date}">#{formatDate date}</time></span>
+ </h2>
+ """
+ codeFor = require "./documentation/v#{majorVersion}/code.coffee"
+
+ htmlFor = ->
+ marked = require 'marked'
+ markdownRenderer = new marked.Renderer()
+ markdownRenderer.heading = (text, level) ->
+ "<h#{level}>#{text}</h#{level}>" # Don’t let marked add an id
+ markdownRenderer.code = (code) ->
+ if code.indexOf('codeFor(') is 0 or code.indexOf('releaseHeader(') is 0
+ "<%= #{code} %>"
+ else
+ "<pre><code>#{code}</code></pre>" # Default
+
+ (file, bookmark) ->
+ md = fs.readFileSync "#{sectionsSourceFolder}/#{file}.md", 'utf-8'
+ md = md.replace /<%= releaseHeader %>/g, releaseHeader
+ md = md.replace /<%= majorVersion %>/g, majorVersion
+ md = md.replace /<%= fullVersion %>/g, CoffeeScript.VERSION
+ html = marked md, renderer: markdownRenderer
+ html = _.template(html)
+ codeFor: codeFor()
+ releaseHeader: releaseHeader
+
+ include = ->
+ (file) ->
+ file = "#{versionedSourceFolder}/#{file}" if file.indexOf('/') is -1
+ output = fs.readFileSync file, 'utf-8'
+ if /\.html$/.test(file)
+ render = _.template output
+ output = render
+ releaseHeader: releaseHeader
+ majorVersion: majorVersion
+ fullVersion: CoffeeScript.VERSION
+ htmlFor: htmlFor()
+ codeFor: codeFor()
+ include: include()
+ output
+
+ # Task
+ do renderIndex = ->
+ render = _.template fs.readFileSync(indexFile, 'utf-8')
+ output = render
+ include: include()
+ fs.writeFileSync "#{outputFolder}/index.html", output
+ log 'compiled', green, "#{indexFile}#{outputFolder}/index.html"
+ try
+ fs.symlinkSync "v#{majorVersion}/index.html", 'docs/index.html'
+ catch exception
+
+ for target in [indexFile, versionedSourceFolder, examplesSourceFolder, sectionsSourceFolder]
+ fs.watch target, interval: 200, renderIndex
+ log 'watching...' , green
+
+
+task 'doc:test', 'watch and continually rebuild the browser-based tests', ->
+ # Constants
+ testFile = 'documentation/test.html'
+ testsSourceFolder = 'test'
+ outputFolder = "docs/v#{majorVersion}"
+
+ # Included in test.html
testHelpers = fs.readFileSync('test/support/helpers.coffee', 'utf-8').replace /exports\./g, '@'
+ # Helpers
testsInScriptBlocks = ->
output = ''
- excludedTestFiles = ['error_messages.coffee']
- for filename in fs.readdirSync 'test'
- continue if filename in excludedTestFiles
-
+ for filename in fs.readdirSync testsSourceFolder
if filename.indexOf('.coffee') isnt -1
type = 'coffeescript'
else if filename.indexOf('.litcoffee') isnt -1
@@ -217,41 +239,16 @@ task 'doc:site', 'watch and continually rebuild the documentation for the websit
output
# Task
- examplesSourceFolder = 'documentation/examples'
- examplesOutputFolder = "docs/v#{majorVersion}/examples"
- fs.mkdirSync examplesOutputFolder unless fs.existsSync examplesOutputFolder
- do renderExamples = ->
- execSync "bin/coffee -bc -o #{examplesOutputFolder} #{examplesSourceFolder}/*.coffee"
-
- indexFile = 'documentation/index.html'
- do renderIndex = ->
- render = _.template fs.readFileSync(indexFile, 'utf-8')
- output = render
- css: css
- logo: logo
- codeFor: codeFor()
- releaseHeader: releaseHeader
- majorVersion: majorVersion
- fullVersion: CoffeeScript.VERSION
- fs.writeFileSync "docs/v#{majorVersion}/index.html", output
- log 'compiled', green, "#{indexFile} → docs/v#{majorVersion}/index.html"
-
- testFile = 'documentation/test.html'
do renderTest = ->
render = _.template fs.readFileSync(testFile, 'utf-8')
output = render
testHelpers: testHelpers
tests: testsInScriptBlocks()
- majorVersion: majorVersion
- fs.writeFileSync "docs/v#{majorVersion}/test.html", output
- log 'compiled', green, "#{testFile} → docs/v#{majorVersion}/test.html"
-
- fs.watch examplesSourceFolder, interval: 200, ->
- renderExamples()
- renderIndex()
- fs.watch indexFile, interval: 200, renderIndex
- fs.watch testFile, interval: 200, renderTest
- fs.watch 'test', interval: 200, renderTest
+ fs.writeFileSync "#{outputFolder}/test.html", output
+ log 'compiled', green, "#{testFile}#{outputFolder}/test.html"
+
+ for target in [testFile, testsSourceFolder]
+ fs.watch target, interval: 200, renderTest
log 'watching...' , green
View
@@ -1 +0,0 @@
-examples/
Oops, something went wrong.

0 comments on commit e620434

Please sign in to comment.