From 86848d9da227711b72a8b8631e5b744cd910c4ee Mon Sep 17 00:00:00 2001 From: Marcus Stong Date: Tue, 14 Jan 2014 17:24:42 -0500 Subject: [PATCH] initial commit --- .gitignore | 22 +++++ .npmignore | 14 +++ Cakefile | 125 +++++++++++++++++++++++++ History.md | 4 + LICENSE.md | 21 +++++ README.md | 8 ++ lib/hapi-server.js | 123 ++++++++++++++++++++++++ package.json | 43 +++++++++ src/hapi.plugin.coffee | 56 +++++++++++ src/hapi.test.coffee | 2 + src/hapi.tester.coffee | 4 + test/out-expected/test1.txt | 0 test/out-expected/test2.txt | 0 test/src/documents/test1.txt.uc | 0 test/src/documents/test2.txt.uppercase | 0 15 files changed, 422 insertions(+) create mode 100644 .gitignore create mode 100644 .npmignore create mode 100644 Cakefile create mode 100644 History.md create mode 100644 LICENSE.md create mode 100644 README.md create mode 100644 lib/hapi-server.js create mode 100644 package.json create mode 100644 src/hapi.plugin.coffee create mode 100644 src/hapi.test.coffee create mode 100644 src/hapi.tester.coffee create mode 100644 test/out-expected/test1.txt create mode 100644 test/out-expected/test2.txt create mode 100644 test/src/documents/test1.txt.uc create mode 100644 test/src/documents/test2.txt.uppercase diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..12152ba --- /dev/null +++ b/.gitignore @@ -0,0 +1,22 @@ +lib-cov +*.seed +*.log +*.csv +*.dat +*.out +*.pid +*.gz + +pids +logs +results + +node_modules +npm-debug.log + +test/out/ +out/ + +.idea +*.iml +.DS_Store \ No newline at end of file diff --git a/.npmignore b/.npmignore new file mode 100644 index 0000000..c64fd21 --- /dev/null +++ b/.npmignore @@ -0,0 +1,14 @@ +.travis* +Makefile +Cakefile +History.md + +src/ +out/*.tester.* +out/*.test.* +out/test/ +test/ + +.idea +*.iml +.DS_Store \ No newline at end of file diff --git a/Cakefile b/Cakefile new file mode 100644 index 0000000..35b9e29 --- /dev/null +++ b/Cakefile @@ -0,0 +1,125 @@ +# This file was originally created by Benjamin Lupton (http://balupton.com) +# and is currently licensed under the Creative Commons Zero (http://creativecommons.org/publicdomain/zero/1.0/) +# making it public domain so you can do whatever you wish with it without worry (you can even remove this notice!) +# +# If you change something here, be sure to reflect the changes in: +# - the scripts section of the package.json file +# - the .travis.yml file + + +# ----------------- +# Variables + +WINDOWS = process.platform.indexOf('win') is 0 +NODE = process.execPath +NPM = if WINDOWS then process.execPath.replace('node.exe','npm.cmd') else 'npm' +EXT = (if WINDOWS then '.cmd' else '') +APP = process.cwd() +BIN = "#{APP}/node_modules/.bin" +CAKE = "#{BIN}/cake#{EXT}" +COFFEE = "#{BIN}/coffee#{EXT}" +OUT = "#{APP}/out" +SRC = "#{APP}/src" +TEST = "#{APP}/test" + + +# ----------------- +# Requires + +pathUtil = require('path') +{exec,spawn} = require('child_process') +safe = (next,fn) -> + return (err) -> + return next(err) if err + return fn() + + +# ----------------- +# Actions + +clean = (opts,next) -> + (next = opts; opts = {}) unless next? + args = [ + '-Rf' + OUT + pathUtil.join(APP,'node_modules') + pathUtil.join(APP,'*out') + pathUtil.join(APP,'*log') + pathUtil.join(TEST,'node_modules') + pathUtil.join(TEST,'*out') + pathUtil.join(TEST,'*log') + ] + spawn('rm', args, {stdio:'inherit',cwd:APP}).on('exit',next) + +compile = (opts,next) -> + (next = opts; opts = {}) unless next? + spawn(COFFEE, ['-bco', OUT, SRC], {stdio:'inherit',cwd:APP}).on('exit',next) + +watch = (opts,next) -> + (next = opts; opts = {}) unless next? + spawn(COFFEE, ['-bwco', OUT, SRC], {stdio:'inherit',cwd:APP}).on('exit',next) + +install = (opts,next) -> + (next = opts; opts = {}) unless next? + spawn(NPM, ['install'], {stdio:'inherit',cwd:APP}).on 'exit', safe next, -> + spawn(NPM, ['install'], {stdio:'inherit',cwd:TEST}).on('exit',next) + +reset = (opts,next) -> + (next = opts; opts = {}) unless next? + clean opts, safe next, -> install opts, safe next, -> compile opts, next + +setup = (opts,next) -> + (next = opts; opts = {}) unless next? + install opts, safe next, -> + compile opts, next + +test = (opts,next) -> + (next = opts; opts = {}) unless next? + spawn(NPM, ['test'], {stdio:'inherit',cwd:APP}).on('exit',next) + +finish = (err) -> + throw err if err + console.log('OK') + + +# ----------------- +# Commands + +# clean +task 'clean', 'clean up instance', -> + clean finish + +# compile +task 'compile', 'compile our files', -> + compile finish + +# dev/watch +task 'dev', 'watch and recompile our files', -> + watch finish +task 'watch', 'watch and recompile our files', -> + watch finish + +# install +task 'install', 'install dependencies', -> + install finish + +# reset +task 'reset', 'reset instance', -> + reset finish + +# setup +task 'setup', 'setup for development', -> + setup finish + +# test +task 'test', 'run our tests', -> + test finish + +# test-debug +task 'test-debug', 'run our tests in debug mode', -> + test {debug:true}, finish + +# test-prepare +task 'test-prepare', 'prepare out tests', -> + setup finish + diff --git a/History.md b/History.md new file mode 100644 index 0000000..ab1ff3b --- /dev/null +++ b/History.md @@ -0,0 +1,4 @@ +## History + +v2.0.0 August 13, 2013 + - Initial commit \ No newline at end of file diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..c654a23 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2013 Sparks Creative Limited + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..306a772 --- /dev/null +++ b/README.md @@ -0,0 +1,8 @@ +# Hapi Server Plugin for [DocPad](http://docpad.org) + +A fully customizable Hapi server for docpad. + +## Usage (more coming soon) + +## License +Licensed under the incredibly [permissive](http://en.wikipedia.org/wiki/Permissive_free_software_licence) [MIT License](http://creativecommons.org/licenses/MIT/) \ No newline at end of file diff --git a/lib/hapi-server.js b/lib/hapi-server.js new file mode 100644 index 0000000..2e1db43 --- /dev/null +++ b/lib/hapi-server.js @@ -0,0 +1,123 @@ +module.exports = function(docpad, settings, port, hostname) { + + var Hapi = require('hapi'); + + // Declare internals + + var internals = {}; + + internals.settings = settings || {}; + + internals.port = port || 9778; + + internals.hostname = hostname || '0.0.0.0'; + + internals.serverConfig = { + files: { + relativeTo: process.cwd() + }, + cache: { + engine: 'memory' + } + }; + + // Initiate Server + + var server = new Hapi.Server(internals.port, internals.serverConfig); + + // Pre Handler + // Query .docpad.db before serving static file + + var readDatabase = function(request, reply) { + + // Query DB + + // Serve Document + + // If no document, then exit early + + internals.serveDocument = function(document) { + if (!document) { + return reply('foo'); + } + + // Content Type + + var contentType = document.outContentType || document.contentType; + + // Return content from DB + + var content = document.getOutContent(); + + if (content) { + return reply.file(content); + } + else { + return reply(); + } + }; + + if (request.params.file.indexOf('/') !== 0) { + var filePath = '/' + request.params.file; + } + + docpad.getFileByRoute(filePath, function(err,file) { + + // Check + + if (err || !file) { + return reply(); + } + + // Check if we are the desired url + // if we aren't do a permanent redirect + + var url = file.get('url'); + var cleanUrl = docpad.getUrlPathname(url); + + if ((url !== cleanUrl) && (url !== request.params.file)) { + return reply.redirect(url); + } + + // Serve the file to the user + + internals.serveDocument(file); + }); + + }; + + + // Main route for serving site + + internals.routes = []; + + var staticRoute = { + method: 'GET', + path: '/{file*}', + handler: { + directory: { + path: 'public_html/' + } + }, + config: { + cache: { + expiresIn: 60000 * 60 * 3 + }, + pre: [{ + method: readDatabase, + assign: 'queryEngine' + }] + } + }; + + internals.routes.push(staticRoute); + + if (typeof internals.settings.routes === 'array' && internals.settings.routes.length > 0) { + internals.routes.push.apply(internals.routes, internals.settings.routes); + } + + server.route(internals.routes); + + return server; + +}; \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..5c81488 --- /dev/null +++ b/package.json @@ -0,0 +1,43 @@ +{ + "name": "docpad-plugin-hapi", + "version": "2.0.1", + "description": "A fully customizable Hapi server for docpad.", + "homepage": "https://github.com/stongo/docpad-plugin-hapi", + "keywords": [ + "docpad", + "docpad-plugin", + "server", + "hapi" + ], + "author": "Marcus Stong (http://github.com/stongo)", + "maintainers": [ + "Marcus Stong (http://github.com/stongo)" + ], + "contributors": [ + "Marcus Stong (http://github.com/stongo)" + ], + "bugs": { + "url": "https://github.com/stongo/docpad-plugin-hapi/issues" + }, + "repository": { + "type": "git", + "url": "https://github.com/stongo/docpad-plugin-hapi.git" + }, + "engines": { + "node": ">=0.8", + "docpad": ">=6" + }, + "dependencies": { + "hapi": "2.x", + "wrench": "1.5.x", + "path": "~0.4.9" + }, + "devDependencies": { + "coffee-script": "~1.6.2" + }, + "main": "./out/hapi.plugin.js", + "scripts": { + "publish": "cake compile", + "test": "node ./out/hapi.test.js" + } +} diff --git a/src/hapi.plugin.coffee b/src/hapi.plugin.coffee new file mode 100644 index 0000000..d39f068 --- /dev/null +++ b/src/hapi.plugin.coffee @@ -0,0 +1,56 @@ +Hapi = require 'hapi' + +module.exports = (BasePlugin) -> + + class HapiPlugin extends BasePlugin + name: 'hapi' + + config = docpad.getConfig() + hapiConfig = config.plugins.hapi + + generateAfter: (opts, next) -> + # Prepare + docpad = @docpad + docpadConfig = docpad.getConfig() + wrench = require('wrench') + path = require('path') + config = @config + staticPath = config.path or defaults.path + + # Set out directory + # the trailing / indicates to cp that the files of this directory should be copied over + # rather than the directory itself + outPath = path.normalize "#{docpadConfig.outPath}" + staticPath = path.normalize "#{staticPath}" + + if outPath.slice(-1) is '/' + staticPath.slice(0, -1) + + staticPath = path.join process.cwd(), staticPath + + docpad.log "debug", "Copying out folder. outPath: #{outPath}, staticPath: #{staticPath}" + + wrench.copyDirRecursive outPath, staticPath, {forceDelete: true}, (err) -> + return next(err) if err + docpad.log "Done copying out folder to #{staticPath}" + return next() + + serverAfter: (opts, next) -> + # Get configs + docpad = @docpad + config = opts + port = docpad.getPort() + hostname = docpad.getHostname() + + # Shutdown Express + docpad.log('info', "Shutting down default Express server") + docpad.destroyServer() + + # Require Hapi server and start + server = require('../lib/hapi-server.js')(docpad, config, port, hostname) + + @server = server + + server.start ()-> + docpad.log('info', "Starting Hapi server") + return next() \ No newline at end of file diff --git a/src/hapi.test.coffee b/src/hapi.test.coffee new file mode 100644 index 0000000..33cb7fc --- /dev/null +++ b/src/hapi.test.coffee @@ -0,0 +1,2 @@ +# Test our plugin using DocPad's Testers +#require('docpad').require('testers').test({pluginPath: __dirname+'/..'}) \ No newline at end of file diff --git a/src/hapi.tester.coffee b/src/hapi.tester.coffee new file mode 100644 index 0000000..225b70c --- /dev/null +++ b/src/hapi.tester.coffee @@ -0,0 +1,4 @@ +# Export Plugin Tester +#module.exports = (testers) -> + # Define My Tester + #class MyTester extends testers.RendererTester \ No newline at end of file diff --git a/test/out-expected/test1.txt b/test/out-expected/test1.txt new file mode 100644 index 0000000..e69de29 diff --git a/test/out-expected/test2.txt b/test/out-expected/test2.txt new file mode 100644 index 0000000..e69de29 diff --git a/test/src/documents/test1.txt.uc b/test/src/documents/test1.txt.uc new file mode 100644 index 0000000..e69de29 diff --git a/test/src/documents/test2.txt.uppercase b/test/src/documents/test2.txt.uppercase new file mode 100644 index 0000000..e69de29