squareboy v0.1.0
= |ˆڡˆ|ᕗ
== squareboy
== Source
$ git clone git@github.com:harsha-mudi/squareboy.git
link:https://github.com/harsha-mudi/squareboy[github]
~~ 400 lines
== Install
npm install squareboy
== About
squareboy removes the tedious aspects of web-dev. +
Each website/webapp is represented by a .tasklist.coffee file. +
It comes with a websocket/proxy/static server. +
Also, you never have to deal with bower.json or package.json with squareboy.
You can use squareboy as a build server which sends out websocket notifications for live reloading for example. +
== Running
squareboy foobar.tasklist.coffee --key value ...
A tasklist file is watched. + squareboy restarts the process, when it changes. + Manual restart is triggerred with "Enter" keypress on your terminal +
== A Blog Tasklist
source,javascript
require "squareboy"
comment following below will describe a squareboy export
gulp knowledge is assumed
squareboy exports globals
each global may export another global instead returning
source, dist are provided for folder management
source folder: "lexical" dist folder: "/Users/harsha/foobar/lexical"
those give out $source, $dist globals
which can take a dir or a file
for e in "css", "fonts", "images","data" $source.dir(e) $dist.dir(e)
for e in "contents", "templates" $source.dir(e)
file adds folder + first-arg
$source.file("appfile", "app/main.js")
abs_file doesn't add it
$source.abs_file("bundlefile", "bundle.js") $source.file("lessfile", "css/styles.less")
last argument is a glob pattern
$dist.abs_dir("vendor", "vendor", null); $dist.dir("js"); $dist.dir("tags"); $dist.abs_dir("html", $dist.folder, "*.html");
$args is command line options parsed by yargs
opts = min : (false || $args.min)
never deal with bower.json or package.json or
their command-line counterparts directly
npm "gulp-less" npm "gulp-rename" npm "gulp-minify-css" npm "gulp-size"
this gives you $less, $rename ...
$ is short for gulp
from for src
to for dest
log for logging
$if is gulp-if
__ is for ignoring errors with plumber
$.task "css", ->
# File checking helper
exists $source.lessfile
from $source.lessfile
.pipe __()
.pipe $less()
.pipe $rename
suffix: '.less'
.pipe $if(opts.min, $minify_css())
.pipe $if(opts.min, $rename({ suffix: '.min' }))
.pipe $if(opts.min, $size())
.pipe to($dist.css)
npm "browserify" npm "gulp-uglify" npm "gulp-size"
alternate import names
npm "vinyl-buffer", "buffer" npm "vinyl-source-stream", "source_stream"
$.task 'browserify', -> if exists($source.appfile, false) $browserify() .add($source.appfile) .bundle() .pipe $source_stream($source.bundlefile) .pipe $buffer() .pipe $if(opts.min, $uglify()) .pipe $if(opts.min, $rename({ suffix: '.min' })) .pipe $if(opts.min, $size()) .pipe to($dist.js) else log "can't browserify"
npm "gulp-clean"
$.task 'clean', ->
from($dist.files) .pipe print() .pipe $clean({force: true})
$.task 'mkdist', ->
# helper
$dist.mkdirs
npm "gulp-imagemin"
$.task 'copy', ->
every directory added to source also adds a _files glob pattern
from($source.data_files) .pipe to $dist.data
from($source.images_files) .pipe $if(opts.min, $imagemin()) .pipe to($dist.images)
from($source.fonts_files) .pipe to $dist.fonts
$task is current task
this is for granular livereloading
if $task != "default" log("committing copy") $server.io.emit("change", {type: "copy"})
$.task 'watch', -> watchers = [ ($.watch $source.app_files, 'lint', 'browserify', 'copy') , ($.watch $source.css_files, 'css', 'copy') , ($.watch $source.fonts_files, 'copy') , ($.watch $source.data_files, 'copy') , ($.watch $source.images_files, 'copy') , ($.watch $source.templates_files, "default") , ($.watch $source.contents_files, "default") ]
for w in watchers
w.on('change', (e) ->
log("file #{e.path} was #{e.type}")
$server.io.emit("change", e))
npm "gulp-jshint"
$.task 'lint', -> exists $source.jshintfile from $source.app_files .pipe $jshint() .pipe $jshint.reporter('default')
npm "marked"
markdown_parser = (text) -> $marked.setOptions({ renderer: new $marked.Renderer() gfm: true tables: true breaks: false pedantic: true sanitize: true smartLists: true smartpants: true }) $marked(text)
$.task 'compile', ->
# contents makes a data structure $contents
# out of disk files
# this makes it easier to analyse, group and query
return contents(markdown: markdown_parser)
npm "nunjucks"
this mutex lock makes sure that the install commands
are run before gulp
$mutex.lock -> env = new $nunjucks.Environment(new $nunjucks.FileSystemLoader($source.templates)); global"$nunjucks" = env; $mutex.unlock()
$.task "single-page", 'compile', ->
# toStr will Stringify an object
writeFile($dist.data + "/content.json", toStr($contents))
lodash has a neat query language inbuilt
$.task 'tags', 'compile', -> tags = [] .map($contents, (i) -> if i.tags then tags.push(i.tags) else null) .map(.unique(.flatten(tags)), (t) -> taggedcontents = .where($contents, {tags: t}); sortedposts = .sortBy(tagged_contents, "title") $nunjucks.render("tags.nunjucks", {tag: t, posts: sorted_posts, opts: opts}, (err, html) -> if err error(err) process.exit(1) else writeFile($dist.html + "/tags/" + t + ".html", html)))
writeFile is a simple helper
$.task 'posts', 'compile', -> _.map($contents, (i) -> $nunjucks.render("post.nunjucks", {post: i, opts: opts}, (err, html) -> if err error(err) process.exit(1) else writeFile($dist.html + "/" + i.filename + ".html", html)))
$.task 'index', 'compile', 'single-page', 'posts', 'tags', -> sortedposts = .sortBy($contents, "title") sortedposts = .filter(sortedposts, (p) -> not .has(p,"category")) $nunjucks.render("index.nunjucks", {posts: sorted_posts, opts: opts}, (err, html) -> if err error(err) process.exit(1) else writeFile($dist.html + "/index.html", html))
started by convention
$.task 'default', 'mkdist', 'clean', -> $.start 'copy', 'css', 'browserify', "index", (err) -> if err error(err) else log("committing default") $server.io.emit("change", {type:"commit"})
npm 'gulp-local-screenshots', "screenshots"
$.task 'screens', -> from $dist.html_files .pipe($screenshots({ port: "8000", path: $dist.html, width: '1600', '1000', '480', '320', folder: ($dist.html + "/screenshots") })) .pipe to($dist.html)
start watching
$.start('watch')
$.task 'serve', ->
# server is a static and websocket server
port = $args.port || "8080"
server dir: $dist.folder, port: port
# refresh
$server.io.emit("change", {type: "start"})
$server.app.post("/gulp", (req,res) ->
# parser for foo: bar baz
# rargs to parse `a:b,c`
rargs(req.body.gulp)
$.start $rargs[0], (err) ->
if err
error(err)
res.send("ok"))
$.task 'dump', -> dump($server.args)
start server
$.start('serve')
forget about bower.json
bower directory: $dist.vendor, cwd: $dist.folder, packages: "jquery", "sammy"
debugging
dump($dist) dump($source)
starts gulp
prePress()
== How is squareboy different ?
squareboy has no forced folder conventions. + squareboy is like rake and make. +
squareboy does not need a plugin system. + use gulp, npm directly. +
squareboy can do what jekyll does. + squareboy does not need a query language like docpad. + use lodash. +
== License
MIT
== Status
Beta
== Credits