Skip to content
This repository
Fetching contributors…

Cannot retrieve contributors at this time

file 207 lines (173 sloc) 7.397 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207
fs = require("fs")
path = require("path")
{spawn, exec} = require("child_process")
stdout = process.stdout

# Use executables installed with npm bundle.
process.env["PATH"] = "node_modules/.bin:#{process.env["PATH"]}"

# ANSI Terminal Colors.
bold = "\033[0;1m"
red = "\033[0;31m"
green = "\033[0;32m"
reset = "\033[0m"

# Log a message with a color.
log = (message, color, explanation) ->
  console.log color + message + reset + ' ' + (explanation or '')

# Handle error and kill the process.
onerror = (err)->
  if err
    process.stdout.write "#{red}#{err.stack}#{reset}\n"
    process.exit -1


## Setup ##

# Setup development dependencies, not part of runtime dependencies.
task "setup", "Install development dependencies", ->
  fs.readFile "package.json", "utf8", (err, package)->
    log "Need runtime dependencies, installing into node_modules ...", green
    exec "npm bundle", onerror

    log "Need development dependencies, installing ...", green
    for name, version of JSON.parse(package).devDependencies
      log "Installing #{name} #{version}", green
      exec "npm bundle install \"#{name}@#{version}\"", onerror


## Building ##

build = (callback)->
  log "Compiling CoffeeScript to JavaScript ...", green
  exec "rm -rf lib && coffee -c -l -b -o lib src", (err, stdout)->
    callback err
task "build", "Compile CoffeeScript to JavaScript", -> build onerror

task "watch", "Continously compile CoffeeScript to JavaScript", ->
  cmd = spawn("coffee", ["-cw", "-o", "lib", "src"])
  cmd.stdout.on "data", (data)-> process.stdout.write green + data + reset
  cmd.on "error", onerror


clean = (callback)->
  exec "rm -rf html lib man7", callback
task "clean", "Remove temporary files and such", -> clean onerror


## Testing ##

runTests = (callback)->
  log "Running test suite ...", green
  exec "vows --spec", (err, stdout)->
    process.stdout.write stdout
    callback err if callback
task "test", "Run all tests", ->
  runTests (err)->
    process.stdout.on "drain", -> process.exit -1 if err


## Documentation ##

# Markdown to HTML.
toHTML = (source, callback)->
  target = "html/#{path.basename(source, ".md").toLowerCase()}.html"
  fs.readFile "doc/layout/main.html", "utf8", (err, layout)->
    onerror err
    fs.readFile source, "utf8", (err, text)->
      onerror err
      log "Creating #{target}", green
      exec "ronn --html #{source}", (err, stdout, stderr)->
        onerror err
        [name, title] = stdout.match(/<h1>(.*)<\/h1>/)[1].split(" -- ")
        name = name.replace(/\(\d\)/, "")
        body = stdout.replace(/<h1>.*<\/h1>/, "")
        html = layout.replace("{{body}}", body).replace(/{{title}}/g, title)
        fs.writeFile target, html, "utf8", (err)->
          callback err, target

documentPages = (callback)->
  files = fs.readdirSync(".").filter((file)-> path.extname(file) == ".md").
    concat(fs.readdirSync("doc").filter((file)-> path.extname(file) == ".md").map((file)-> "doc/#{file}"))
  fs.mkdir "html", 0777, ->
    convert = ->
      if file = files.pop()
        toHTML file, (err)->
          onerror err
          convert()
      else
        process.stdout.write "\n"
        fs.readFile "html/readme.html", "utf8", (err, html)->
          html = html.replace(/<h1>(.*)<\/h1>/, "<h1>Zombie.js</h1><b>$1</b>")
          fs.writeFile "html/index.html", html, "utf8", onerror
          fs.unlink "html/readme.html", onerror
          exec "cp -fr doc/css doc/images html/", callback
    convert()

documentSource = (callback)->
  log "Documenting source files ...", green
  exec "docco src/*.coffee src/**/*.coffee", (err, stdout, stderr)->
    log stdout, green
    onerror err
    log "Copying to html/source", green
    exec "mkdir -p html && cp -rf docs/ html/source && rm -rf docs", callback

generateMan = (callback)->
  files = fs.readdirSync(".").filter((file)-> path.extname(file) == ".md").
    concat(fs.readdirSync("doc").filter((file)-> path.extname(file) == ".md").map((file)-> "doc/#{file}"))
  fs.mkdir "man7", 0777, (err)->
    log "Generating man file ...", green
    convert = ->
      if file = files.pop()
        target = "man7/#{path.basename(file, ".md").toLowerCase()}.7"
        exec "ronn --roff #{file}", (err, stdout, stderr)->
          onerror err
          log "Creating #{target}", green
          fs.writeFile target, stdout, "utf8", onerror
          convert()
      else
        exec "mv man7/readme.7 man7/zombie.7", onerror
        process.stdout.write "\n"
        callback()
    convert()

generatePDF = (callback)->
  log "Generating PDF documentation ...", green
  files = "index api selectors troubleshoot".split(" ").map((f)-> "html/#{f}.html")
  options = "--disable-javascript --outline --print-media-type --title Zombie.js --header-html doc/layout/header.html"
  toc = "--toc --toc-depth 2 --toc-no-dots --cover doc/layout/cover.html --allow doc/images --outline"
  margins = "--margin-left 20 --margin-right 20 --margin-top 20 --margin-bottom 20 --header-spacing 5"
  exec "wkhtmltopdf #{options} #{margins} #{toc} #{files.join(" ")} html/zombie.pdf", callback

generateDocs = (callback)->
  log "Generating documentation ...", green
  documentPages (err)->
    onerror err
    documentSource (err)->
      onerror err
      generatePDF (err)->
        onerror err
        generateMan callback

task "doc:pages", "Generate documentation for main pages", -> documentPages onerror
task "doc:source", "Generate documentation from source files", -> documentSource onerror
task "doc:man", "Generate man pages", -> generateMan onerror
task "doc:pdf", "Generate PDF documentation", -> generatePDF onerror
task "doc", "Generate all documentation", -> generateDocs onerror


## Publishing ##

publishDocs = (callback)->
  log "Uploading documentation ...", green
  exec "rsync -chr --del --stats html/ labnotes.org:/var/www/zombie/", (err, stdout, stderr)->
    log stdout, green
    callback err
task "doc:publish", "Publish documentation to site", ->
  documentPages (err)->
    onerror err
    documentSource (err)->
      onerror err
      generatePDF (err)->
        onerror err
        publishDocs onerror

task "publish", "Publish new version (Git, NPM, site)", ->
  # Run tests, don't publish unless tests pass.
  runTests (err)->
    onerror err
    # Clean up temporary files and such, want to create everything from
    # scratch, don't want generated files we no longer use, etc.
    clean (err)->
      onerror err
      fs.readFile "package.json", "utf8", (err, package)->
        package = JSON.parse(package)

        # Create a tag for this version and push changes to Github.
        log "Tagging v#{package.version} ...", green
        exec "git tag v#{package.version}", (err, stdout, stderr)->
          log stdout, green
          exec "git push --tags origin master", (err, stdout, stderr)->
            log stdout, green

        # Publish documentation, need these first to generate man pages,
        # inclusion on NPM package.
        generateDocs (err)->
          onerror err

          log "Publishing to NPM ...", green
          build (err)->
            onerror err
            exec "npm publish", (err, stdout, stderr)->
              log stdout, green
              onerror err

          # We can do this in parallel.
          publishDocs onerror
Something went wrong with that request. Please try again.