diff --git a/.project b/.project index fa954bc..efa5c18 100644 --- a/.project +++ b/.project @@ -5,7 +5,13 @@ + + org.eclipse.wst.jsdt.core.javascriptValidator + + + + org.eclipse.wst.jsdt.core.jsNature diff --git a/README.md b/README.md index 3abfb6e..e46c690 100644 --- a/README.md +++ b/README.md @@ -11,10 +11,7 @@ A javascript library providing server defined loading of resouces for a single p On index.html - FFSpaLoader.start({ - url: '/my/url/for/resources.json', - debug: true - }); + FFSpaLoader.start(...); ## Options diff --git a/es5-ff-spa-loader.js b/es5-ff-spa-loader.js index bf30cb3..0cf8eaa 100644 --- a/es5-ff-spa-loader.js +++ b/es5-ff-spa-loader.js @@ -24,18 +24,66 @@ // TODO: -// conv to req queue -// split js/css so css can be done later // set tag.media = 'only you'; // add media in resouces -// add userAgant match in resouces -// NOTE: add ordered inject, for now JS in non-cache mode needs to be aggragated server side -// add browser supported +// check supported browsers -var FFSpaLoader = (function () { +/** + * FFSpaLoader is an assets loader for single page applications. + * Its build around the concept the there is only a single static index.html which + * synces all its assets to local cache for offline and or fast page loads. + * + * Features: + * - Assets caching for offline use. + * - Assets hashing for fast syncing. + * - Assets types: js,css,cssData + * - Caching backends: null,localStorage,webSqlDB,sqllite + * - Optional ask and cache server assets url. + * - Cordova deviceready event booting. + * + * @module FFSpaLoader + */ +var FFSpaLoader = (/** @lends module:FFSpaLoader */function () { - var options = {}; + var options = { + debug: false, + errorHandler: null, + bootDevice: { + timeout: 4096, + windowFlag: 'FFCordovaDevice' + }, + askUrl: { + urlTransport: 'http://', + questionText: 'Please provide the server name;', + cssText: '.ffAskUrl { font-size: 1em;margin: auto;width: 50%;border: 3px solid #73AD21;padding: 1em;} .ffAskUrl > div {font-size: 0.8em;color: #ccc;} .ffAskUrl > div > * {} .ffAskUrl > div > input {} .ffAskUrlError{ color: red}', + }, + server: { + url: null, + urlPath: null, + timeout: 4096, + windowFlag: 'FFServerUrl', + header: { + request: { + 'X-FFSpaLoader': '42' + }, + response: { + } + } + }, + cache: { + factory: null, + meta: null, + js: null, + css: null, + cssData: null + } + }; + /** + * Prints debug message to the console if options.debug is true. + * @param {String} message The message to log. + * @private + */ var utilDebug = function (message) { if (options.debug !== true) { return; @@ -43,257 +91,640 @@ var FFSpaLoader = (function () { console.log('FFSpaLoader.'+message); }; + var factory = { + detect: { + localStorage: function() { + try { + var testData = 'localStorageDetect'; + localStorage.setItem(testData, testData); + localStorage.removeItem(testData); + return true; + } catch(e) { + return false; + } + }, + openDatabase: function() { + return 'openDatabase' in window; + }, + sqlitePlugin: function() { + return 'sqlitePlugin' in window; + }, + cordova: function() { + return 'cordova' in window; + }, + cordovaDevice: function() { + return options.bootDevice.windowFlag in window; + }, + mobileAgent: function() { + return navigator.userAgent.match(/(iPhone|iPod|iPad|Android|BlackBerry|IEMobile)/); + } + }, + cache: { + localStorage: function() { + return { + cacheGetValue: function(key, cb) { + try { + var dataRaw = localStorage.getItem(key); + var data = JSON.parse(dataRaw); + cb(null, data); + } catch(e) { + cb(e); + } + }, + cacheSetValue: function(key, value, cb) { + try { + localStorage.setItem(key,JSON.stringify(value)); + cb(null); + } catch(e) { + cb(e); + } + }, + cacheDeleteValue: function(key, cb) { + try { + localStorage.removeItem(key); + cb(null); + } catch(e) { + cb(e); + } + } + } + }, + websql: function(opt) { + if (opt === undefined) { opt = {}; } + if (opt.name === undefined) { opt.name = 'ffSpaLoader.db'; } + if (opt.size === undefined) { opt.size = -1; } + if (opt.version === undefined) { opt.version = '1.0'; } + if (opt.openDatabase === undefined) { opt.openDatabase = window.openDatabase; } + var nullDataHandler = function(cb) { + return function (tx, results) { + cb(null); + }; + }; + var sqlErrorHandler = function(cb) { + return function (tx, err) { + cb(err.message+' code: '+err.code); + }; + }; + var cacheDB = window.openDatabase(opt.name, opt.version, opt.name, opt.size); + cacheDB.transaction(function(tx) { + var query = 'SELECT value FROM cache_store WHERE key = \"test-for-table\"'; + utilDebug('websql.init query: '+query); + tx.executeSql(query, [], function(tx,res) {}, function(tx,errorNoTable) { + var query = 'CREATE TABLE cache_store(id INTEGER PRIMARY KEY AUTOINCREMENT, key TEXT NOT NULL, value TEXT NOT NULL)'; + utilDebug('websql.init query: '+query); + tx.executeSql(query, [], function(tx,res) { + var query = 'CREATE UNIQUE INDEX cache_store__key__udx ON TABLE cache_store'; + utilDebug('websql.init query: '+query); + tx.executeSql(query, [], function(tx,res) {}, sqlErrorHandler(options.errorHandler)); // FIX0) { - for (var i in scripts) { - if (scripts[i].src && scripts[i].src.match(/.*ffSpaLoaderUrl.*/)) { - var query = scripts[i].src; - var queryParameters = {}; - query.split('?').forEach(function(part) { - var item = part.split("="); - queryParameters[item[0]] = decodeURIComponent(item[1]); - }); - // TODO: remove debug here - FFSpaLoader.start({ - debug: true, - injectAsLink: true, - url: queryParameters.ffSpaLoaderUrl - }); - break; + /** + * Starts the loader. + * + * @param {function} cb Callback gets called when loader is done. + */ + var start = function (cbArgu) { + var startTime = new Date().getTime(); + var cb = function(err) { + if (err !== null) { + options.errorHandler(err); + } else { + utilDebug('start done in '+(new Date().getTime()-startTime)+' ms.'); + if (typeof cbArgu === "function") { + cbArgu(); + } } } + utilDebug('start serverUrl: '+options.server.url); + if (options.server.url !== null) { + startLoader(cb); + return; + } + if (cacheHasService('meta')) { + cacheGetValue('meta','server_url',function(err, value) { + if (err !== null) { + cb(err); + } else if (value === undefined || value === null || value === '') { + askUrl(cb); + } else { + options.server.url = value; + startLoader(cb); + } + }); + } else { + askUrl(cb); + } + }; + + /** + * Helper for automatic selecting the best to none cache backend option. + * + * Order of detection; sqllite,openDatabase,localStorage,none. + */ + var autoSelectCache = function() { + if (factory.detect.cordovaDevice() && factory.detect.sqlitePlugin()) { + utilDebug('autoSelectCache sqlitePlugin'); + return factory.cache.websql({openDatabase: window.sqlitePlugin}); + } + if (factory.detect.openDatabase()) { + utilDebug('autoSelectCache openDatabase'); + return factory.cache.websql(); + } + if (factory.detect.localStorage()) { + utilDebug('autoSelectCache localStorage'); + return factory.cache.localStorage(); + } + utilDebug('autoSelectCache none'); + return null; // no caching } -}; - -autoStartFFSpaLoader(); // TODO: make private + + /** + * Helper for cordova applications which want to use the sqllite plugin as cache. + * Note: On none cordova page it will callback directly. + * Note: On none cordova device page is will timeout. + * + * @param {function} cb Callback gets called device is ready to use. + */ + var bootDevice = function(cb) { + var startTime = new Date().getTime(); + var bootOnce = function() { + if (typeof cb === "function") { + var callback = cb; + cb = null; + utilDebug('bootDevice done in '+(new Date().getTime()-startTime)+' ms.'); + callback(); + } + }; + if (!factory.detect.cordova()) { + utilDebug('bootDevice webapp'); + bootOnce(); + return; + } + utilDebug('bootDevice timeout: '+options.bootDeviceTimeout); + setTimeout ( function () { + utilDebug('bootDevice timeout'); + bootOnce(); + }, options.bootDevice.timeout); + document.addEventListener("deviceready", function () { + window[options.bootDevice.windowFlag] = true; + utilDebug('bootDevice '+options.bootDevice.windowFlag); + bootOnce(); + }, false); + }; + + return { + options: options, + factory: factory, + start: start, + bootDevice: bootDevice, + autoSelectCache: autoSelectCache + }; +})(); diff --git a/example/example-assets.json b/example/example-assets.json deleted file mode 100644 index e4d3138..0000000 --- a/example/example-assets.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "linkMapping" : { - "/static/module/bootstrap/": "node_modules/bootstrap/dist/", - "/static/module/flot/": "node_modules/flot/", - "/static/": "www_static/" - }, - "css": { - "linkTarget": "/static/css/lib/assets.css", - "linkSources": [ - "/static/module/bootstrap/css/bootstrap.css" - ] - }, - "js": { - "linkTarget": "/static/js/lib/assets.js", - "linkSources": [ - "/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" - ] - } -} diff --git a/example/example.js b/example/example.js index 7acc4f2..003a38d 100644 --- a/example/example.js +++ b/example/example.js @@ -1,46 +1,80 @@ 'use strict'; var express = require('express'); -var async = require('async'); var path = require('path'); -var assets = require('node-ff-assets'); var fs = require('fs'); var minify = require('minify'); +var fetch = require('fetch'); +var cors = require('cors'); -function buildAssets(server,callbackDone) { - var singleResult = 'false' !== process.env.DEV_ASSETS_SINGLE_RESULT; - var assetsConfig = require('./example-assets.json'); - assets.build({ - assets: { - js: { - configCreate: assets.factory.builder.configCreate.fromJSON(assetsConfig,'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: assets.factory.builder.configCreate.fromJSON(assetsConfig,'css'), - configFill: function (config, callback) { - async.series([ - assets.factory.lib.async.pushLinkSources(config, '/static/css/', 'www_static/css/'), - ],callback); - }, - }, - }, - assemblerCreate: assets.factory.builder.assemblerCreate.readFileRegex(), - 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)); - assembler.config.linkTargetSingleResult = singleResult; - callback(); - }, - },callbackDone); +// example options; +var serverUrl = 'http://localhost:8080'; +var useInline = true; // or false + +var clientResourcesWeb = []; +var clientResources = { + js: [], + css: [], + cssData: [] } +var addClientResource = function(clientResource, resourceType) { + clientResources[resourceType].push(clientResource); +} + +var stringHash = function (str) { + var hash = 31; // prime + for (var i = 0; i < str.length; i++) { + hash = ((hash<<5)-hash)+str.charCodeAt(i); + hash = hash & hash; // keep 32b + } + return hash; +}; + +var fetchHashResource = function(fetchEntry,cb) { + fetch.fetchUrl(serverUrl + fetchEntry.url,function(err, meta, data) { + if (err !== null) { return cb(err); } + console.log('fetched url: '+fetchEntry.url+' length: '+meta.responseHeaders['content-length']); + var assetHash = stringHash(''+data); + clientResourcesWeb.push({ + url: fetchEntry.url, + type: fetchEntry.type, + hash: assetHash + }); + cb(null); + }); +}; + +var fetchHashResources = function(fetchList, cb) { + var resourceStack = fetchList; + var resourceLoader = function() { + resourceStack = resourceStack.slice(1); + if (resourceStack.length === 0) { + cb(null); + } else { + fetchHashResource(resourceStack[0],resourceLoader); + } + }; + fetchHashResource(resourceStack[0],resourceLoader); +}; + +var createClientResourceFetchList = function() { + var fetchList = []; + for (var clientResourceIdx in clientResources.js) { + var url = clientResources.js[clientResourceIdx]; + fetchList.push({url:url,type:'js'}); + } + for (var clientResourceIdx in clientResources.css) { + var url = clientResources.css[clientResourceIdx]; + fetchList.push({url:url,type:'css'}); + } + for (var clientResourceIdx in clientResources.cssData) { + var url = clientResources.cssData[clientResourceIdx]; + fetchList.push({url:url,type:'cssData'}); + } + return fetchList; +}; + function renderTemplatePath(viewPath) { return function (req, res) { res.locals.query = req.query; @@ -57,10 +91,7 @@ function renderIndex(server) { minify(__dirname+'/../es5-ff-spa-loader.js', {}, function(err, data) { inline = '\n\t\t'; }); - var inlineNot = '\n\t\t'; - - var useInline = true; // or false - + var inlineNot = '\n\t\t'; return function (req, res) { res.render('index', { inlineNot: useInline?'':inlineNot, @@ -69,80 +100,50 @@ function renderIndex(server) { }; } -function sendRedirect() { - return function (req, res) { - res.redirect('/example-ui'); - }; -} - var stringHash = function (str) { - var hash = 31; // prime - for (var i = 0; i < str.length; i++) { - hash = ((hash<<5)-hash)+str.charCodeAt(i); - hash = hash & hash; // keep 32b - } - return hash; -}; + +addClientResource('/static/module/jquery/jquery.js','js'); +addClientResource('/static/module/angular/angular.js','js'); +addClientResource('/static/module/angular-route/angular-route.js','js'); +addClientResource('/static/module/bootstrap/css/bootstrap.css','css'); +addClientResource('/static/module/bootstrap/js/bootstrap.js','js'); +addClientResource('/static/css/boot.css','css'); +addClientResource('/static/css/style.css','css'); +addClientResource('/static/js/example-app.js','js'); +addClientResource('/static/js/controller/page-bar.js','js'); +addClientResource('/static/js/controller/page-foo.js','js'); +addClientResource('/static/js/controller/page-index.js','js'); var server = express(); -buildAssets(server,function(err) { - if (err) { - throw err; - } - console.info('Server assets done.'); - - server.set('view engine', 'ejs'); - 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('/static/es5-ff-spa-loader.js', function (req,res) { - res.write(fs.readFileSync(__dirname+'/../es5-ff-spa-loader.js', 'utf8')); - res.end(); - }); - server.get('/static/resources-spa-mobile', function (req,res) { - var hashJs = stringHash(fs.readFileSync(__dirname+'/www_static/js/lib/assets.js', 'utf8')); - var hashCss = stringHash(fs.readFileSync(__dirname+'/www_static/css/lib/assets.css', 'utf8')); - res.json({ - data: { - resources: [ - { - url: '/static/js/lib/assets.js----TODO', - type: 'js', - hash: hashJs - }, - ] - } - }); - }); - server.get('/static/resources-spa-web', function (req,res) { - var hashJs = stringHash(fs.readFileSync(__dirname+'/www_static/js/lib/assets.js', 'utf8')); - var hashCss = stringHash(fs.readFileSync(__dirname+'/www_static/css/lib/assets.css', 'utf8')); - res.json({ - data: { - resources: [ - { - url: '/static/js/lib/assets.js', - type: 'js', - hash: hashJs - }, - { - url: '/static/css/lib/assets.css', - type: 'css', - hash: hashCss - } - ] - } - }); - }); - - server.get('/', sendRedirect()); - server.get('/example-ui/thtml/*', renderTemplatePath('thtml/')); - server.get('/example-ui', renderIndex(server)); - server.get('/example-ui/*', renderIndex(server)); // must be last; for HTML5 history - console.info('Server config done.'); - - server.listen(8080); - console.info('Server started on port 8080'); +server.use(cors({credentials: true, origin: '*'})); +server.set('view engine', 'ejs'); +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/jquery', express.static(path.join(__dirname,'node_modules/jquery/dist'))); +server.use('/static/module/angular', express.static(path.join(__dirname,'node_modules/angular'))); +server.use('/static/module/angular-route', express.static(path.join(__dirname,'node_modules/angular-route'))); + +server.get('/static/es5-ff-spa-loader.js', function (req,res) { + res.write(fs.readFileSync(__dirname+'/../es5-ff-spa-loader.js', 'utf8')); + res.end(); }); +server.get('/static/spa-client-resources', function (req,res) { + res.json({data: {resources: clientResourcesWeb}}); +}); + +server.get('/', function (req, res) {res.redirect('/example-ui');}); +server.get('/example-ui/thtml/*', renderTemplatePath('thtml/')); +server.get('/example-ui', renderIndex(server)); +server.get('/example-ui/*', renderIndex(server)); // must be last; for HTML5 history +console.info('Server config done.'); + +server.listen(8080); +console.info('Server started on port 8080'); + +var res = createClientResourceFetchList(); +fetchHashResources(res, function(err) { + if (err !== null) {console.log(err);}; + console.log('Total assets build: '+clientResourcesWeb.length); +}); + diff --git a/example/package.json b/example/package.json index 32f3b48..e350cf4 100644 --- a/example/package.json +++ b/example/package.json @@ -7,12 +7,14 @@ "start": "node example.js" }, "dependencies": { - "async": "1.2.x", + "angular": "^1.4.8", + "angular-route": "^1.4.8", "bootstrap": "3.3.x", + "cors": "^2.7.1", "ejs": "2.3.x", "express": "4.11.x", - "flot": "0.8.x", - "minify": "^2.0.2", - "node-ff-assets": "^0.2.5" + "fetch": "0.3.x", + "jquery": "^2.1.4", + "minify": "^2.0.2" } } diff --git a/example/www_static/css/flot.css b/example/www_static/css/flot.css deleted file mode 100644 index 76b6b11..0000000 --- a/example/www_static/css/flot.css +++ /dev/null @@ -1,10 +0,0 @@ - -.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 deleted file mode 100644 index 7e97652..0000000 --- a/example/www_static/css/panel.css +++ /dev/null @@ -1,56 +0,0 @@ - -.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/js/controller/page-bar.js b/example/www_static/js/controller/page-bar.js index 3f628ac..bee4ac8 100644 --- a/example/www_static/js/controller/page-bar.js +++ b/example/www_static/js/controller/page-bar.js @@ -1,7 +1,7 @@ pageRouteInit.push(function ($routeProvider, $locationProvider) { $routeProvider.when('/example-ui/bar', { - templateUrl: '/example-ui/thtml/bar', + templateUrl: window.serverUrl+'/example-ui/thtml/bar', controller: PageFoo }); }); diff --git a/example/www_static/js/controller/page-foo.js b/example/www_static/js/controller/page-foo.js index a5177b2..971b27e 100644 --- a/example/www_static/js/controller/page-foo.js +++ b/example/www_static/js/controller/page-foo.js @@ -1,7 +1,7 @@ pageRouteInit.push(function ($routeProvider, $locationProvider) { $routeProvider.when('/example-ui/foo', { - templateUrl: '/example-ui/thtml/foo', + template: '

