This repository has been archived by the owner on Nov 9, 2017. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
08ff3c0
commit 66e2b9b
Showing
7 changed files
with
396 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1 @@ | |||
node_modules/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,10 @@ | |||
#!/usr/bin/env node | |||
|
|||
var path = require('path') | |||
var fs = require('fs') | |||
var lib = path.join(path.dirname(fs.realpathSync(__filename)), '../lib') | |||
|
|||
require('coffee-script') | |||
|
|||
Skeleton = require(lib + '/skeleton') | |||
new Skeleton |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,2 @@ | |||
Array::last = -> | |||
this[this.length - 1] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,95 @@ | |||
# Node.js dependencies | |||
fs = require 'fs' | |||
path = require 'path' | |||
util = require 'util' | |||
mkdirp = require 'mkdirp' | |||
|
|||
# Local dependencies | |||
Template = require './template' | |||
OptionParser = require './option_parser' | |||
|
|||
# Helpers | |||
require './helpers' | |||
|
|||
# Main class | |||
class Skeleton | |||
|
|||
@VERSION = '0.0.1' | |||
|
|||
@OPTIONS = [ | |||
['-h', '--help', 'display this help message'] | |||
['-v', '--version', 'display the version number'] | |||
['-r', '--renderer', 'use specified renderer [only ejs for now]'] | |||
] | |||
|
|||
# Bin command | |||
constructor: -> | |||
args = process.argv.splice(2) | |||
options = new OptionParser(args) | |||
|
|||
if options.help | |||
this.displayHelp() | |||
return | |||
|
|||
if options.version | |||
this.displayVersion() | |||
return | |||
|
|||
this.createProject(options.appName, options) if options.appName | |||
|
|||
createProject: (appName, opts) => | |||
template = new Template(appName, opts) | |||
for filename, content of template.files | |||
this.write filename, "#{content}\n" | |||
|
|||
write: (path, content) -> | |||
this.mkdir path, => | |||
return if path.split('/').pop() == 'empty' | |||
|
|||
fs.writeFile path, content, (err) => | |||
throw err if err | |||
this.displayLine "=> Create #{path}" | |||
|
|||
mkdir: (filename, callback=null) -> | |||
parts = filename.split('/') | |||
parts.pop() | |||
path = parts.join('/') | |||
|
|||
mkdirp path, '0755', (err) -> | |||
throw err if err | |||
callback() if callback | |||
|
|||
# Display messages | |||
displayHelp: -> | |||
rules = [] | |||
longest = 0 | |||
|
|||
for option in Skeleton.OPTIONS | |||
short = option[0] | |||
long = option[1] | |||
desc = option[2] | |||
|
|||
length = short.length + long.length | |||
longest = length if length > longest | |||
|
|||
rules.push | |||
short: short | |||
long: long | |||
desc: desc | |||
length: length | |||
|
|||
this.displayLine '\nUsage: skeleton [options] myapp\n' | |||
|
|||
for rule in rules | |||
spaces = new Array(longest - rule.length + 3).join(' ') | |||
this.displayLine "#{rule.short}, #{rule.long}#{spaces}#{rule.desc}" | |||
|
|||
displayVersion: -> | |||
this.displayLine "Skeleton version #{Skeleton.VERSION}" | |||
|
|||
displayLine: (line) -> | |||
process.stdout.write "#{line}\n" | |||
|
|||
|
|||
# Exports | |||
module.exports = Skeleton |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,25 @@ | |||
class OptionParser | |||
|
|||
constructor: (@args) -> | |||
joinedArgs = @args.join('|') | |||
|
|||
# TODO: Make the returned object completely dynamic | |||
return { | |||
help: joinedArgs.search(/-h|--help/) > -1 || args.length == 0 | |||
version: joinedArgs.search(/-v|--version/) > -1 | |||
renderer: this.getOptionValue ['-r', '--renderer'] | |||
appName: this.getOptionValue(['-a', '--appname']) || @args.last() | |||
} | |||
|
|||
# Private | |||
# Returns given flags value or null | |||
getOptionValue: (flags) -> | |||
for flag in flags | |||
index = @args.indexOf(flag) | |||
return @args[index + 1] if index > -1 | |||
|
|||
null | |||
|
|||
|
|||
# Exports | |||
module.exports = OptionParser |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,246 @@ | |||
class Template | |||
|
|||
constructor: (@appName, @opts) -> | |||
@files = this.setFiles() | |||
|
|||
setFiles: -> | |||
files = {} | |||
|
|||
# ./myapp | |||
files["#{@appName}/.gitignore"] = """ | |||
node_modules/ | |||
""" | |||
|
|||
files["#{@appName}/package.json"] = """ | |||
{ | |||
"name": "#{@appName}" | |||
, "version": "0.0.1" | |||
, "dependencies": { | |||
"express": "3.0.x" | |||
, "connect-assets": "2.1.x" | |||
, "stylus": "*" | |||
, "ejs": "*" | |||
, "coffee-script": "*" | |||
} | |||
, "scripts": { | |||
"start": "server.js" | |||
} | |||
, "engines": { | |||
"node": "0.8.0" | |||
} | |||
} | |||
""" | |||
|
|||
files["#{@appName}/README.md"] = """ | |||
# #{@appName} | |||
*** | |||
App structure generated by [Skeleton](https://github.com/EtienneLem/skeleton) | |||
""" | |||
|
|||
files["#{@appName}/server.js"] = """ | |||
require("coffee-script") | |||
require("./app/app.coffee") | |||
""" | |||
|
|||
# ./myapp/app | |||
files["#{@appName}/app/app.coffee"] = """ | |||
# Modules | |||
express = require 'express' | |||
http = require 'http' | |||
app = express() | |||
# Boot setup | |||
require("\#{__dirname}/../config/boot")(app) | |||
# Configuration | |||
app.configure -> | |||
port = process.env.PORT || 3000 | |||
if process.argv.indexOf('-p') >= 0 | |||
port = process.argv[process.argv.indexOf('-p') + 1] | |||
app.set 'port', port | |||
app.set 'views', "\#{__dirname}/views" | |||
app.set 'view engine', 'ejs' | |||
app.use express.static("\#{__dirname}/../public") | |||
app.use express.favicon() | |||
app.use express.logger('dev') | |||
app.use express.bodyParser() | |||
app.use express.methodOverride() | |||
app.use require('connect-assets')(src: "\#{__dirname}/assets") | |||
app.use app.router | |||
app.configure 'development', -> | |||
app.use express.errorHandler() | |||
# Routes | |||
require("\#{__dirname}/routes")(app) | |||
# Server | |||
http.createServer(app).listen app.get('port'), -> | |||
console.log "Express server listening on port \#{app.get 'port'} in \#{app.settings.env} mode" | |||
""" | |||
|
|||
# ./myapp/app/assets/css | |||
files["#{@appName}/app/assets/css/styles.styl"] = """ | |||
// Based on <https://github.com/heliom/stylus-utils/blob/master/styles.styl-sample> | |||
// @import "nib" | |||
// Reset --------------------------------------------------------------------- | |||
* | |||
margin: 0; padding: 0 | |||
-webkit-box-sizing: border-box | |||
-moz-box-sizing: border-box | |||
box-sizing: border-box | |||
// Base ---------------------------------------------------------------------- | |||
html | |||
font-size: 62.5% | |||
height: 100% | |||
body | |||
font-size: 16 | |||
body, legend, input, textarea, button | |||
font-family: 'Helvetica Neue' | |||
line-height: 1.4 | |||
color: #333 | |||
a:link, a:visited { color: deeppink } | |||
a:focus, a:link:hover { color: hotpink } | |||
""" | |||
|
|||
# ./myapp/app/assets/js | |||
files["#{@appName}/app/assets/js/scripts.coffee"] = """ | |||
# console.log '#{@appName}' | |||
""" | |||
|
|||
# ./myapp/app/controllers | |||
files["#{@appName}/app/controllers/application_controller.coffee"] = """ | |||
class ApplicationController | |||
# GET / | |||
@index = (req, res) -> | |||
res.render 'index', | |||
view: 'index' | |||
# Exports | |||
module.exports = (app) -> | |||
app.ApplicationController = ApplicationController | |||
""" | |||
|
|||
# ./myapp/app/helpers | |||
files["#{@appName}/app/helpers/index.coffee"] = """ | |||
fs = require 'fs' | |||
# Recursively require a folder’s files | |||
exports.autoload = autoload = (dir, app) -> | |||
fs.readdirSync(dir).forEach (file) -> | |||
path = "\#{dir}/\#{file}" | |||
stats = fs.lstatSync(path) | |||
# Go through the loop again if it is a directory | |||
if stats.isDirectory() | |||
autoload path, app | |||
else | |||
require(path)?(app) | |||
# Capitalize a string | |||
# string => String | |||
String::capitalize = () -> | |||
this.replace /(?:^|s)S/g, (a) -> a.toUpperCase() | |||
# Classify a string | |||
# application_controller => ApplicationController | |||
String::classify = (str) -> | |||
classified = [] | |||
words = str.split('_') | |||
for word in words | |||
classified.push word.capitalize() | |||
classified.join('') | |||
""" | |||
|
|||
# ./myapp/app/routes | |||
files["#{@appName}/app/routes/index.coffee"] = """ | |||
module.exports = (app) -> | |||
# Index | |||
app.get '/', app.ApplicationController.index | |||
# Error handling (No previous route found. Assuming it’s a 404) | |||
app.get '/*', (req, res) -> | |||
NotFound res | |||
NotFound = (res) -> | |||
res.render '404', status: 404, view: 'four-o-four' | |||
""" | |||
|
|||
# ./myapp/app/views | |||
files["#{@appName}/app/views/404.ejs"] = "<h1>Nothing here…</h1>" | |||
|
|||
files["#{@appName}/app/views/index.ejs"] = """ | |||
<h1>This page has been generated by <a href="https://github.com/EtienneLem/skeleton">Skeleton</a></h1> | |||
<p>Edit in <span>#{@appName}/views/index.ejs</span></p> | |||
""" | |||
|
|||
files["#{@appName}/app/views/layout.ejs"] = """ | |||
<!DOCTYPE html> | |||
<html lang="en"> | |||
<head> | |||
<meta charset="utf-8"> | |||
<title>#{@appName}</title> | |||
<%- css('styles.css') %> | |||
</head> | |||
<body data-view="<%= view %>"> | |||
<%- body %> | |||
<script> | |||
document.write('<script src=' + | |||
('__proto__' in {} ? 'http://zeptojs.com/zepto.min.js' : 'http://code.jquery.com/jquery-1.7.2.min.js') + | |||
'.js><\/script>') | |||
</script> | |||
<%- js('scripts.js') %> | |||
</body> | |||
</html> | |||
""" | |||
|
|||
# ./myapp/config | |||
files["#{@appName}/config/boot.coffee"] = """ | |||
module.exports = (app) -> | |||
# Helpers | |||
app.helpers = require "\#{__dirname}/../app/helpers" | |||
# Lib | |||
app.helpers.autoload "\#{__dirname}/../lib", app | |||
# Controllers | |||
app.helpers.autoload "\#{__dirname}/../app/controllers", app | |||
""" | |||
|
|||
# ./myapp/lib/myapp | |||
files["#{@appName}/lib/#{@appName}/my_custom_class.coffee"] = """ | |||
# module.exports = (app) -> | |||
# # Your code | |||
# | |||
# | |||
# Or if you want this to be a class | |||
# | |||
# class MyCustomClass | |||
# | |||
# constructor: (args) -> | |||
# # Your code | |||
# | |||
# # Exports | |||
# module.exports = (app) -> | |||
# app.MyCustomClass = MyCustomClass | |||
# | |||
# Usage: new app.MyCustomClass(args) | |||
""" | |||
|
|||
# ./myapp/public | |||
files["#{@appName}/public/empty"] = "" | |||
|
|||
# Return the files object | |||
files | |||
|
|||
|
|||
module.exports = Template |
Oops, something went wrong.