├── template ├── _template │ ├── index.html │ ├── entry.js │ ├── webpackOptionsDevServer.js │ ├── enhancedRequireOptionsDevServer.js │ ├── enhancedRequireOptionsProduction.js │ ├── index.jade │ ├── enhancedRequireOptions.js │ ├── webpackOptions.js │ ├── webpackOptionsPublish.js │ ├── loadOptions.js │ ├── publish.js │ └── devServer.js ├── app │ ├── app.js │ └── lib │ │ ├── Router.js │ │ └── Server.js ├── server.bat ├── server.sh ├── publish.bat ├── publish.sh ├── dev-server.bat ├── dev-server.sh ├── webpackOptions.js ├── enhancedRequireOptions.js ├── webpackOptionsDevServer.js ├── webpackOptionsPublish.js ├── enhancedRequireOptionsDevServer.js ├── enhancedRequireOptionsProduction.js ├── __.gitignore ├── package.json ├── README.md ├── server.js └── template.json ├── .gitattributes ├── .gitignore ├── lib ├── update.js ├── promptYesNo.js ├── writePackageJson.js ├── applyOptions.js ├── pathJoin.js ├── init.js ├── print.js ├── applyTemplate.js ├── initWebApp.js ├── askForOption.js ├── getFile.js ├── get.js ├── createWebApp.js ├── openPackageJson.js ├── create.js ├── enable.js ├── set.js ├── install.js └── applyFiles.js ├── package.json ├── README.md └── bin └── wpt.js /template/_template/index.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /template/_template/entry.js: -------------------------------------------------------------------------------- 1 | require("../app/app"); -------------------------------------------------------------------------------- /template/app/app.js: -------------------------------------------------------------------------------- 1 | document.write("It's working!"); -------------------------------------------------------------------------------- /template/server.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | node server 3 | -------------------------------------------------------------------------------- /template/server.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | node Server 3 | -------------------------------------------------------------------------------- /template/publish.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | node _template\publish 3 | -------------------------------------------------------------------------------- /template/publish.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | node _template/publish 3 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | bin/* eol=lf 3 | template/* eol=lf -------------------------------------------------------------------------------- /template/dev-server.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | node _template\devServer 3 | -------------------------------------------------------------------------------- /template/dev-server.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | node _template/devServer 3 | -------------------------------------------------------------------------------- /template/webpackOptions.js: -------------------------------------------------------------------------------- 1 | module.exports = function(options) { 2 | // add your own options here 3 | } -------------------------------------------------------------------------------- /template/enhancedRequireOptions.js: -------------------------------------------------------------------------------- 1 | module.exports = function(options) { 2 | // add your own options here 3 | } -------------------------------------------------------------------------------- /template/webpackOptionsDevServer.js: -------------------------------------------------------------------------------- 1 | module.exports = function(options) { 2 | // add your own options here 3 | } -------------------------------------------------------------------------------- /template/webpackOptionsPublish.js: -------------------------------------------------------------------------------- 1 | module.exports = function(options) { 2 | // add your own options here 3 | } -------------------------------------------------------------------------------- /template/enhancedRequireOptionsDevServer.js: -------------------------------------------------------------------------------- 1 | module.exports = function(options) { 2 | // add your own options here 3 | } -------------------------------------------------------------------------------- /template/enhancedRequireOptionsProduction.js: -------------------------------------------------------------------------------- 1 | module.exports = function(options) { 2 | // add your own options here 3 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | /template/public 3 | /template/dev-server.html 4 | /template/index.html 5 | /template/cache.manifest 6 | /template/publishedStats.json 7 | /template/node_modules 8 | -------------------------------------------------------------------------------- /lib/update.js: -------------------------------------------------------------------------------- 1 | var print = require("./print"); 2 | 3 | module.exports = function(argv) { 4 | print.red("Not implemented.\n"); 5 | print("* update - Updates a webpack-template-module.\n"); 6 | print("* update all - Updates all wtms.\n"); 7 | } -------------------------------------------------------------------------------- /template/_template/webpackOptionsDevServer.js: -------------------------------------------------------------------------------- 1 | module.exports = function(options) { 2 | options.watch = true; 3 | options.watchDelay = 200; 4 | options.debug = true; 5 | options.output = "dev.bundle.js"; 6 | options.outputPostfix = ".dev.bundle.js"; 7 | } -------------------------------------------------------------------------------- /template/_template/enhancedRequireOptionsDevServer.js: -------------------------------------------------------------------------------- 1 | var path = require("path"); 2 | module.exports = function(options) { 3 | options.resolve.alias.indexHtml = path.join(__dirname, "index.html"); 4 | options.substitutions = {}; 5 | options.substitutionFactories = {}; 6 | } -------------------------------------------------------------------------------- /template/_template/enhancedRequireOptionsProduction.js: -------------------------------------------------------------------------------- 1 | var path = require("path"); 2 | var wtpOptions = require("../package.json").webpackTemplate.options; 3 | module.exports = function(options) { 4 | options.hot = options.watch = wtpOptions.hotProductionServer; 5 | options.resolve.alias.indexHtml = path.join(__dirname, "..", "index.html"); 6 | } -------------------------------------------------------------------------------- /lib/promptYesNo.js: -------------------------------------------------------------------------------- 1 | var read = require("read"); 2 | 3 | function promptYesNo(yes, no, def) { 4 | read({ 5 | prompt: "Type 'yes' or 'no':" 6 | }, function(err, answer) { 7 | if(err) answer = def ? "yes" : "no"; 8 | if(answer == "yes") return yes && yes(); 9 | if(answer == "no") return no && no(); 10 | return promptYesNo(yes, no, def); 11 | }); 12 | } 13 | 14 | module.exports = promptYesNo; -------------------------------------------------------------------------------- /lib/writePackageJson.js: -------------------------------------------------------------------------------- 1 | var path = require("path"); 2 | var fs = require("fs"); 3 | 4 | var print = require("./print"); 5 | 6 | function writePackageJson(outputDir, packageJson, callback) { 7 | print.green("update "); 8 | print("package.json"); 9 | print.nl(); 10 | fs.writeFile( 11 | path.join(outputDir, "package.json"), 12 | JSON.stringify(packageJson, null, "\t"), 13 | "utf-8", 14 | callback 15 | ); 16 | } 17 | 18 | module.exports = writePackageJson; -------------------------------------------------------------------------------- /template/__.gitignore: -------------------------------------------------------------------------------- 1 | # will be installed by "wpt init" 2 | /publish.bat 3 | /publish.sh 4 | /dev-server.bat 5 | /dev-server.sh 6 | /server.bat 7 | /server.sh 8 | /_template 9 | 10 | # will be installed by "npm install" 11 | /node_modules 12 | 13 | # will be created by publishing or "wpt init" 14 | # you may remove these lines if you want to publish 15 | # to a git repo. (i. e. in the gh-pages branch) 16 | /publishedStats.json 17 | /public 18 | /index.html 19 | /cache.manifest 20 | /server.js -------------------------------------------------------------------------------- /template/_template/index.jade: -------------------------------------------------------------------------------- 1 | !!! html 2 | html(manifest=cacheManifestPublicPath) 3 | - var fs = require("fs"); 4 | - var path = require("path"); 5 | head 6 | - if(fs.existsSync(path.join(__dirname, "..", "app", "head.jade"))) { 7 | != require("../app/head.jade")(locals) 8 | - } 9 | script(type="text/javascript", charset="utf-8", src=assetsPublicPath) 10 | body 11 | - if(fs.existsSync(path.join(__dirname, "..", "app", "body.jade"))) { 12 | != require("../app/body.jade")(locals) 13 | - } 14 | -------------------------------------------------------------------------------- /lib/applyOptions.js: -------------------------------------------------------------------------------- 1 | function applyOptions(templateJson, templatePath, outputDir, packageJson, callback) { 2 | if(!templateJson.options) return callback(); 3 | 4 | var options = Object.keys(templateJson.options); 5 | 6 | options.forEach(function(option) { 7 | var config = templateJson.options[option]; 8 | var value = packageJson.webpackTemplate.options[option]; 9 | 10 | if(config.packageJson) { 11 | packageJson[config.packageJson] = value; 12 | } 13 | }); 14 | 15 | return callback(); 16 | } 17 | 18 | module.exports = applyOptions; -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wpt", 3 | "version": "0.5.6", 4 | "author": "Tobias Koppers @sokra", 5 | "dependencies": { 6 | "optimist": "0.3.x", 7 | "read": "1.0.x", 8 | "buffer-equal": "0.0.x", 9 | "enhanced-require": "0.4.x", 10 | "json-loader": "0.1.x" 11 | }, 12 | "bin": "./bin/wpt.js", 13 | "licenses": [ 14 | { 15 | "type": "MIT", 16 | "url": "http://www.opensource.org/licenses/mit-license.php" 17 | } 18 | ], 19 | "maintainers": [ 20 | { 21 | "name": "Tobias Koppers", 22 | "url": "https://github.com/sokra" 23 | } 24 | ] 25 | } -------------------------------------------------------------------------------- /template/_template/enhancedRequireOptions.js: -------------------------------------------------------------------------------- 1 | var path = require("path"); 2 | var wtpOptions = require("../package.json").webpackTemplate.options; 3 | module.exports = { 4 | recursive: true, 5 | hot: !!wtpOptions.hotServer, 6 | watch: !!wtpOptions.hotServer, 7 | context: path.join(__dirname, ".."), 8 | resolve: { 9 | alias: { 10 | app: path.join(__dirname, "..", "app") 11 | }, 12 | paths: [], 13 | extensions: [ 14 | "", 15 | ".node", 16 | ".coffee", 17 | ".js" 18 | ], 19 | modulesDirectories: ["modules", "node_modules"], 20 | postprocess: {} 21 | } 22 | } -------------------------------------------------------------------------------- /template/app/lib/Router.js: -------------------------------------------------------------------------------- 1 | function Router(app) { 2 | this.app = app; 3 | // Define your routes here 4 | app.get("/", this.routeGetRoot.bind(this)); 5 | } 6 | exports = module.exports = Router; 7 | 8 | Router.prototype.dispose = function() { 9 | // Perform tasks to unbind from app 10 | 11 | // remove routes 12 | for(var verb in this.app.routes) { 13 | this.app.routes[verb].length = 0; 14 | } 15 | } 16 | 17 | Router.prototype.routeGetRoot = function(req, res) { 18 | res.status = 200; 19 | res.setHeader("Content-Type", "text/html; charset=utf-8") 20 | res.end(require("raw!indexHtml"), "utf-8"); 21 | } 22 | -------------------------------------------------------------------------------- /lib/pathJoin.js: -------------------------------------------------------------------------------- 1 | var path = require("path"); 2 | module.exports = function() { 3 | var args = Array.prototype.slice.call(arguments, 0); 4 | var start = -1; 5 | args.forEach(function(arg, idx) { 6 | if(/^https?:\/\//.test(arg)) 7 | start = idx; 8 | }); 9 | if(start >= 0) 10 | return normalize(args.slice(start).join("/")); 11 | return path.join.apply(path, arguments) 12 | } 13 | 14 | function normalize(str) { 15 | str = str 16 | .replace(/\/[^\/]+\/\.\.\//g, "/") 17 | .replace(/\/\.\//g, "/") 18 | .replace(/\/[^\/]+\/\.\.$/g, "") 19 | .replace(/\/\.$/, ""); 20 | return str; 21 | } -------------------------------------------------------------------------------- /template/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "<<>>", 3 | "version": "0.1.0", 4 | "author": "<<>>", 5 | "devDependencies": { 6 | "wpt": "0.5.x", 7 | "webpack": "0.8.x", 8 | "webpack-dev-server": "0.8.x", 9 | "enhanced-require": "0.4.x", 10 | "coffee-loader": "0.2.x", 11 | "jade-loader": "0.2.x", 12 | "json-loader": "0.2.x", 13 | "raw-loader": "0.2.x", 14 | "express": "3.0.x" 15 | }, 16 | "licenses": [ 17 | { 18 | "type": "MIT", 19 | "url": "http://www.opensource.org/licenses/mit-license.php" 20 | } 21 | ], 22 | "webpackTemplate": { 23 | "version": "XXX", 24 | "modules": {}, 25 | "options": {} 26 | } 27 | } -------------------------------------------------------------------------------- /template/_template/webpackOptions.js: -------------------------------------------------------------------------------- 1 | var path = require("path"); 2 | var EventEmitter = require("events").EventEmitter; 3 | var events = new EventEmitter(); 4 | module.exports = { 5 | output: "[hash].bundle.js", 6 | outputPostfix: ".[hash].bundle.js", 7 | events: events, 8 | context: path.join(__dirname, ".."), 9 | resolve: { 10 | alias: { 11 | "app": path.join(__dirname, "..", "app") 12 | }, 13 | paths: [], 14 | extensions: [ 15 | "", 16 | ".webpack.coffee", 17 | ".webpack.js", 18 | ".web.coffee", 19 | ".web.js", 20 | ".coffee", 21 | ".js" 22 | ], 23 | modulesDirectories: ["web_modules", "modules", "node_modules"], 24 | postprocess: {} 25 | }, 26 | parse: { 27 | overwrites: {} 28 | }, 29 | postLoaders: [], 30 | preLoaders: [] 31 | }; 32 | -------------------------------------------------------------------------------- /template/_template/webpackOptionsPublish.js: -------------------------------------------------------------------------------- 1 | var path = require("path"); 2 | var wtpOptions = require("../package.json").webpackTemplate.options; 3 | module.exports = function(options) { 4 | options.outputDirectory = path.join(__dirname, "..", "public", "assets"), 5 | options.publicPrefix = wtpOptions.nodeServer ? "assets/" : "public/assets/"; 6 | options.publicPrefixCacheManifest = ""; 7 | options.minimize = true; 8 | addExtension(options.resolve.extensions, ".min.js", ".js"); 9 | addExtension(options.resolve.extensions, ".web.min.js", ".web.js"); 10 | addExtension(options.resolve.extensions, ".webpack.min.js", ".webpack.js"); 11 | } 12 | 13 | function addExtension(list, newExtension, before) { 14 | var i = list.indexOf(before); 15 | if(i < 0) return; 16 | list.splice(i, 0, newExtension); 17 | } -------------------------------------------------------------------------------- /template/README.md: -------------------------------------------------------------------------------- 1 | # <<>> 2 | 3 | ## Setup 4 | 5 | ``` text 6 | npm install 7 | ``` 8 | 9 | ## Development 10 | 11 | Execute `./dev-server.sh` (linux) or `dev-server.bat` (windows). 12 | 13 | Open `http://locahost:8081` in your browser. 14 | 15 | ## Publish 16 | 17 | Execute `./publish.sh` (linux) or `publish.bat` (windows). 18 | 19 | Execute `./server.sh` (linux) or `publish.bat` (windows). (if node.js server) 20 | 21 | Open `index.html` in your browser. (if no node.js server) 22 | 23 | Open `http://locahost:8080/` in your browser. (if node.js server) 24 | 25 | ## Notes 26 | 27 | If you want to publish to a git repo, you need to push these files: (see .gitignore) 28 | 29 | * public/* 30 | * index.html 31 | * publishedStats.json (if node.js server) 32 | * server.js (if node.js server) 33 | * cache.minifest (if cacheManifest) -------------------------------------------------------------------------------- /template/server.js: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT THIS FILE. 2 | // IT IS GENERATED BY WPT 3 | 4 | // Check "lib/Server.js" for your own code. 5 | 6 | // This file is entry point for node.js hosting providers 7 | // so it must be on this path 8 | 9 | var path = require("path"); 10 | 11 | var er = require("enhanced-require")(module, require("./_template/loadOptions")("enhancedRequire", "Production")); 12 | 13 | var Server = er("./app/lib/Server"); 14 | var stats = er("./publishedStats.json"); 15 | 16 | var server = new Server({ 17 | publishedStats: stats, 18 | publicPath: path.join(__dirname, "public") 19 | }); 20 | 21 | // TODO add Watcher here and issue server.updateOptions(...) 22 | 23 | var port = process.env.NODE_PORT && parseInt(process.env.NODE_PORT, 10) || 24 | process.env.PORT && parseInt(process.env.PORT, 10) || 25 | 8080; 26 | server.listen(port); -------------------------------------------------------------------------------- /lib/init.js: -------------------------------------------------------------------------------- 1 | var path = require("path"); 2 | 3 | var print = require("./print"); 4 | var initWebApp = require("./initWebApp"); 5 | var writePackageJson = require("./writePackageJson"); 6 | 7 | module.exports = function(argv) { 8 | 9 | var templatePath = path.join(__dirname, "..", "template"); 10 | var outputDir = process.cwd(); 11 | 12 | initWebApp(templatePath, outputDir, function(err, packageJson) { 13 | if(err) return print.red(err + "\n"); 14 | 15 | writePackageJson(outputDir, packageJson, function(err) { 16 | if(err) return print.red(err + "\n"); 17 | 18 | print.green("Done.\n"); 19 | print("The next steps are:\n"); 20 | print.bold("> npm install\n"); 21 | print.bold("> dev-server\n"); 22 | print("Then open dev-server.html in your browser.\n"); 23 | print("It should open your web app."); 24 | print.nl(); 25 | }); 26 | }); 27 | } -------------------------------------------------------------------------------- /lib/print.js: -------------------------------------------------------------------------------- 1 | function print(msg) { 2 | process.stdout.write(msg); 3 | } 4 | 5 | print.nl = function() { 6 | process.stdout.write("\n"); 7 | } 8 | 9 | // http://en.wikipedia.org/wiki/ANSI_escape_code#graphics 10 | var colors = { 11 | 'bold' : [1, 22], 12 | 'italic' : [3, 23], 13 | 'underline' : [4, 24], 14 | 'inverse' : [7, 27], 15 | 'white' : [37, 39], 16 | 'grey' : [90, 39], 17 | 'black' : [30, 39], 18 | 'blue' : [34, 39], 19 | 'cyan' : [36, 39], 20 | 'green' : [32, 39], 21 | 'magenta' : [35, 39], 22 | 'red' : [31, 39], 23 | 'yellow' : [33, 39] 24 | }; 25 | 26 | Object.keys(colors).forEach(function(name) { 27 | var begin = "\033[1m\033[" + colors[name][0] + "m"; 28 | var end = "\033[" + colors[name][1] + "m\033[22m"; 29 | print[name] = function(msg) { 30 | print(begin + msg + end); 31 | } 32 | }); 33 | 34 | module.exports = print; -------------------------------------------------------------------------------- /lib/applyTemplate.js: -------------------------------------------------------------------------------- 1 | var applyOptions = require("./applyOptions"); 2 | var applyFiles = require("./applyFiles"); 3 | var getFile = require("./getFile"); 4 | var pathJoin = require("./pathJoin"); 5 | 6 | function applyTemplate(name, templateDir, outputDir, packageJson, callback) { 7 | 8 | getFile(pathJoin(templateDir, "template.json"), function(err, templateJson) { 9 | if(err) return callback(err); 10 | 11 | templateJson = JSON.parse(templateJson); 12 | 13 | if(templateJson.name != name) 14 | return callback(new Error("module name mismatch. " + JSON.stringify(templateJson.name) + " != " + JSON.stringify(name))); 15 | 16 | applyOptions(templateJson, templateDir, outputDir, packageJson, function(err) { 17 | if(err) return callback(err); 18 | 19 | applyFiles(templateJson, templateDir, outputDir, packageJson, callback); 20 | }); 21 | 22 | }); 23 | } 24 | 25 | module.exports = applyTemplate; -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # webpack/template 2 | 3 | Scaffolding for webpack wep apps. 4 | 5 | Features: 6 | 7 | * Create web apps by scaffolding. 8 | * Update scaffolded web app if the template updates. 9 | * Include development server for just-in-time compiling (just edit the source and update your browser). 10 | * Includes all webpack features: Just require any resource (css, less, coffee, png). 11 | * Also supports a node.js Server. It is enhanced with enhanced-require, so you can use webpack features in node. 12 | * Supports hot code replacement on server side. 13 | * Install webpack-template-modules, which add some stuff to the template 14 | * i. e. jQuery, bootstrap, etc. 15 | 16 | ``` text 17 | > npm install wpt -g 18 | 19 | > wpt create 20 | appName: my-test-app 21 | author: Your Name 22 | ... 23 | 24 | > cd my-test-app 25 | 26 | > npm install 27 | 28 | > wpt install webpack/jquery-wpt-module 29 | Installing jquery wpt-module... 30 | Done. 31 | 32 | > wpt enable nodeServer 33 | Done. 34 | ... 35 | 36 | > dev-server 37 | 38 | > publish 39 | ... 40 | 41 | > server 42 | ``` 43 | -------------------------------------------------------------------------------- /lib/initWebApp.js: -------------------------------------------------------------------------------- 1 | var writePackageJson = require("./writePackageJson"); 2 | var openPackageJson = require("./openPackageJson"); 3 | 4 | function initWebApp(templatePath, outputDir, callback) { 5 | 6 | openPackageJson(outputDir, function(err, packageJson) { 7 | if(err) return callback(err); 8 | 9 | var applyTemplate = require("./applyTemplate"); 10 | 11 | applyTemplate(null, templatePath, outputDir, packageJson, function(err) { 12 | if(err) return callback(err); 13 | 14 | var modules = Object.keys(packageJson.webpackTemplate.modules); 15 | 16 | if(modules.length == 0) return callback(null, packageJson); 17 | 18 | var i = 0; 19 | (function next() { 20 | var module = modules[i++]; 21 | if(!module) return callback(null, packageJson); 22 | var moduleConfig = packageJson.webpackTemplate.modules[module]; 23 | 24 | applyTemplate(module, moduleConfig.template, outputDir, packageJson, function(err) { 25 | if(err) return callback(err); 26 | next(); 27 | }); 28 | 29 | })(); 30 | }) 31 | }); 32 | 33 | } 34 | 35 | module.exports = initWebApp; -------------------------------------------------------------------------------- /lib/askForOption.js: -------------------------------------------------------------------------------- 1 | var read = require("read"); 2 | var print = require("./print"); 3 | 4 | function askForOption(option, config, currentValue, callback) { 5 | read({ 6 | prompt: option + (config.description && " (" + config.description + ")" || "") + ":", 7 | "default": currentValue === null ? config["default"] + "" : currentValue === undefined ? "" : currentValue + "", 8 | edit: parseInt(process.versions.node.split(".")[1], 10) >= 8 9 | }, function(err, result) { 10 | if(err) return callback(err); 11 | if(config.required && result == "") { 12 | print.yellow("It's required.\n"); 13 | return askForOption(option, config, currentValue, callback); 14 | } 15 | if(config["boolean"]) { 16 | if(result == "true" || result == "yes") 17 | return callback(null, true); 18 | if(result == "false" || result == "no") 19 | return callback(null, false); 20 | print.yellow("Type 'yes' / 'true' or 'no' / 'false'!\n"); 21 | return askForOption(option, config, result, callback); 22 | } 23 | return callback(null, result); 24 | }); 25 | 26 | } 27 | 28 | module.exports = askForOption; -------------------------------------------------------------------------------- /template/app/lib/Server.js: -------------------------------------------------------------------------------- 1 | var express = require("express"); 2 | 3 | function Server(options) { 4 | this.options = options || {}; 5 | this.app = new express(); 6 | 7 | this.app.configure(this.onConfigure.bind(this)); 8 | this.initRoutes(this.app); 9 | } 10 | module.exports = Server; 11 | 12 | Server.prototype.updateOptions = function(newOptions) { 13 | for(var optName in newOptions) { 14 | this.options[optName] = newOptions[optName]; 15 | } 16 | } 17 | 18 | Server.prototype.onConfigure = function() { 19 | if(this.options.publicPath) { 20 | var oneYear = 31557600000; 21 | this.app.use(express.static(this.options.publicPath, { maxAge: oneYear })); 22 | } 23 | // uncomment the next line to use the bodyParser middleware 24 | // this.app.use(express.bodyParser()); 25 | } 26 | 27 | Server.prototype.listen = function() { 28 | return this.app.listen.apply(this.app, arguments); 29 | } 30 | 31 | Server.prototype.initRoutes = function(app) { 32 | var Router = require("./Router"); 33 | this.router = new Router(app); 34 | 35 | if(module.hot) { 36 | module.hot.accept("./Router", function() { 37 | this.router.dispose(); 38 | Router = require("./Router"); 39 | this.router = new Router(app); 40 | }.bind(this)); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /lib/getFile.js: -------------------------------------------------------------------------------- 1 | var fs = require("fs"); 2 | var print = require("./print"); 3 | var url = require("url"); 4 | 5 | module.exports = function getFile(file, callback) { 6 | if(/^https?:\/\//.test(file)) { 7 | var protocol = /^http:/.test(file) ? "http" : "https"; 8 | print.cyan("wpt " + protocol + " GET " + file + "\n"); 9 | var reqOpts = url.parse(file); 10 | reqOpts.rejectUnauthorized = false; 11 | require(protocol).get(reqOpts, function(res) { 12 | print.cyan("wpt " + protocol + " " + res.statusCode + " " + file + "\n"); 13 | if(res.statusCode == 301 || res.statusCode == 302) { 14 | if(!res.headers.location) return callback(new Error("No location header")); 15 | return getFile(res.headers.location, callback); 16 | } 17 | if(res.statusCode != 200) 18 | return callback(new Error("Response not valid (statusCode = " + res.statusCode + ")")); 19 | var buffers = []; 20 | var len = 0; 21 | res.on("data", function(b) { 22 | buffers.push(b); 23 | len += b.length; 24 | }); 25 | res.on("end", function() { 26 | var buffer = new Buffer(len); 27 | var pos = 0; 28 | for(var i = 0; i < buffers.length; i++) 29 | pos += buffers[i].copy(buffer, pos); 30 | return callback(null, buffer); 31 | }); 32 | }).on("error", function(e) { 33 | console.dir(e); 34 | return callback(e); 35 | }); 36 | return; 37 | } 38 | return fs.readFile(file, callback); 39 | } -------------------------------------------------------------------------------- /lib/get.js: -------------------------------------------------------------------------------- 1 | var path = require("path"); 2 | var fs = require("fs"); 3 | var print = require("./print"); 4 | 5 | var wptVersion = require("../package.json").version; 6 | 7 | module.exports = function(argv) { 8 | 9 | var outputDir = process.cwd(); 10 | fs.readFile(path.join(outputDir, "package.json"), "utf-8", function(err, currentPackageJson) { 11 | if(err) return onError(err); 12 | 13 | currentPackageJson = JSON.parse(currentPackageJson); 14 | 15 | if(!currentPackageJson.webpackTemplate) { 16 | print.bold("This is not a web app created by wpt.\n"); 17 | print.red("Failed!\n"); 18 | return; 19 | } 20 | 21 | var configOptions = currentPackageJson.webpackTemplate.options; 22 | 23 | if(argv._.length > 0) { 24 | var option = argv._[0]; 25 | printOption(option); 26 | } else { 27 | Object.keys(configOptions).forEach(function(option) { 28 | print(" - "); 29 | printOption(option); 30 | }); 31 | } 32 | 33 | function printOption(option, next) { 34 | var value = configOptions[option]; 35 | switch(typeof value) { 36 | case "string": 37 | print.bold(option) 38 | print(": "); 39 | print(value); 40 | print.nl(); 41 | break; 42 | case "boolean": 43 | print.bold(option); 44 | print(" "); 45 | if(value) print.green("is enabled"); 46 | else print.yellow("is disabled"); 47 | print.nl(); 48 | break; 49 | default: 50 | print(option); 51 | print.red(" has some opaque value."); 52 | print.nl(); 53 | break; 54 | } 55 | } 56 | 57 | }); 58 | function onError(err) { 59 | print.red(err + "\n"); 60 | print.red("Failed!\n"); 61 | return; 62 | } 63 | } -------------------------------------------------------------------------------- /template/_template/loadOptions.js: -------------------------------------------------------------------------------- 1 | var path = require("path"); 2 | module.exports = function(category, type) { 3 | var options = require("./"+category+"Options"); 4 | var userOptions = null, typedOptions = null, userTypedOptions = null; 5 | 6 | var config = require("../package.json").webpackTemplate; 7 | 8 | 9 | try { 10 | userOptions = require("../"+category+"Options"); 11 | } catch(e) {} 12 | try { 13 | typedOptions = require("./"+category+"Options"+type); 14 | } catch(e) {} 15 | try { 16 | userTypedOptions = require("../"+category+"Options"+type) 17 | } catch(e) {} 18 | 19 | // "modules: { 20 | // "jquery": { 21 | // installUrl: "http://webpack.github.com/wtms/jquery.json", 22 | // version: "1.8.1", 23 | // versionUrl: "https://raw.github.com/webpack/jquery-wtm/v1.8.1/package.json", 24 | // manual: true, 25 | // references: 0 26 | // } 27 | // } 28 | Object.keys(config.modules).forEach(function(module) { 29 | try { 30 | var moduleOptions = require(path.join(__dirname, "modules", module, category+"Options")); 31 | console.log("- included options from " + module + " wpt-module."); 32 | } catch(e) { return } 33 | moduleOptions(options); 34 | }); 35 | 36 | userOptions && userOptions(options); 37 | 38 | typedOptions && typedOptions(options); 39 | 40 | Object.keys(config.modules).forEach(function(module) { 41 | try { 42 | var moduleTypedOptions = require(path.join(__dirname, "modules", module, category+"Options"+type)); 43 | console.log("- included specific options from " + module + " wpt-module."); 44 | } catch(e) { return } 45 | moduleTypedOptions(options); 46 | }); 47 | 48 | userTypedOptions && userTypedOptions(options); 49 | 50 | return options; 51 | } -------------------------------------------------------------------------------- /lib/createWebApp.js: -------------------------------------------------------------------------------- 1 | var fs = require("fs"); 2 | var path = require("path"); 3 | 4 | var writePackageJson = require("./writePackageJson"); 5 | var openPackageJson = require("./openPackageJson"); 6 | var askForOption = require("./askForOption"); 7 | var applyTemplate = require("./applyTemplate"); 8 | 9 | var wptVersion = require("../package.json").version; 10 | 11 | function createWebApp(templatePath, outputDir, appName, callback) { 12 | 13 | fs.readFile(path.join(templatePath, "package.json"), "utf-8", function(err, packageJson) { 14 | if(err) return callback(err); 15 | 16 | packageJson = JSON.parse(packageJson); 17 | 18 | packageJson.webpackTemplate.version = wptVersion; 19 | packageJson.webpackTemplate.options.appName = appName; 20 | 21 | fs.readFile(path.join(templatePath, "template.json"), function(err, templateJson) { 22 | if(err) return callback(err); 23 | 24 | templateJson = JSON.parse(templateJson); 25 | 26 | var createOptions = Object.keys(templateJson.options).filter(function(name) { 27 | return templateJson.options[name].create; 28 | }); 29 | 30 | var i = 0; 31 | (function next() { 32 | var option = createOptions[i++]; 33 | if(!option) return createFiles(); 34 | askForOption(option, templateJson.options[option], null, function(err, value) { 35 | if(err) return callback(err); 36 | packageJson.webpackTemplate.options[option] = value; 37 | next(); 38 | }); 39 | })(); 40 | 41 | }); 42 | 43 | function createFiles() { 44 | applyTemplate(null, templatePath, outputDir, packageJson, function(err) { 45 | if(err) return callback(err); 46 | writePackageJson(outputDir, packageJson, function(err) { 47 | if(err) return callback(err); 48 | return callback(); 49 | }); 50 | }); 51 | } 52 | 53 | }); 54 | 55 | } 56 | 57 | module.exports = createWebApp; -------------------------------------------------------------------------------- /lib/openPackageJson.js: -------------------------------------------------------------------------------- 1 | var path = require("path"); 2 | var fs = require("fs"); 3 | 4 | var print = require("./print"); 5 | var promptYesNo = require("./promptYesNo"); 6 | var writePackageJson = require("./writePackageJson"); 7 | 8 | var wptVersion = require("../package.json").version; 9 | 10 | function openPackageJson(outputDir, callback) { 11 | fs.readFile(path.join(outputDir, "package.json"), "utf-8", function(err, packageJson) { 12 | if(err) return onError(err); 13 | packageJson = JSON.parse(packageJson); 14 | 15 | if(!packageJson.webpackTemplate) { 16 | return callback("This is not a web app created by wpt."); 17 | } 18 | 19 | if(packageJson.webpackTemplate.version != wptVersion) { 20 | print.yellow("current template version mismatches wpt version.\n"); 21 | print("current version: " + packageJson.webpackTemplate.version + "\n"); 22 | print("template version: " + wptVersion + "\n"); 23 | print.bold("If I continue I'll update your web app to version " + wptVersion + "\nShould I continue?\n"); 24 | promptYesNo(update, function() { 25 | print.red("\nFailed!\n"); 26 | print("The next steps are:\n"); 27 | print.bold("Install the correct version of wpt:\n"); 28 | print.bold("- Update your package.json dependency\n"); 29 | print.bold("> npm install\n"); 30 | print.bold("Then rerun this command.\n"); 31 | }); 32 | function update() { 33 | print.yellow("update template version: " + 34 | packageJson.webpackTemplate.version + 35 | " --> " + 36 | wptVersion + 37 | "\n"); 38 | packageJson.webpackTemplate.version = wptVersion; 39 | writePackageJson(outputDir, packageJson, function(err) { 40 | if(err) return onError(err); 41 | callback(null, packageJson); 42 | }); 43 | } 44 | } else { 45 | callback(null, packageJson); 46 | } 47 | }); 48 | } 49 | 50 | module.exports = openPackageJson; -------------------------------------------------------------------------------- /lib/create.js: -------------------------------------------------------------------------------- 1 | var path = require("path"); 2 | var fs = require("fs"); 3 | var child_process = require("child_process"); 4 | var read = require("read"); 5 | 6 | var print = require("./print"); 7 | var createWebApp = require("./createWebApp"); 8 | 9 | module.exports = function(argv) { 10 | 11 | var templatePath = path.join(__dirname, "..", "template"); 12 | 13 | var appName = argv._[0]; 14 | 15 | if(appName) return checkAppName(false); 16 | else return askForAppName(); 17 | 18 | function askForAppName() { 19 | read({ 20 | prompt: "Choose a name for your web app:", 21 | "default": appName, 22 | edit: true 23 | }, function(err, name) { 24 | if(err) { 25 | print.red("You do not want it anymore?\n"); 26 | return; 27 | } 28 | if(name == "") { 29 | print.red("Just type a name. Do not leave it empty!\n"); 30 | return askForAppName(); 31 | } 32 | appName = name; 33 | checkAppName(true); 34 | }); 35 | } 36 | 37 | function checkAppName(retry) { 38 | var outputDir = path.join(process.cwd(), appName); 39 | fs.mkdir(outputDir, function(err) { 40 | if(err) { 41 | print.red(err); 42 | print.nl(); 43 | if(retry) return askForAppName(); 44 | return; 45 | } 46 | print.green("I created the directory successfully.\n"); 47 | print.bold("Let's add some files.\n"); 48 | print.bold("We start with the package.json file.\n"); 49 | print.bold("I need some options for your web app:\n"); 50 | createWebApp(templatePath, outputDir, appName, function(err) { 51 | if(err) { 52 | print.red(err); 53 | print.nl(); 54 | if(retry) return promptYesNo(checkAppName.bind(null, true), function() {}); 55 | return; 56 | } 57 | print.green("\nDone. Your web app is created.\n"); 58 | print("The next steps are:\n"); 59 | print.bold("> cd " + path.basename(outputDir) + "\n"); 60 | print.bold("> npm install\n"); 61 | print.bold("> dev-server\n"); 62 | print("Then open dev-server.html in your browser.\n"); 63 | print("It should display: "); 64 | print.bold("It's working"); 65 | print.nl(); 66 | }); 67 | }); 68 | } 69 | } -------------------------------------------------------------------------------- /bin/wpt.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | // Local version replace global one 4 | try { 5 | var localWpt = require.resolve(require("path").join(process.cwd(), "node_modules", "wpt", "bin", "wpt.js")); 6 | if(__filename != localWpt) { 7 | return require(localWpt); 8 | } 9 | } catch(e) {} 10 | 11 | var version = require("../package.json").version; 12 | 13 | var wptIntro = 14 | ' _ _ ' + ' ___ '+ ' _____ \n' + 15 | ' | | | |' + ' | \\ '+'|_ _| \n' + 16 | ' | | ___ | |' + ' | () ) '+ ' | | \n' + 17 | ' | \\/ _ \\/ |'+' | _/ '+ ' | | \n' + 18 | ' \\ / \\ / '+' | | '+ ' | | \n' + 19 | ' \\_/ \\_/ '+' |_| '+ ' |_| ' + version + "\n" + 20 | ' Web ' + ' Pack - '+ 'Template\n'; 21 | 22 | var argv = require("optimist") 23 | .usage(wptIntro + 24 | "Commands:\n" + 25 | "* create - Create a new web app in a subdirectory.\n" + 26 | "* init - Inits a existing web app in the current directory.\n" + 27 | " It updates the template if mismatched version.\n" + 28 | "* install - Install a webpack-template-module (wtm).\n" + 29 | "* uninstall - Unistall a webpack-template-module.\n" + 30 | "* update - Updates a webpack-template-module.\n" + 31 | "* update all - Updates all wtms.\n" + 32 | "* enable - Enable an boolean option.\n" + 33 | "* disable - Disable an boolean option.\n" + 34 | "* get - Reads the value of an option.\n" + 35 | "* set - Sets the value of an string option.\n" + 36 | "") 37 | 38 | .demand(1) 39 | .argv; 40 | 41 | var cmd = argv._.shift(); 42 | 43 | console.log(wptIntro); 44 | 45 | switch(cmd) { 46 | case "create": return require("../lib/create")(argv); 47 | case "init": return require("../lib/init")(argv); 48 | case "install": return require("../lib/install")(argv); 49 | case "uninstall": return require("../lib/uninstall")(argv); 50 | case "update": return require("../lib/update")(argv); 51 | case "enable": return require("../lib/enable")(argv, true); 52 | case "disable": return require("../lib/enable")(argv, false); 53 | case "get": return require("../lib/get")(argv); 54 | case "set": return require("../lib/set")(argv); 55 | } 56 | 57 | -------------------------------------------------------------------------------- /template/_template/publish.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | var fs = require("fs"); 4 | var path = require("path"); 5 | 6 | fs.exists = fs.exists || path.exists; // node 0.6 support 7 | fs.existsSync = fs.existsSync || path.existsSync; // node 0.6 support 8 | 9 | var er = require("enhanced-require")(module, require("./loadOptions")("enhancedRequire", "Publish")); 10 | var options = require("./loadOptions")("webpack", "Publish"); 11 | var webpack = require("webpack"); 12 | var formatOutput = require("webpack/lib/formatOutput"); 13 | var indexTemplate = er("./index.jade"); 14 | 15 | var rootDir = path.join(__dirname, ".."); 16 | 17 | var config = require("../package.json").webpackTemplate; 18 | 19 | webpack(path.join(__dirname, "entry.js"), options, function(err, stats) { 20 | if(err) throw err; 21 | console.log(formatOutput(stats, { 22 | context: options.context, 23 | colors: true 24 | })); 25 | 26 | // generate the index.html file 27 | var templateParams = { 28 | assetsPublicPath: 29 | options.publicPrefix + 30 | options.output.replace(/\[hash\]/g, stats.hash), 31 | cacheManifestPublicPath: config.options.cacheManifest && 32 | (options.publicPrefixCacheManifest + "cache.manifest") || null, 33 | type: "publish", 34 | config: config.options, 35 | }; 36 | fs.writeFile( 37 | path.join(rootDir, "index.html"), 38 | indexTemplate(templateParams), 39 | throwOnErr); 40 | 41 | // store stats in json format 42 | // it may be used by external applications 43 | fs.writeFile( 44 | path.join(rootDir, "publishedStats.json"), 45 | JSON.stringify(stats, null, "\t"), "utf-8", 46 | throwOnErr); 47 | 48 | if(config.options.cacheManifest) { 49 | // generate a cache manifest 50 | var manifest = ["CACHE MANIFEST", "# " + stats.hash, "", "CACHE:"]; 51 | for(var file in stats.fileSizes) { 52 | manifest.push( 53 | options.publicPrefix + 54 | file.replace(/\[hash\]/g, stats.hash)); 55 | } 56 | manifest.push("", "NETWORK:", "*"); 57 | fs.writeFile( 58 | path.join(rootDir, "cache.manifest"), 59 | manifest.join("\n"), "utf-8", 60 | throwOnErr); 61 | } 62 | }); 63 | function throwOnErr(err) { 64 | if(err) throw err; 65 | } -------------------------------------------------------------------------------- /template/_template/devServer.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | var fs = require("fs"); 4 | var path = require("path"); 5 | 6 | fs.exists = fs.exists || path.exists; // node 0.6 support 7 | fs.existsSync = fs.existsSync || path.existsSync; // node 0.6 support 8 | 9 | var WebpackDevServer = require("webpack-dev-server"); 10 | var er = require("enhanced-require")(module, require("./loadOptions")("enhancedRequire", "DevServer")); 11 | var options = require("./loadOptions")("webpack", "DevServer"); 12 | 13 | var indexTemplate = er("./index.jade"); 14 | 15 | var config = require("../package.json").webpackTemplate; 16 | 17 | var hasServer = fs.existsSync(path.join(__dirname, "..", "app", "lib", "Server.js")); 18 | 19 | var devPort = process.env.PORT && parseInt(process.env.PORT, 10) || 8081; 20 | 21 | options.publicPrefix = (hasServer ? "http://localhost:8081" : "") + "/assets/"; 22 | 23 | // generate the dev-server.html file 24 | var templateParams = { 25 | assetsPublicPath: 26 | options.publicPrefix + 27 | options.output, 28 | cacheManifestPublicPath: null, 29 | type: "dev-server", 30 | config: config.options 31 | }; 32 | var indexHtml = indexTemplate(templateParams); 33 | 34 | er.options.substitutions[er.resolve("raw!indexHtml")] = indexHtml; 35 | 36 | var Server = null; 37 | if(hasServer) 38 | Server = er("../app/lib/Server"); 39 | 40 | function MyWebpackDevServer() { 41 | WebpackDevServer.apply(this, arguments); 42 | } 43 | 44 | MyWebpackDevServer.prototype = Object.create(WebpackDevServer.prototype); 45 | 46 | if(!Server) { 47 | console.log("- Serving static content."); 48 | MyWebpackDevServer.prototype.serveContent = function(req, res) { 49 | res.status = 200; 50 | res.setHeader("Content-Type", "text/html; charset=utf-8") 51 | res.end(indexHtml, "utf-8"); 52 | } 53 | } else { 54 | console.log("- Starting your node.js server on port 8080."); 55 | var server = new Server(); 56 | server.listen(8080); 57 | } 58 | 59 | console.log("- dev-server on port " + devPort + "."); 60 | console.log("> Open http://localhost:" + devPort + "/ in your browser."); 61 | console.log("\n"); 62 | var devServer = new MyWebpackDevServer(path.join(__dirname, "entry.js"), { 63 | contentUrl: "http://localhost:8080/", 64 | webpack: options 65 | }); 66 | devServer.listen(devPort); 67 | -------------------------------------------------------------------------------- /lib/enable.js: -------------------------------------------------------------------------------- 1 | var path = require("path"); 2 | var fs = require("fs"); 3 | 4 | var print = require("./print"); 5 | var promptYesNo = require("./promptYesNo"); 6 | var writePackageJson = require("./writePackageJson"); 7 | var initWebApp = require("./initWebApp"); 8 | 9 | var wptVersion = require("../package.json").version; 10 | 11 | module.exports = function(argv, enable) { 12 | 13 | var templatePath = path.join(__dirname, "..", "template"); 14 | 15 | var outputDir = process.cwd(); 16 | 17 | initWebApp(templatePath, outputDir, function(err, packageJson) { 18 | if(err) return print.red(err + "\n"); 19 | 20 | fs.readFile(path.join(templatePath, "template.json"), function(err, templateJson) { 21 | if(err) return print.red(err + "\n"); 22 | 23 | templateJson = JSON.parse(templateJson); 24 | 25 | var configOptions = packageJson.webpackTemplate.options; 26 | var endis = (enable ? "enable" : "disable"); 27 | if(argv._.length > 0) { 28 | var option = argv._.shift(); 29 | if(typeof configOptions[option] != "boolean" && 30 | typeof configOptions[option] != "undefined") { 31 | return onError("Please use 'wpt " + endis + "' only for boolean options"); 32 | } 33 | if(typeof configOptions[option] == "undefined") { 34 | print.yellow("A new option will be created. Are you sure?\n"); 35 | promptYesNo(exec, print.red.bind(null, "Aborted.")); 36 | } else exec(); 37 | 38 | function exec() { 39 | configOptions[option] = enable; 40 | onDone(templateJson.options[option] ? templateJson.options[option].requireInit : true); 41 | } 42 | } else { 43 | return print.red("Please specify a option to " + endis + ": 'wpt " + endis + "