Foo

Welcome to the foo.

', controller: PageFoo }); }); diff --git a/example/www_static/js/controller/page-index.js b/example/www_static/js/controller/page-index.js index 2a3fd23..983dee9 100644 --- a/example/www_static/js/controller/page-index.js +++ b/example/www_static/js/controller/page-index.js @@ -1,7 +1,7 @@ pageRouteInit.push(function ($routeProvider, $locationProvider) { $routeProvider.when('/example-ui', { - templateUrl: '/example-ui/thtml/index', + template: '

Example UI Index

Welcome make yourself at home.

', controller: PageIndex }); }); diff --git a/example/www_static/js/example-app.js b/example/www_static/js/example-app.js index 17bb47b..649eb9c 100644 --- a/example/www_static/js/example-app.js +++ b/example/www_static/js/example-app.js @@ -1,22 +1,22 @@ 'use strict'; - document.title = 'FF-Spa-Loader Example'; -$('html').attr('ng-app', 'exampleUI'); -$('html').attr('lang', 'en'); + +var serverUrl = window.FFServerUrl; +console.log('FF provided serverUrl: '+serverUrl); $(document.createElement('div')).attr('id', 'wrapper').appendTo($('body')); -$(document.createElement('div')).attr('ng-include', '\'/example-ui/thtml/layout/header\'').appendTo($('#wrapper')); +$(document.createElement('div')).attr('ng-include', '\''+serverUrl+'/example-ui/thtml/header\'').appendTo($('#wrapper')); $(document.createElement('div')).attr('id', 'page-wrapper').appendTo($('#wrapper')); $(document.createElement('div')).attr('id', 'container-fluid').attr('ng-view', '').appendTo($('#page-wrapper')); -$(document.createElement('div')).attr('ng-include', '\'/example-ui/thtml/layout/footer\'').appendTo($('body')); +$(document.createElement('div')).attr('ng-include', '\''+serverUrl+'/example-ui/thtml/footer\'').appendTo($('body')); 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({enabled: true, requireBase: false}); - }]); +angular.module('exampleUI', ['ngRoute']).config( + ['$routeProvider', '$locationProvider', function + ($routeProvider, $locationProvider) { + + pageRouteInit.forEach(function(init) { init($routeProvider, $locationProvider); }); + $routeProvider.otherwise({ redirectTo: '/example-ui' }); + $locationProvider.html5Mode({enabled: true, requireBase: false}); +}]); diff --git a/example/www_views/index.ejs b/example/www_views/index.ejs index 03c00a4..9a90080 100644 --- a/example/www_views/index.ejs +++ b/example/www_views/index.ejs @@ -1,17 +1,17 @@ - + Loading<%- inlineNot %> <%- inline %> diff --git a/example/www_views/thtml/bar.ejs b/example/www_views/thtml/bar.ejs index 0029a6b..8609501 100644 --- a/example/www_views/thtml/bar.ejs +++ b/example/www_views/thtml/bar.ejs @@ -1,32 +1,7 @@ -
-

