paige.coffee | |
---|---|
Require our external dependencies, including Showdown.js (the JavaScript implementation of Markdown). | _ = require "underscore"
fs = require 'fs'
path = require 'path'
showdown = require('./../vendor/showdown').Showdown
{spawn, exec} = require 'child_process'
events = require('events')
rocco = require './rocco.js'
subfiles = []
configuration = {
"title" : "Untitled",
"content_file" : "README.mdown",
"include_index" : false,
"docco_files" : null,
"header" : "Untitled",
"subheader" : "Untitled",
"background" : "bright_squares",
"output" : "docs"
} |
Read our configuration file. | read_config = (callback) ->
filename = "paige.config"
filename = process.ARGV[2] if process.ARGV[2]?
fs.readFile filename, "utf-8", (error, data) ->
if error
console.log "\nCould not find a configuration file. (default: ./paige.config)"
console.log "Create and specify a configuration file. Example:\n\n"
console.log config_template + "\n"
else
config = JSON.parse(data)
process_config(config)
callback(config) if callback |
Process the configuration file | process_config = (config={}) ->
_.map config, (value, key, list) ->
configuration[key] = value if config[key]? |
Ensure that the destination directory exists. | ensure_directory = (dir, callback) ->
exec "mkdir -p #{dir}", -> callback() |
... | copy_image = ->
desired_image = fs.readFileSync(__dirname + "/../resources/#{configuration.background}.png")
fs.writeFile "#{configuration.output}/bg.png", desired_image |
Build the main html file by reading the source Markdown file, and if necessary collecting all the filenames of our source. We will then use these names to construct the index that's shown at the top of the page. We pass the source Markdown file to Showdown, get the result, then pipe it into our templating function described above. | process_html_file = ->
source = configuration.content_file
subfiles_names = clean_file_extension(subfiles) if configuration.include_index
clean_subfiles = clean_path_names(subfiles) if configuration.include_index
fs.readFile source, "utf-8", (error, code) ->
if error
console.log "\nThere was a problem reading your the content file: #{source}"
throw error
else
content_html = showdown.makeHtml code
html = mdown_template {
content_html: content_html,
title: configuration.title,
header: configuration.header,
subheader: configuration.subheader,
include_index: configuration.include_index,
subfiles: clean_subfiles,
subfiles_names: subfiles_names
}
console.log "paige: #{source} -> #{configuration.output}/index.html"
fs.writeFile "#{configuration.output}/index.html", html |
Micro-templating, originally by John Resig, borrowed by way of Underscore.js. | template = (str) ->
new Function 'obj',
'var p=[],print=function(){p.push.apply(p,arguments);};' +
'with(obj){p.push(\'' +
str.replace(/[\r\t\n]/g, " ")
.replace(/'(?=[^<]*%>)/g,"\t")
.split("'").join("\\'")
.split("\t").join("'")
.replace(/<%=(.+?)%>/g, "',$1,'")
.split('<%').join("');")
.split('%>').join("p.push('") +
"');}return p.join('');" |
Kind of hacky, but I can't figure out another way of doing this cleanly. Will list all the files that will be used as your source file for passing onto rocco. | get_subfiles = (callback) =>
count = 0
find_files = (file, total) =>
f_path = file.substr(0,file.lastIndexOf('/')+1)
f_file = file.substr(file.lastIndexOf('/')+1)
exec "find ./#{f_path} -name '#{f_file}' -print", (error, stdout, stderr) ->
count++
subfiles = _.uniq(_.union(subfiles, stdout.trim().split("\n")))
if count >= total
callback() if callback
if _.isArray(configuration.docco_files)
_.each configuration.docco_files, (file) ->
find_files(file,configuration.docco_files.length)
else if _.isString(configuration.docco_files)
find_files(configuration.docco_files,1) |
Remove trailing path names from each file from a list | clean_path_names = (names) ->
clean_names = []
_.each names, (name) ->
clean_names.push name.substr(name.lastIndexOf('/')+1) || name
return clean_names |
Remove file extensions from each file from a list | clean_file_extension = (names) ->
clean_names = []
_.each names, (name) ->
clean_names.push name.substr(0,name.lastIndexOf('.')).substr(name.lastIndexOf('/')+1) || name
return clean_names |
Process the rocco files and wrappers if needed. | check_for_rocco = ->
if configuration.docco_files?
rocco(subfiles, configuration) |
Some necessary files | mdown_template = template fs.readFileSync(__dirname + '/../resources/paige.jst').toString()
config_template = fs.readFileSync(__dirname + '/../resources/paige.config').toString() |
Run the script | read_config (config) ->
ensure_directory configuration.output, ->
get_subfiles ->
copy_image()
process_html_file()
check_for_rocco()
|