diff --git a/.gitignore b/.gitignore index b227694..e9b9bbf 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,12 @@ npm-debug.log # Ignore mocha test data test/data +# Ignore example data +example/node_modules +example/npm-debug.log +example/www_static/css/lib +example/www_static/js/lib + # Ignore binary files *.o *.class diff --git a/example/example.js b/example/example.js new file mode 100644 index 0000000..797a478 --- /dev/null +++ b/example/example.js @@ -0,0 +1,142 @@ + +var express = require('express'); +var async = require('async'); +var path = require('path'); +var assets = require('../lib/node-ff-assets'); + +var assetsConfig = { + // Map from uri paths to file systems paths. + linkMapping : { + '/static/module/bootstrap/': 'node_modules/bootstrap/dist/', + '/static/module/flot/': 'node_modules/flot/', + '/static/': 'www_static/', + }, + linkSourcesCss : [ + '/static/module/bootstrap/css/bootstrap.css', + ], + linkSourcesJs : [ + '/static/js/lib/jquery-2.1.3/jquery.js@http://code.jquery.com/jquery-2.1.3.js', + '/static/module/bootstrap/js/bootstrap.js', + '/static/module/flot/jquery.flot.js', + '/static/module/flot/jquery.flot.resize.js', + '/static/module/flot/jquery.flot.pie.js', + '/static/js/lib/angularjs-1.4.0-b4/angular.js@https://code.angularjs.org/1.4.0-beta.4/angular.js', + '/static/js/lib/angularjs-1.4.0-b4/angular-route.js@https://code.angularjs.org/1.4.0-beta.4/angular-route.js', + '/static/js/lib/angularjs-1.4.0-b4/angular-resource.js@https://code.angularjs.org/1.4.0-beta.4/angular-resource.js', + '/static/js/lib/angularjs-1.4.0-b4/angular-touch.js@https://code.angularjs.org/1.4.0-beta.4/angular-touch.js', + ], +} + +//callback helper to return an assembler config per asset type +function createBuildConfig(type) { + return function(callback) { + var singleResult = 'false' != process.env.DEV_ASSETS_SINGLE_RESULT; + console.info('Asset single page result: '+singleResult+' for: '+type); + if (type == 'css') { + callback(null,{ + linkMapping: assetsConfig.linkMapping, + linkTargetSingleResult: singleResult, + linkTarget: '/static/css/lib/assets.css', + linkSources: assetsConfig.linkSourcesCss, + assetType: type, + }); + } else { + callback(null, { + downloadStartDelay: 200, + linkTargetSingleResult: singleResult, + linkMapping: assetsConfig.linkMapping, + linkTarget: '/static/js/lib/assets.js', + linkSources: assetsConfig.linkSourcesJs, + assetType: type, + }); + } + } +} + +function buildAssets(server,callbackDone) { + assets.build({ + assets: { + js: { + configCreate: createBuildConfig('js'), + configFill: function (config, callback) { + async.series([ + assets.factory.lib.async.pushLinkSources(config, '/static/js/', 'www_static/js/'), + assets.factory.lib.async.pushLinkSources(config, '/static/js/controller/', 'www_static/js/controller/'), + ],callback); + }, + }, + css: { + configCreate: createBuildConfig('css'), + configFill: function (config, callback) { + async.series([ + assets.factory.lib.async.pushLinkSources(config, '/static/css/', 'www_static/css/'), + ],callback); + + }, + assemblerCreate: function (assemblerConfig, callback) { + callback(null,new assets.AssetAssembler(assemblerConfig,assets.factory.assembler.constructor.readFileMinify())); + }, + }, + }, + assemblerFill: function (assembler, callback) { + var serverResultKey = 'ff_assets_'+assembler.config.assetType; + assembler.on ('log', assets.factory.assembler.event.log.console(assembler.config.assetType)); + assembler.on ('result', assets.factory.assembler.event.result.objectSet(server,serverResultKey)); + callback(); + }, + },callbackDone); +} + +function renderTemplate(server) { + return function (req, res, next) { + if (req.params.sub) { + res.render('include/' + req.params.page + '/' + req.params.sub); + } else { + res.render('include/' + req.params.page); + } + } +} + +function renderPage(server) { + return function (req, res, next) { + res.render('index', { + includeCssFiles: server.get('ff_assets_css'), + includeJsFiles: server.get('ff_assets_js'), + }); + } +} + +function sendRedirect() { + return function (req, res, next) { + res.redirect('/example-ui'); + } +} + + +var server = express(); +buildAssets(server,function(err) { + if (err) { + throw err; + } + console.info('Server assets done.'); + + server.set('view engine', 'jade'); + server.set('views', path.join(__dirname, 'www_views')); + server.use('/static',express.static(path.join(__dirname,'www_static'))); + server.use('/static/module/bootstrap',express.static(path.join(__dirname,'node_modules/bootstrap/dist'))); + server.use('/static/module/flot',express.static(path.join(__dirname,'node_modules/flot'))); + + server.get('/example-ui/include/:page', renderTemplate()); + server.get('/example-ui/include/:page/:sub', renderTemplate()); + server.get('/', sendRedirect()); + server.get('/example-ui', renderPage(server)); + server.get('/example-ui/*', renderPage(server)); // must be last; for HTML5 history + console.info('Server config done.'); + + server.listen(8080); + console.info('Server started on port 8080'); +}); + +module.exports = { + version: 'example' +}; diff --git a/example/package.json b/example/package.json new file mode 100644 index 0000000..229225f --- /dev/null +++ b/example/package.json @@ -0,0 +1,17 @@ +{ + "name": "node-ff-assets-example", + "description": "node-ff-assets-example", + "version": "1.0.0", + "private": true, + "scripts": { + "start": "node example.js" + }, + "dependencies": { + "async": "~0.9.0", + "bootstrap": "^3.3.2", + "express": "~4.11.0", + "flot": "^0.8.0-alpha", + "jade": "^1.9.2", + "node-ff-assets": "^0.2.0" + } +} diff --git a/example/www_static/css/boot.css b/example/www_static/css/boot.css new file mode 100644 index 0000000..803eb92 --- /dev/null +++ b/example/www_static/css/boot.css @@ -0,0 +1,140 @@ + +body { + margin-top: 100px; + background-color: #222; +} + +@media ( min-width :768px) { + body { + margin-top: 50px; + } +} + +#wrapper { + padding-left: 0; +} + +#page-wrapper { + width: 100%; + padding: 0; + background-color: #fff; +} + +.huge { + font-size: 50px; + line-height: normal; +} + +@media ( min-width :768px) { + #wrapper { + padding-left: 225px; + } + #page-wrapper { + padding: 10px; + } +} + +/* Top Navigation */ +.top-nav { + padding: 0 15px; +} + +.top-nav>li { + display: inline-block; + float: left; +} + +.top-nav>li>a { + padding-top: 15px; + padding-bottom: 15px; + line-height: 20px; + color: #999; +} + +.top-nav>li>a:hover, .top-nav>li>a:focus, .top-nav>.open>a, .top-nav>.open>a:hover, + .top-nav>.open>a:focus { + color: #fff; + background-color: #000; +} + +.top-nav>.open>.dropdown-menu { + float: left; + position: absolute; + margin-top: 0; + border: 1px solid rgba(0, 0, 0, .15); + border-top-left-radius: 0; + border-top-right-radius: 0; + background-color: #fff; + -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, .175); + box-shadow: 0 6px 12px rgba(0, 0, 0, .175); +} + +.top-nav>.open>.dropdown-menu>li>a { + white-space: normal; +} + +ul.message-dropdown { + padding: 0; + max-height: 250px; + overflow-x: hidden; + overflow-y: auto; +} + +li.message-preview { + width: 275px; + border-bottom: 1px solid rgba(0, 0, 0, .15); +} + +li.message-preview>a { + padding-top: 15px; + padding-bottom: 15px; +} + +li.message-footer { + margin: 5px 0; +} + +ul.alert-dropdown { + width: 200px; +} + +/* Side Navigation */ +@media ( min-width :768px) { + .side-nav { + position: fixed; + top: 51px; + left: 225px; + width: 225px; + margin-left: -225px; + border: none; + border-radius: 0; + overflow-y: auto; + background-color: #222; + } + .side-nav>li>a { + width: 225px; + } + .side-nav li a:hover, .side-nav li a:focus { + outline: none; + background-color: #000 !important; + } +} + +.side-nav>li>ul { + padding: 0; +} + +.side-nav>li>ul>li>a { + display: block; + padding: 10px 15px 10px 38px; + text-decoration: none; + color: #999; +} + +.side-nav>li>ul>li>a:hover { + color: #fff; +} + +.huge { + font-size: 40px; +} diff --git a/example/www_static/css/flot.css b/example/www_static/css/flot.css new file mode 100644 index 0000000..76b6b11 --- /dev/null +++ b/example/www_static/css/flot.css @@ -0,0 +1,10 @@ + +.flot-chart { + display: block; + height: 400px; +} + +.flot-chart-content { + width: 100%; + height: 100%; +} diff --git a/example/www_static/css/panel.css b/example/www_static/css/panel.css new file mode 100644 index 0000000..7e97652 --- /dev/null +++ b/example/www_static/css/panel.css @@ -0,0 +1,56 @@ + +.panel-green { + border-color: #5cb85c; +} + +.panel-green .panel-heading { + border-color: #5cb85c; + color: #fff; + background-color: #5cb85c; +} + +.panel-green a { + color: #5cb85c; +} + +.panel-green a:hover { + color: #3d8b3d; +} + +.panel-red { + border-color: #d9534f; +} + +.panel-red .panel-heading { + border-color: #d9534f; + color: #fff; + background-color: #d9534f; +} + +.panel-red a { + color: #d9534f; +} + +.panel-red a:hover { + color: #b52b27; +} + +.panel-yellow { + border-color: #f0ad4e; +} + +.panel-yellow .panel-heading { + border-color: #f0ad4e; + color: #fff; + background-color: #f0ad4e; +} + +.panel-yellow a { + color: #f0ad4e; +} + +.panel-yellow a:hover { + color: #df8a13; +} + + diff --git a/example/www_static/css/style.css b/example/www_static/css/style.css new file mode 100644 index 0000000..745a426 --- /dev/null +++ b/example/www_static/css/style.css @@ -0,0 +1,44 @@ + +#wrapper { + padding-right: 0px; + padding-left: 0px; +} + +.side-nav { + right: 0px; + left: 0px; +} + +.btn { + margin-right: 10px; +} + +.navbar-footer { + margin-left: 45%; +} + +.navbar-toggle { + display: none; +} + +.navbar-brand { + background-color: #C110D8; +} + +.navbar-inverse .navbar-brand { + color: #FFFFFF; +} + +.navbar-inverse .navbar-brand:focus { + outline: none; +} + +.navbar-inverse .navbar-brand:hover { + background-color: #0F9A28; + outline: none; +} + +.navbar-inverse { + background-color: #C110D8; +} + diff --git a/example/www_static/js/controller/page-bar.js b/example/www_static/js/controller/page-bar.js new file mode 100644 index 0000000..0f26769 --- /dev/null +++ b/example/www_static/js/controller/page-bar.js @@ -0,0 +1,10 @@ + +pageRouteInit.push(function ($routeProvider, $locationProvider) { + $routeProvider.when('/example-ui/bar', { + templateUrl: '/example-ui/include/bar', + controller: PageFoo + }); +}); + +function PageFoo($scope, $http) { +} diff --git a/example/www_static/js/controller/page-foo.js b/example/www_static/js/controller/page-foo.js new file mode 100644 index 0000000..3365794 --- /dev/null +++ b/example/www_static/js/controller/page-foo.js @@ -0,0 +1,10 @@ + +pageRouteInit.push(function ($routeProvider, $locationProvider) { + $routeProvider.when('/example-ui/foo', { + templateUrl: '/example-ui/include/foo', + controller: PageFoo + }); +}); + +function PageFoo($scope, $http) { +} diff --git a/example/www_static/js/controller/page-index.js b/example/www_static/js/controller/page-index.js new file mode 100644 index 0000000..9850c61 --- /dev/null +++ b/example/www_static/js/controller/page-index.js @@ -0,0 +1,10 @@ + +pageRouteInit.push(function ($routeProvider, $locationProvider) { + $routeProvider.when('/example-ui', { + templateUrl: '/example-ui/include/index', + controller: PageIndex + }); +}); + +function PageIndex($scope, $http) { +} diff --git a/example/www_static/js/example-app.js b/example/www_static/js/example-app.js new file mode 100644 index 0000000..3657458 --- /dev/null +++ b/example/www_static/js/example-app.js @@ -0,0 +1,13 @@ +'use strict'; + +var pageRouteInit = []; + +angular.module('exampleUI', ['ngRoute']). + config(['$routeProvider', '$locationProvider', function($routeProvider, $locationProvider) { + for (var i = 0; i < pageRouteInit.length; i++) { + pageRouteInit[i]($routeProvider, $locationProvider); + } + $routeProvider.otherwise({ redirectTo: '/example-ui' }); + $locationProvider.html5Mode(true); + }]); + diff --git a/example/www_views/include/bar.jade b/example/www_views/include/bar.jade new file mode 100644 index 0000000..867ed58 --- /dev/null +++ b/example/www_views/include/bar.jade @@ -0,0 +1,5 @@ +div + h2 Bar + + p Welcome to bar. + diff --git a/example/www_views/include/foo.jade b/example/www_views/include/foo.jade new file mode 100644 index 0000000..d5fe452 --- /dev/null +++ b/example/www_views/include/foo.jade @@ -0,0 +1,4 @@ +div + h2 Foo + + p Welcome to foo. diff --git a/example/www_views/include/index.jade b/example/www_views/include/index.jade new file mode 100644 index 0000000..0848c16 --- /dev/null +++ b/example/www_views/include/index.jade @@ -0,0 +1,5 @@ +div + h2 Example UI Index + + p Welcome + p Make your self at home. diff --git a/example/www_views/include/layout/footer.jade b/example/www_views/include/layout/footer.jade new file mode 100644 index 0000000..e47cd5d --- /dev/null +++ b/example/www_views/include/layout/footer.jade @@ -0,0 +1,3 @@ +nav(class='navbar') + div(class='navbar-footer') + Example footer \ No newline at end of file diff --git a/example/www_views/include/layout/header.jade b/example/www_views/include/layout/header.jade new file mode 100644 index 0000000..72fae6e --- /dev/null +++ b/example/www_views/include/layout/header.jade @@ -0,0 +1,10 @@ +nav(class='navbar navbar-inverse navbar-fixed-top',role='navigation') + div(class='navbar-header') + button(type='button',class='navbar-toggle',data-toggle='collapse',data-target='.navbar-ex1-collapse') + span(class='sr-only') Toggle navigation + span(class='icon-bar') + span(class='icon-bar') + span(class='icon-bar') + a(class='navbar-brand',href='/example-ui') Home + a(class='navbar-brand',href='/example-ui/foo') Foo + a(class='navbar-brand',href='/example-ui/bar') Bar \ No newline at end of file diff --git a/example/www_views/index.jade b/example/www_views/index.jade new file mode 100644 index 0000000..ec431c6 --- /dev/null +++ b/example/www_views/index.jade @@ -0,0 +1,21 @@ +doctype html +html(lang='en',ng-app='exampleUI') + head + base(href='/example-ui') + title='Example UI' + meta(charset='UTF-8') + meta(http-equiv='X-UA-Compatible' content='IE=edge') + meta(name='viewport' content='width=device-width, initial-scale=1') + meta(name='keywords' content='Example UI') + each cssFile in includeCssFiles + link(rel='stylesheet' href='#{cssFile}') + body + div(id='wrapper') + div(ng-include='\'/example-ui/include/layout/header\'') + div(id='page-wrapper') + div(id='container-fluid') + div(ng-view) + div(ng-include='\'/example-ui/include/layout/footer\'') + each jsFile in includeJsFiles + script(src='#{jsFile}') + diff --git a/test/test-asset-assembler.js b/test/test-asset-assembler.js index c4ccf7c..c0d9c38 100644 --- a/test/test-asset-assembler.js +++ b/test/test-asset-assembler.js @@ -23,6 +23,7 @@ var testDataCss = function (testName) { var testName = ''; describe('lib/asset-assembler.js', function() { + testName = 'test-aggregate-two'; describe(testName, function() { this.timeout(10000); @@ -52,6 +53,7 @@ describe('lib/asset-assembler.js', function() { }); }); }); + testName = 'test-aggregate-two-and-remote'; describe(testName, function() { this.timeout(10000);