Bar

-

Welcome to the bar.

-
- - - - - - - - - - - - - - - - - - - - - - - - - -
ChairPersonDrinking
seat 1emptynone
seat 2youcoffee
seat 3catwater
-
-
+

Bar

Welcome to the bar.

+ + + + + +
ChairPersonDrinking
seat 1emptynone
seat 2youcoffee
seat 3catwater
\ No newline at end of file diff --git a/example/www_views/thtml/foo.ejs b/example/www_views/thtml/foo.ejs deleted file mode 100644 index 52c464f..0000000 --- a/example/www_views/thtml/foo.ejs +++ /dev/null @@ -1,4 +0,0 @@ -
-

Foo

-

Welcome to the foo.

-
diff --git a/example/www_views/thtml/layout/footer.ejs b/example/www_views/thtml/footer.ejs similarity index 100% rename from example/www_views/thtml/layout/footer.ejs rename to example/www_views/thtml/footer.ejs diff --git a/example/www_views/thtml/layout/header.ejs b/example/www_views/thtml/header.ejs similarity index 100% rename from example/www_views/thtml/layout/header.ejs rename to example/www_views/thtml/header.ejs diff --git a/example/www_views/thtml/index.ejs b/example/www_views/thtml/index.ejs deleted file mode 100644 index c6c6dcc..0000000 --- a/example/www_views/thtml/index.ejs +++ /dev/null @@ -1,4 +0,0 @@ -
-

Example UI Index

-

Welcome make yourself at home.

-
diff --git a/package.json b/package.json index 56e7db7..91b2d70 100644 --- a/package.json +++ b/package.json @@ -4,10 +4,29 @@ "description": "Javascript Single Page Application Loader", "main": "es5-ff-spa-loader.js", "author": "Willem (http://forwardfire.net/)", - "keywords": ["website","assets","js","css","loader","spa","mobile","resources","sync","cache"], + "keywords": [ + "website", + "assets", + "js", + "css", + "loader", + "spa", + "mobile", + "resources", + "sync", + "cache" + ], "license": "BSD-2-Clause", "repository": { "type": "git", "url": "https://bitbucket.org/im_ik/es5-ff-spa-loader.git" - } + }, + "dependencies": { + "jsdoc": "^3.4.0" + }, + "files": [ + "README.md", + "es5-ff-spa-loader.js", + "example/" + ] }