From 1b6dbc49b39008956d03d030a089976a8cb71818 Mon Sep 17 00:00:00 2001 From: Marc Diethelm Date: Sat, 25 Jan 2014 11:38:03 +0100 Subject: [PATCH 1/5] Remove trailing comma. --- Gruntfile.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gruntfile.js b/Gruntfile.js index 8676727..99865a4 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -339,7 +339,7 @@ module.exports = function(grunt) { // Define build tasks // use actual task name (first part before colon)! grunt.registerTask('build-sprites', ['glue']); - grunt.registerTask('build-external-js', ['concat:external_scripts', 'jshint:external',]); + grunt.registerTask('build-external-js', ['concat:external_scripts', 'jshint:external']); grunt.registerTask('build-inline-js', ['concat:inline_scripts', 'log:devJsDone', 'jshint:inline']); grunt.registerTask('build-external-css', ['less_imports:external', 'less:external']); grunt.registerTask('build-inline-css', ['less_imports:inline', 'less:inline', 'log:devCssDone']); From eeaefe07df89206eb2d788abd7edc6b454a21cf6 Mon Sep 17 00:00:00 2001 From: Marc Diethelm Date: Sat, 25 Jan 2014 11:44:04 +0100 Subject: [PATCH 2/5] Readme cosmetics and underp changelog wording. --- CHANGELOG.md | 3 ++- README.md | 3 +-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 799c0dc..d7204c9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ ## develop branch (0.8.0-beta1) +- This release contains breaking changes. - Use Hipsum.js for easy filler text. Available in development and production installations. - Use grunt-glue-nu for improved glue spriting the grunt way - Full logging in production, including date and user agent. @@ -18,7 +19,7 @@ - Handlebars helpers are now automatically registered for use in module templates. - Views in the project overview are now rendered using the catch-all route. This prevents conflicts with with ‘raw’ & ‘solo’ `_view` routes if the dev adds custom routes to the views that include queries. - "Pin" views to the top in the project overview by writing view names in a json file in _config/. -- Default asset build now goes writes `build` dir (not tracked by git) and does not minify anymore. Start grunt with `--dist` option to start a production build including minification into `dist` dir (tracked by git). +- Default asset build now writes into `build` dir (not tracked by git) and does not minify anymore. Start grunt with `--dist` option to start a production build, including minification, into `dist` dir (tracked by git). - Improved formatting of rendered modules. Auto-indent nested modules. You can manually specify the desired indentation on module and inline asset calls. - Refactored a lot of application code for clarity and better separation of components. - Using [node-convict](https://github.com/mozilla/node-convict) for configuration building and switched to [CJSON](https://github.com/kof/node-cjson) config files. Convict supports environment variables and validation of config values. diff --git a/README.md b/README.md index 72ab4c7..f47219c 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,5 @@ -Master [![Build status (master)](http://b.adge.me/travis/MarcDiethelm/xtc/master.svg)](https://travis-ci.org/MarcDiethelm/xtc)   Develop [![Build status (develop)](http://b.adge.me/travis/MarcDiethelm/xtc/develop.svg)](https://travis-ci.org/MarcDiethelm/xtc)    ![MIT license](http://b.adge.me/:license-MIT-brightgreen.svg)    [![Follow @xtcjs](http://b.adge.me/:@xtcjs-follow-green.svg)](https://twitter.com/xtcjs)    [![gittip donate](http://b.adge.me/:gittip-donate-lightgrey.svg)](https://www.gittip.com/MarcDiethelm/) +Master [![Build status (master)](http://b.adge.me/travis/MarcDiethelm/xtc/master.svg)](https://travis-ci.org/MarcDiethelm/xtc)   Develop [![Build status (develop)](http://b.adge.me/travis/MarcDiethelm/xtc/develop.svg)](https://travis-ci.org/MarcDiethelm/xtc)    ![MIT license](http://b.adge.me/:license-MIT-brightgreen.svg)    [![Follow @xtcjs](http://b.adge.me/:@xtcjs-follow-green.svg)](https://twitter.com/xtcjs)    [![gittip donate](http://b.adge.me/:gittip-donate-lightgrey.svg)](https://www.gittip.com/MarcDiethelm/) ---- # xtc – frontend development server and framework From a61b88d3d52725ced9b185b99ac594c0cd305435 Mon Sep 17 00:00:00 2001 From: Marc Diethelm Date: Sat, 25 Jan 2014 17:41:04 +0100 Subject: [PATCH 3/5] Update default repo URI --- _config/config-default.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_config/config-default.js b/_config/config-default.js index cede55b..913bd4b 100644 --- a/_config/config-default.js +++ b/_config/config-default.js @@ -51,7 +51,7 @@ module.exports = { ,repository: { doc : 'Used to construct links to views, modules and layouts in the project overview' ,format : 'url' - ,default : 'https://github.com/MarcDiethelm/node-terrific/tree/develop/' + ,default : 'https://github.com/MarcDiethelm/xtc/tree/develop/' } // Should asset building include sprites generation? Dependencies: Glue (Python) and OptiPNG (binary executable) ,enableSpritesBuilding: false From 9fc141e58779f2324098d158164fb8f6edb4a760 Mon Sep 17 00:00:00 2001 From: Marc Diethelm Date: Tue, 28 Jan 2014 10:08:47 +0100 Subject: [PATCH 4/5] Additional config / build rewrite, allows complete flexibility for frontend sources and build destinations, even outside of xtc root. All relative paths are resolved to absolute paths. xtc can now be used as a Terrific build tool in foreign backends. --- CHANGELOG.md | 13 +- Gruntfile.js | 81 ++++--- README.md | 2 +- _config/config-default.js | 224 +++++++++++------- _config/x-config-standalone-build.json | 91 +++++++ app.js | 12 +- controllers/_default.js | 8 +- .../{test/lib => lib/test}/jquery-iframe.js | 0 .../{test/lib => lib/test}/qunit-1.12.0.css | 0 .../{test/lib => lib/test}/qunit-1.12.0.js | 0 .../lib => lib/test}/qunit-90afd90147.js | 0 frontend/_public/{ => lib}/test/test.js | 0 frontend/views/_test-modules.hbs | 4 +- frontend/views/layouts/default.hbs | 2 +- lib/configure.js | 118 ++++++--- lib/handlebars-helpers-xtc.js | 9 +- lib/helpers.js | 13 +- lib/mod-render.js | 4 +- lib/overview.js | 23 +- test/assets/config-assets-uri.json | 90 +++++-- test/assets/config-assets.json | 71 ++++-- test/configure/configure.js | 2 +- test/configure/fixtures/config-project.json | 9 +- .../config-terrific-annotate.json | 4 +- test/terrific-modules/config-terrific.json | 4 +- .../expected/basic/basic-read-error.html | 3 - test/terrific-modules/terrific.js | 3 +- 27 files changed, 554 insertions(+), 236 deletions(-) create mode 100644 _config/x-config-standalone-build.json rename frontend/_public/{test/lib => lib/test}/jquery-iframe.js (100%) rename frontend/_public/{test/lib => lib/test}/qunit-1.12.0.css (100%) rename frontend/_public/{test/lib => lib/test}/qunit-1.12.0.js (100%) rename frontend/_public/{test/lib => lib/test}/qunit-90afd90147.js (100%) rename frontend/_public/{ => lib}/test/test.js (100%) delete mode 100644 test/terrific-modules/expected/basic/basic-read-error.html diff --git a/CHANGELOG.md b/CHANGELOG.md index d7204c9..1b8cb5f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,11 +1,20 @@ # Changelog -## develop branch (0.8.0-beta2) +## develop branch (0.9.0) + +- + +## 0.8.0-beta3 + +- This release contains breaking changes. +- Additional config / build rewrite, allows complete flexibility for frontend sources and build destinations, even outside of xtc root. All relative paths are resolved to absolute paths. xtc can now be used as a Terrific build tool in foreign frameworks. + +## 0.8.0-beta2 - Fix missing dependencies that resulted from gitignoring too aggressively. -## develop branch (0.8.0-beta1) +## 0.8.0-beta1 - This release contains breaking changes. - Use Hipsum.js for easy filler text. Available in development and production installations. diff --git a/Gruntfile.js b/Gruntfile.js index 99865a4..ec7215a 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -1,11 +1,13 @@ module.exports = function(grunt) { + process.env.NODE_ENV = grunt.option('dist') ? 'production' : 'development'; + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Read project configuration var path = require('path') ,configr = require('./lib/configure') - ,cfg ,modulesPattern, buildBasePath, buildBaseDirName + ,cfg ,modulesPattern, buildPath, buildBaseDirName ,isDistBuild = grunt.option('dist') || false // based on this value we will execute a dev or dist build ; @@ -23,12 +25,9 @@ module.exports = function(grunt) { //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Create vars from config - modulesPattern = path.join(cfg.paths.modulesBaseDir, cfg.moduleDirName.replace('{{name}}', '*')) - buildBaseDirName = isDistBuild ? cfg.static.build.baseDirNameDist : cfg.static.build.baseDirNameDev; - buildBasePath = isDistBuild - ? path.join(cfg.paths.staticBaseDir, cfg.static.build.baseDirNameDist) // build.baseDirNameDist can be empty - : path.join(cfg.paths.staticBaseDir, cfg.static.build.baseDirNameDev) // build.baseDirNameDev can be empty - ; + modulesPattern = path.join(cfg.sources.modulesBaseDir, cfg.moduleDirName.replace('{{name}}', '*')) + buildBaseDirName = isDistBuild ? cfg.build.baseDirNameDist : cfg.build.baseDirNameDev; + buildPath = path.join(cfg.buildBasePath, buildBaseDirName); // build.baseDirName can be empty //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -36,35 +35,35 @@ module.exports = function(grunt) { grunt.initConfig({ - pkg : grunt.file.readJSON('package.json') + pkg : require('./package.json') - ,staticUriPrefixCss : cfg.staticUriPrefix - ,staticUriPrefix : (cfg.staticUriPrefix || '') + '/' + ,staticBaseUriCss : cfg.staticBaseUri + ,staticBaseUri : (cfg.staticBaseUri || '') + '/' //////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Sources base paths - ,tcInline : cfg.paths.inline - ,tcBase : cfg.paths.base + ,tcInline : cfg.sources.inline + ,tcBase : cfg.sources.base ,spritesPath : '<%=tcBase%>/css/sprites' ,tcModules : modulesPattern - ,tcApplication : cfg.paths.application - ,staticDir : cfg.paths.staticBaseDir + ,tcApplication : cfg.sources.application + ,staticDir : cfg.staticPath //////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Output destinations - ,baseDirName : cfg.static.build.baseDirName - - ,buildBasePath : buildBasePath // dynamic, depends on build mode (development/production) - ,buildBaseDirName : buildBaseDirName // dynamic, depends on build mode (development/production) - ,tmpPath : '<%=buildBasePath%>/tmp' + //,baseDirName : cfg.build.baseDirName + + ,buildPath : buildPath // dynamic, depends on build mode (development/production) + //,buildBaseDirName : buildBaseDirName // dynamic, depends on build mode (development/production) + ,tmpPath : '<%=buildPath%>/tmp' - ,destJs : '<%=buildBasePath%>' - ,destCss : '<%=buildBasePath%>' - ,destSpritesImg : '<%=buildBasePath%>' + ,destJs : '<%=buildPath%>' + ,destCss : '<%=buildPath%>' + ,destSpritesImg : '<%=buildPath%>' ,destSpritesCss : '<%=spritesPath%>' // technically this should go in tmp, but we want the generated classes in our base css for easy lookup. @@ -102,7 +101,7 @@ module.exports = function(grunt) { ,'<%=tcApplication%>/js/*.js' ] ,module_test_js: [ - '<%=staticDir%>/test/*.js' + '<%=staticDir%>/lib/test/*.js' ,'<%=tcModules%>/test/*.js' ] ,jshint_inline: [ @@ -132,7 +131,7 @@ module.exports = function(grunt) { options: { css : '<%=destSpritesCss%>' ,less : true - ,url : '<%=staticUriPrefix%><%=buildBaseDirName%>' + ,url : '<%=staticBaseUri%><%=buildBaseDirName%>' ,namespace : '' ,'sprite-namespace' : '' ,optipng : true @@ -193,7 +192,7 @@ module.exports = function(grunt) { ,less: { inline: { options: { - // cssmin will not create file if the output is empty. a special comment fixes this. + // cssmin will not create file if the output is empty. a special comment fixes this. banner : '/*! Inline style dependencies for page bootstrapping */' ,imports: { reference : ['<%=tcInline%>/css/lib/reference/*.less'] @@ -204,9 +203,10 @@ module.exports = function(grunt) { } ,external: { options: { - banner : "@static-prefix: '<%=staticUriPrefixCss%>';" + banner : "@static-prefix: '<%=staticBaseUriCss%>';" ,imports: { - reference : ['<%=tcBase%>/css/lib/reference/*.less'] + //reference : ['<%=tcBase%>/css/lib/reference/*.less'] + reference : [path.relative(process.cwd(), cfg.sources.base +'/css/lib/reference')+'/*.less'] } } ,src : '<%=tmpPath%>/external-imports.less' @@ -227,13 +227,18 @@ module.exports = function(grunt) { // After dist build remove all non-minified files. ,clean: { - dist: [ - '<%=tmpPath%>' - ,'<%=destCss%>/inline.css' - ,'<%=destCss%>/external.css' - ,'<%=destJs%>/inline.js' - ,'<%=destJs%>/external.js' - ] + dist: { + options: { + force: true + } + ,src: [ + '<%=tmpPath%>' + ,'<%=destCss%>/inline.css' + ,'<%=destCss%>/external.css' + ,'<%=destJs%>/inline.js' + ,'<%=destJs%>/external.js' + ] + } } ,jshint: { @@ -290,7 +295,11 @@ module.exports = function(grunt) { } ,watch: { - sprites: { + options: { + //cwd : '../..', + spawn : false + } + ,sprites: { files : ['<%=sources.sprites_watch%>'] ,tasks : ['build-sprites', 'build-external-css'] }, @@ -400,7 +409,7 @@ module.exports = function(grunt) { grunt.registerMultiTask('log', 'a console logging task', function() { var options = this.options() - ,color = options.color || false + ,color = options.color || false ; if (options.bold) { diff --git a/README.md b/README.md index f47219c..db300b6 100644 --- a/README.md +++ b/README.md @@ -154,7 +154,7 @@ The configuration files are located the folder `_config`. `config-local.json` is also listed in `.jitsuignore`, so if you're using Nodejitsu for hosting this file will never be deployed. Make sure these two files are not tracked by git unless you know what you're doing. -The location of the config files can be configured in package.json. +Which config files are loaded and their order can be configured in configs.json. The location of the config files can be configured in package.json by changing the `configPath` property. ### Start the Server! diff --git a/_config/config-default.js b/_config/config-default.js index 913bd4b..3ca6391 100644 --- a/_config/config-default.js +++ b/_config/config-default.js @@ -1,24 +1,68 @@ // Never commit authentication data to a public repository! +/** + * Default configuration + * + * Uses convict.js. Properties can be simple values like strings, integers, etc or "schemas" + * see: https://github.com/mozilla/node-convict + * + * @type {exports} + */ + var check = require('../lib/validator'); module.exports = { + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // App basics + // Default html > head > title is constructed from this - siteName: 'XTC Project' - ,devPort: { - doc: 'Local port for the server' - ,format: 'port' - ,default: 3000 + "siteName": "XTC Project" + + ,"devPort": { + doc : 'Local port for the server' + ,format : 'port' + ,default : 3000 } - ,i18n: { + + ,"i18n": { // Sets the HTML lang attribute - langDefault: 'en-US' + "langDefault" : "en-US" + } + + ,"enableModuleTesting": true + + // Should asset building include sprites generation? Dependencies: Glue (Python) and OptiPNG (binary executable) + ,"enableSpritesBuilding": false + + ,"repository": { + doc : 'Used to construct links to views, modules and layouts in the project overview' + ,format : 'url' + ,default : 'https://github.com/MarcDiethelm/xtc/tree/develop/' + } + + + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // Rendering + + ,"annotateModules": { + "development" : true + ,"production" : false } + + // Characters to use for indentation of modules and inline assets + ,"indentString" : '\t' + // default indentation level of modules and inline assets + // (currently 0, because views rendered with Handlebars can't be indented) + ,"indentLevel" : 0 + + + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Basic auth credentials to protect routes - ,auth: { - basic: { - format : Object + + ,"auth": { + "basic": { + format : Object ,default : {} ,env : 'AUTH_BASIC' }, @@ -31,7 +75,7 @@ module.exports = { or see e.g. http://compnetworking.about.com/od/workingwithipaddresses/a/cidr_notation.htm /32: exact ip */ - ip: { + "ip": { format: function(val) { check('ipRanges', val, 'should contain valid IP ranges'); } @@ -42,91 +86,103 @@ module.exports = { ,'env' : 'AUTH_IP' } } - ,allowAuthBypassForIpRanges: false - ,annotateModules: { - development: true - ,production: false - } - ,enableModuleTesting: true - ,repository: { - doc : 'Used to construct links to views, modules and layouts in the project overview' - ,format : 'url' - ,default : 'https://github.com/MarcDiethelm/xtc/tree/develop/' - } - // Should asset building include sprites generation? Dependencies: Glue (Python) and OptiPNG (binary executable) - ,enableSpritesBuilding: false - - // File system paths relative to app.js, a property called app.config.pathsAbsolute will be generated from them - ,paths: { - // helpers: hardcoded in apps.js - inline : 'frontend/_inline' - ,base : 'frontend/_base' - ,application : 'frontend/_application' - ,routes : 'controllers/routes.js' - ,views : 'frontend/views' - ,layouts : 'frontend/views/layouts' + + ,"allowAuthBypassForIpRanges": false + + + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // Frontend sources + // Paths to frontend source folders relative to app.js, will be resolved to absolute paths + + // base path to the frontend sources, can be empty + ,"sourcesBasePath" : "frontend" + ,"sources": { + "inline" : "_inline" + ,"base" : "_base" + ,"application" : "_application" + ,"views" : "views" + ,"layouts" : "views/layouts" // Path to the Terrific modules directories - ,modulesBaseDir : 'frontend/modules' - // Path to the static assets, used by Express and by the 'asset' template helper - ,staticBaseDir : 'frontend/_public' + ,"modulesBaseDir" : "modules" } - // relative to templateBaseDir - ,defaultLayoutName : 'default' - ,moduleDirName : '{{name}}' - ,skinsDirName : 'skins' + ,"defaultLayoutName" : "default" + ,"moduleDirName" : "{{name}}" // A pattern for module folder names, {{name}} will be replaced. + ,"skinsDirName" : "skins" - // URIs for use in layouts are constructed from the following data - // URI prefix for static assets, e.g. '/static', empty string for none - ,staticUriPrefix: '' - // static assets URIs are relative to 'staticUriPrefix' - ,'static': { - img: 'img' - // URIs to generated assets - ,build: { - // baseDirName is relative to paths.staticBaseDir - baseDirNameDev : 'build' - ,baseDirNameDist : 'dist' - // js and css are relative to baseDirName - ,js: { - // to inline scripts in a template, usage: {{inline "js"}} - inline: { - development : 'inline.js' - ,production : 'inline.min.js' - } - // URI of the generated main js file, usage: {{static.build.js.external}} - ,external: { - development : 'external.js' - ,production : 'external.min.js' - } + + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // Frontend asset build destinations + // Destination paths and file names. Paths relative to app.js, will be resolved to absolute paths. + + ,"buildBasePath" : "frontend/_public" + ,"build": { + // baseDirNameX is relative to buildBasePath + "baseDirNameDev" : "build", + "baseDirNameDist" : "dist" + + // js and css are relative to baseDirNameX + ,"js": { + "dirName" : "" + // to inline scripts in a template, usage: {{inline "js"}} + ,"inline": { + "development" : "inline.js" + ,"production" : "inline.min.js" + } + // URI of the generated main js file, usage: {{static.build.js.external}} + , + "external": { + "development" : "external.js" + ,"production" : "external.min.js" + } + }, + "css": { + "dirName" : "" + // to inline styles in a template, usage: {{inline "css"}} + ,"inline": { + "development" : "inline.css" + ,"production" : "inline.min.css" }, - css: { - // to inline styles in a template, usage: {{inline "css"}} - inline: { - development : 'inline.css' - ,production : 'inline.min.css' - }, - // URI of the generated main css file, usage: {{static.build.css.external}} - external: { - development : 'external.css' - ,production : 'external.min.css' - } + // URI of the generated main css file, usage: {{static.build.css.external}} + "external": { + "development" : "external.css" + ,"production" : "external.min.css" } } + ,"spriteSheets": { + "dirName" : "" + } } - // Characters to use for indentation of modules and inline assets - ,indentString: '\t' - // default indentation level of modules and inline assets - // (currently 0, because views rendered with Handlebars can't be indented) - ,indentLevel: 0 + + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // Routing + + ,"routesPath" : "controllers/routes.js" + + // URIs for use in layouts are constructed from the following data + + // URI prefix for static assets, e.g. '/static', empty string for none + , "staticBaseUri" : "" + + // Physical path to the static assets, used by Express and by the 'asset' template helper + ,"staticPath" : "frontend/_public" + + // list static asset sub-paths to create direct references for, for use in templates. Relative to staticPath + , "static": { + "img" : "img" + } + + + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // Module Testing // Config properties for client-side QUnit - ,QUnitFE: { + ,"QUnitFE": { // QUnit updates document.title to add a checkmark or x-mark to indicate if a testsuite passed or failed. - alterTitle : true + "alterTitle" : true // A summary of all executed tests is logged to the browser console. - ,consoleOutput : true + ,"consoleOutput" : true // Activate the standard QUnit UI. - ,showUi : false + ,"showUi" : false } } \ No newline at end of file diff --git a/_config/x-config-standalone-build.json b/_config/x-config-standalone-build.json new file mode 100644 index 0000000..f6cac62 --- /dev/null +++ b/_config/x-config-standalone-build.json @@ -0,0 +1,91 @@ +{ + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // App basics + + // Should asset building include sprites generation? Dependencies: Glue (Python) and OptiPNG (binary executable) + "enableSpritesBuilding": false + + + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // Frontend sources + // Paths to frontend source folders relative to app.js, will be resolved to absolute paths + + // base path to the frontend sources, can be empty + ,"sourcesBasePath": "../xtc-external-assets/frontend" + ,"sources": { + "inline" : "_inline" + ,"base" : "_base" + ,"application" : "_application" + ,"views" : "../../xtc/frontend/views" + ,"layouts" : "../../xtc/frontend/views/layouts" + // Path to the Terrific modules directories + ,"modulesBaseDir" : "modules" + } + ,"defaultLayoutName" : "default" + ,"moduleDirName" : "{{name}}" + ,"skinsDirName" : "skins" + + + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // Frontend asset build destinations + // Destination paths and file names. Paths relative to app.js, will be resolved to absolute paths. + + ,"buildBasePath" : "../xtc-external-assets" + ,"build": { + // baseDirNameX is relative to buildBasePath + "baseDirNameDev" : "build", + "baseDirNameDist" : "dist" + + // js and css are relative to baseDirNameX + ,"js": { + "dirName" : "" + // to inline scripts in a template, usage: {{inline "js"}} + ,"inline": { + "development" : "inline.js", + "production" : "inline.min.js" + } + // URI of the generated main js file, usage: {{static.build.js.external}} + , + "external": { + "development" : "external.js", + "production" : "external.min.js" + } + }, + "css": { + "dirName" : "" + // to inline styles in a template, usage: {{inline "css"}} + ,"inline": { + "development" : "inline.css", + "production" : "inline.min.css" + }, + // URI of the generated main css file, usage: {{static.build.css.external}} + "external": { + "development" : "external.css", + "production" : "external.min.css" + } + } + ,"spriteSheets": { + "dirName" : "" + } + } + + + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // Routing + + ,"routesPath" : "controllers/routes.js" + + // URIs for use in layouts are constructed from the following data + + // URI prefix for static assets, e.g. '/static', empty string for none. Also used inside generated css files as base path. + ,"staticBaseUri" : "" + + // Physical path to the static assets, used by Express and by the 'asset' template helper + ,"staticPath" : "../xtc-external-assets/assets" + + // list static asset sub-paths to create direct references for, for use in templates. Relative to staticPath + , "static": { + "img" : "img" + } + +} diff --git a/app.js b/app.js index 4694661..ce70e1e 100644 --- a/app.js +++ b/app.js @@ -37,7 +37,7 @@ handlebars = require('./lib/handlebars-helpers-xtc.js'); hbs = require('express3-handlebars').create({ handlebars: handlebars - ,layoutsDir: cfg.paths.layouts + ,layoutsDir: cfg.sources.layouts ,defaultLayout: cfg.defaultLayoutName ,extname: '.hbs' }); @@ -45,7 +45,7 @@ hbs = require('express3-handlebars').create({ // Set the express3-handlebars instance as rendering engine app.engine('hbs', hbs.engine); // 1: template file extension, 2: engine render callback app.set('view engine', 'hbs'); -app.set('views', cfg.paths.views); +app.set('views', cfg.sources.views); //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -60,20 +60,22 @@ if ('development' == app.get('env')) { if ('production' == app.get('env')) {} -app.use(express.favicon(path.join(cfg.pathsAbsolute.staticBaseDir, 'favicon.ico'))); +app.use(express.favicon(path.join(cfg.staticPath, 'favicon.ico'))); app.use(express.logger( 'development' == app.get('env') && 'dev' )); // Abbreviated logging for development app.use(express.json()); app.use(express.urlencoded()); app.use(express.multipart()); // Security tip: Disable this if you don't need file upload. app.use(express.methodOverride()); app.use(express.compress()); -app.use(cfg.staticUriPrefix, express.static(cfg.pathsAbsolute.staticBaseDir)); + +app.use(cfg.staticBaseUri, express.static(cfg.staticPath)); +app.use(cfg.staticBaseUri, express.static(cfg.buildBasePath)); // in case buildBasePath is different from staticPath // Voodoo! Set up tracking the Terrific modules included for any URIs, for module testing in the browser. helpers.registerModuleTestTrackingMiddleware(app); // Register our routes in routes.js -require(cfg.pathsAbsolute.routes)(app); +require(cfg.routesPath)(app); app.use(helpers.render404); // If no other middleware responds, this last callback sends a 404. diff --git a/controllers/_default.js b/controllers/_default.js index 23f5eea..2023a0f 100644 --- a/controllers/_default.js +++ b/controllers/_default.js @@ -76,7 +76,7 @@ module.exports = function(app) { ,skipModules: true }); - hbs.render(path.join(cfg.paths.layouts, cfg.defaultLayoutName + '.hbs'), res.locals, + hbs.render(path.join(cfg.sources.layouts, cfg.defaultLayoutName + '.hbs'), res.locals, function(err, html) { if (err) { var error = utils.error('Unable to render the module in the default template', err); @@ -97,7 +97,7 @@ module.exports = function(app) { ,body: '' }); - hbs.render(path.join(cfg.paths.layouts, req.params.layout + '.hbs'), res.locals, + hbs.render(path.join(cfg.sources.layouts, req.params.layout + '.hbs'), res.locals, function(err, html) { if (err) { var error = utils.error('Unable to render the layout', err); @@ -142,7 +142,7 @@ module.exports = function(app) { ,helpers: { test: null } }); - hbs.render(path.join(cfg.pathsAbsolute.layouts, cfg.defaultLayoutName + '.hbs'), res.locals, + hbs.render(path.join(cfg.sources.layouts, cfg.defaultLayoutName + '.hbs'), res.locals, function(err, html) { if (err) { var error = utils.error('Unable to render the modules in the default template', err); @@ -158,7 +158,7 @@ module.exports = function(app) { // Look for a view with the name supplied by the catch-all route ,_subPage: function(req, res, next) { - fs.exists(path.join(cfg.pathsAbsolute.views, req.params.view + '.hbs'), function(exists) { + fs.exists(path.join(cfg.sources.views, req.params.view + '.hbs'), function(exists) { if (exists) { try { res.render(req.params.view, { diff --git a/frontend/_public/test/lib/jquery-iframe.js b/frontend/_public/lib/test/jquery-iframe.js similarity index 100% rename from frontend/_public/test/lib/jquery-iframe.js rename to frontend/_public/lib/test/jquery-iframe.js diff --git a/frontend/_public/test/lib/qunit-1.12.0.css b/frontend/_public/lib/test/qunit-1.12.0.css similarity index 100% rename from frontend/_public/test/lib/qunit-1.12.0.css rename to frontend/_public/lib/test/qunit-1.12.0.css diff --git a/frontend/_public/test/lib/qunit-1.12.0.js b/frontend/_public/lib/test/qunit-1.12.0.js similarity index 100% rename from frontend/_public/test/lib/qunit-1.12.0.js rename to frontend/_public/lib/test/qunit-1.12.0.js diff --git a/frontend/_public/test/lib/qunit-90afd90147.js b/frontend/_public/lib/test/qunit-90afd90147.js similarity index 100% rename from frontend/_public/test/lib/qunit-90afd90147.js rename to frontend/_public/lib/test/qunit-90afd90147.js diff --git a/frontend/_public/test/test.js b/frontend/_public/lib/test/test.js similarity index 100% rename from frontend/_public/test/test.js rename to frontend/_public/lib/test/test.js diff --git a/frontend/views/_test-modules.hbs b/frontend/views/_test-modules.hbs index 8bca522..91168e4 100644 --- a/frontend/views/_test-modules.hbs +++ b/frontend/views/_test-modules.hbs @@ -4,8 +4,8 @@ {{#if showUi}} {{/if}} {{!----}} - - + + {{/env}} - {{#env "development"}}{{/env}} + {{#env "development"}}{{/env}} diff --git a/lib/configure.js b/lib/configure.js index c0bb527..f2f630b 100644 --- a/lib/configure.js +++ b/lib/configure.js @@ -5,19 +5,22 @@ * Additional configs can be created with .merge() * @type {{merge: Function, get: Function}} */ -var convict = require('convict') +var nodeEnv = process.env.NODE_ENV !== 'production' ? 'development' : 'production' + ,convict = require('convict') ,path = require('path') ,fs = require('fs') - ,pkg = require('../package.json') + ,appPath = require.resolve('./configure').split('/lib')[0] + //,appPath = path.dirname(require.resolve('./configure')) + ,pkg = require(path.join(appPath, 'package.json')) ,projectConfig = {} ,dynamicDefaults = { - appPath : process.cwd() + appPath : appPath ,xtcVersion : pkg.xtcVersion ,configPath : pkg.configPath } ,projectConfigPath = pkg.configPath - ,projectConfigNames = require( path.join(dynamicDefaults.appPath, projectConfigPath, 'configs.json') ) + ,projectConfigNames = require( path.join(appPath, projectConfigPath, 'configs.json') ) ; @@ -33,14 +36,14 @@ var mergeConfigs = function(configPath, configNames, config) { config = convict(config || projectConfig); //configPath = path.join(config.get('appPath'), configPath); - configPath = path.join(process.cwd(), configPath); + configPath = path.resolve(appPath, configPath); configNames = configNames || []; configNames.forEach(function(configName) { var file; // Ignore local config in production mode - if (configName == 'local' && process.env.NODE_ENV === 'production') { return; } + if (configName == 'local' && nodeEnv === 'production') { return; } file = path.join(configPath, 'config-'+configName); file += configName === 'default' ? '.js' : '.json'; @@ -60,20 +63,9 @@ var mergeConfigs = function(configPath, configNames, config) { } }); - try { - config.validate(); - } - catch (e) { - // If not in test mode; print validation errors and exit. - if (process.env.NODE_ENV && process.env.NODE_ENV !== 'test') { - console.error('\nConfiguration error(s):\n' + e.message); - process.exit(1); - - } - } - // be informative process.env.NODE_ENV && process.env.NODE_ENV !== 'test' + //process.env.NODE_ENV && process.env.NODE_ENV !== 'foo' && configsUsed.push('env') && console.log('configuration:', configsUsed.join(' < ')); @@ -82,28 +74,98 @@ var mergeConfigs = function(configPath, configNames, config) { /** - * Build some paths and create absolute paths from the cfg.paths using our base path + * Build some paths and create absolute paths from the cfg.sources using our base path */ var configurePaths = function configurePaths(cfg) { - var paths = cfg.get('paths') - ,baseDirName = process.env.NODE_ENV == 'development' ? 'baseDirNameDev' : 'baseDirNameDist' + var sourcesBasePath = cfg.get('sourcesBasePath') + ,sources = cfg.get('sources') + ,build = cfg.get('build') + ,buildBaseUri + ,buildDir = nodeEnv == 'development' ? build.baseDirNameDev : build.baseDirNameDist + ,buildPath = path.join(cfg.get('buildBasePath'), buildDir) + ,keys, key + ,i ; - cfg.set('buildUriPrefix', cfg.get('staticUriPrefix') + '/' + cfg.get('static.build')[baseDirName] +'/'); + buildBaseUri = cfg.get('staticBaseUri') + '/' + buildDir +'/'; + cfg.set('buildBaseUri', buildBaseUri); + cfg.set('cssUri', buildBaseUri + build.css.dirName + build.css.external[nodeEnv]); + cfg.set('jsUri', buildBaseUri + build.js.dirName + build.js.external[nodeEnv]); + cfg.set('testUri', buildBaseUri + build.js.dirName + 'test.js'); + + // Resolve absolute paths from relative paths in config files - // Create absolute paths + cfg.set('staticPath', path.resolve(cfg.get('staticPath'))); + cfg.set('routesPath', path.resolve(cfg.get('routesPath'))); + cfg.set('buildBasePath', path.resolve(cfg.get('buildBasePath'))); - for (pathName in paths) { - cfg.set( 'pathsAbsolute.'+pathName, path.join( cfg.get('appPath'), paths[pathName]) ); + keys = Object.keys(sources); + for (i = 0; i < keys.length; i++) { + key = keys[i]; + cfg.set( 'sources.'+key, path.resolve( sourcesBasePath, sources[key]) ); } + build.css.inline[nodeEnv] && + cfg.set('build.css.inline', path.resolve( buildPath, build.css.inline[nodeEnv] )); + + build.css.external[nodeEnv] && + cfg.set('build.css.external', path.resolve( buildPath, build.css.external[nodeEnv] )); + + build.js.inline[nodeEnv] && + cfg.set('build.js.inline', path.resolve( buildPath, build.js.inline[nodeEnv] )); + + build.js.external[nodeEnv] && + cfg.set('build.js.external', path.resolve( buildPath, build.js.external[nodeEnv] )); + + cfg.set('build.spritesheets', path.resolve( buildPath, build.spriteSheets.dirName )); + return cfg; }; +function makeBuildPaths(cfg) { + var build = cfg.get('build') + ,buildDir = nodeEnv == 'development' ? build.baseDirNameDev : build.baseDirNameDist + ,buildPath = path.join(cfg.get('buildBasePath'), buildDir) + ; + + build.css.inline[nodeEnv] && + cfg.set('build.css.inline', path.resolve( buildPath, build.css.inline[nodeEnv] )); + + build.css.external[nodeEnv] && + cfg.set('build.css.external', path.resolve( buildPath, build.css.external[nodeEnv] )); + + build.js.inline[nodeEnv] && + cfg.set('build.js.inline', path.resolve( buildPath, build.js.inline[nodeEnv] )); + + build.js.external[nodeEnv] && + cfg.set('build.js.external', path.resolve( buildPath, build.js.external[nodeEnv] )); + + cfg.set('build.spritesheets', path.resolve( buildPath, build.spriteSheets.dirName )); + + return cfg; +} + + +function validate(config) { + try { + config.validate(); + } + catch (e) { + // If not in test mode; print validation errors and exit. + if (process.env.NODE_ENV && process.env.NODE_ENV !== 'test') { + console.error('\nConfiguration error(s):\n' + e.message); + process.exit(1); + } + } +} + + // Create the project config. projectConfig = mergeConfigs( projectConfigPath, projectConfigNames ); -projectConfig = configurePaths(projectConfig).root(); // todo: remove root when implementing full convict integration +validate(projectConfig); +projectConfig = configurePaths(projectConfig); +projectConfig = projectConfig.root(); // todo: remove .root() when implementing full convict integration module.exports = { @@ -117,7 +179,9 @@ module.exports = { */ merge: function(configPath, configNames, config) { var merged = mergeConfigs(configPath, configNames, config); - return configurePaths(merged).root(); // todo: remove root when implementing full convict integration + merged = configurePaths(merged); + validate(merged); + return merged.root(); // todo: remove .root() when implementing full convict integration } /** * Get the cached project configuration diff --git a/lib/handlebars-helpers-xtc.js b/lib/handlebars-helpers-xtc.js index 16ce636..b544051 100644 --- a/lib/handlebars-helpers-xtc.js +++ b/lib/handlebars-helpers-xtc.js @@ -15,7 +15,7 @@ if (NODE_ENV !== 'production') NODE_ENV = 'development'; if (NODE_ENV == 'development') { hbs = exphbs.create({ handlebars: handlebars }); - hbs.loadTemplate(path.join(cfg.pathsAbsolute.views, '_test-modules.hbs'), function(err, template) { + hbs.loadTemplate(path.join(cfg.sources.views, '_test-modules.hbs'), function(err, template) { testTemplate = template; }); } @@ -40,8 +40,7 @@ helpers.mod = require('./mod-helper.js'); * @returns {handlebars.SafeString} */ helpers.inline = function(inlineAssetName, options) { - var baseDirName = NODE_ENV == 'development' ? 'baseDirNameDev' : 'baseDirNameDist' - ,file = path.join(cfg.pathsAbsolute.staticBaseDir, cfg.static.build[baseDirName], cfg.static.build[inlineAssetName].inline[NODE_ENV]) + var file = cfg.build[inlineAssetName].inline ,cached = cache[inlineAssetName] ,content ,err @@ -77,8 +76,8 @@ helpers.test = function() { ,showUi: cfg.QUnitFE.showUi ,reorder: 'false' ,'static': { - prefix: cfg.staticUriPrefix - ,build: {test: cfg.staticUriPrefix + '/' + cfg.static.build.baseDirNameDev +'/test.js'} + base: cfg.staticBaseUri + ,build: {test: cfg.testUri} } }); diff --git a/lib/helpers.js b/lib/helpers.js index f6309dd..56c1449 100644 --- a/lib/helpers.js +++ b/lib/helpers.js @@ -12,9 +12,7 @@ var assert = require('assert') if (NODE_ENV != 'production') { NODE_ENV = 'development' } // for useful error message when an asset is not found -cssUri = cfg.buildUriPrefix + cfg.static.build.css.external[NODE_ENV]; -jsUri = cfg.buildUriPrefix + cfg.static.build.js.external[NODE_ENV]; -assetsRegExp = new RegExp(cssUri +'|'+ jsUri); +assetsRegExp = new RegExp(cfg.cssUri +'|'+ cfg.jsUri); function getSmartAuth(basicAuth) { @@ -85,7 +83,6 @@ module.exports.docTitle = function docTitle(pageName) { // todo: should probably * e.g. create URLs to asset files */ module.exports.makeLocals = function() { - var uriPrefix = cfg.staticUriPrefix + '/'; NODE_ENV == 'development' && (cfg.siteName += ' (Dev)'); @@ -95,15 +92,15 @@ module.exports.makeLocals = function() { ,node_env: NODE_ENV // Asset URIs ,'static': { - prefix: cfg.staticUriPrefix - ,img: uriPrefix + cfg.static.img + base: cfg.staticBaseUri + ,img: cfg.staticBaseUri +'/'+ cfg.static.img // generated assets ,build: { js: { - external: cfg.buildUriPrefix + cfg.static.build.js.external[NODE_ENV] + external: cfg.jsUri } ,css: { - external: cfg.buildUriPrefix + cfg.static.build.css.external[NODE_ENV] + external: cfg.cssUri } } } diff --git a/lib/mod-render.js b/lib/mod-render.js index d932fd9..f6e913c 100644 --- a/lib/mod-render.js +++ b/lib/mod-render.js @@ -152,7 +152,7 @@ function getModTemplate(options) { ,err ,template = templateName == moduleName ? moduleName : moduleName + '-' + templateName ,modDirName = cfg.moduleDirName.replace('{{name}}', moduleName) - ,modDir = path.join( cfg.paths.modulesBaseDir, modDirName) + ,modDir = path.join( cfg.sources.modulesBaseDir, modDirName) ,file = path.join(modDir, template + '.hbs') ,returnValue ; @@ -181,7 +181,7 @@ function getModTemplate(options) { if (annotateModules) { returnValue.name = moduleName; returnValue.file = template + '.hbs'; - returnValue.path = modDir.replace(cfg.appPath, ''); + returnValue.path = modDir.replace(cfg.appPath + '/', ''); cfg.repository && (returnValue.repository = cfg.repository + returnValue.path); } return returnValue; diff --git a/lib/overview.js b/lib/overview.js index fa16135..add7e1b 100644 --- a/lib/overview.js +++ b/lib/overview.js @@ -20,10 +20,10 @@ var fs = require('fs') module.exports = function(appConfig) { cfg = appConfig; - modulePath = cfg.paths.modulesBaseDir; + modulePath = cfg.sources.modulesBaseDir; moduleFolderPrefix = cfg.moduleDirName.replace('{{name}}', '').replace('/', ''); - views = fs.readdirSync(cfg.pathsAbsolute.views); - layouts = fs.readdirSync(cfg.pathsAbsolute.layouts); + views = fs.readdirSync(cfg.sources.views); + layouts = fs.readdirSync(cfg.sources.layouts); moduleCandidates = fs.readdirSync(modulePath); pinnedViews = require(path.join(cfg.appPath, cfg.configPath, 'pinned-views.json')); @@ -38,7 +38,7 @@ function isUserView(fileName) { return (fileName.indexOf('_') === 0 ? false : true) && - fs.statSync( path.join(cfg.pathsAbsolute.views, fileName) ).isFile() + fs.statSync( path.join(cfg.sources.views, fileName) ).isFile() ; } @@ -46,7 +46,7 @@ function isUserLayout(fileName) { return (fileName.indexOf('_') === 0 ? false : true) && - fs.statSync( path.join(cfg.pathsAbsolute.layouts, fileName) ).isFile() + fs.statSync( path.join(cfg.sources.layouts, fileName) ).isFile() ; } @@ -69,7 +69,7 @@ function file2ViewInfo(file) { ,pinnedIndex = pinnedViews.indexOf(name) return { name: name - ,repoUri: repositoryUri(cfg.paths.views +'/'+ file) + ,repoUri: repositoryUri(cfg.sources.views +'/'+ file) ,pinnedIndex: pinnedViews.indexOf(name) ,isPinned: pinnedIndex > -1 } @@ -78,14 +78,14 @@ function file2ViewInfo(file) { function file2LayoutInfo(file) { return { name: file.replace('.hbs', '') - ,repoUri: repositoryUri(cfg.paths.layouts +'/'+ file) + ,repoUri: repositoryUri(cfg.sources.layouts +'/'+ file) } } function file2Template(file, dir, modName) { return { name: file.replace(modName+'-', '').replace('.hbs', '') - ,repoUri: repositoryUri(cfg.paths.modulesBaseDir + '/' + dir +'/'+ file) + ,repoUri: repositoryUri(cfg.sources.modulesBaseDir + '/' + dir +'/'+ file) } } @@ -99,13 +99,14 @@ function directory2Module(dir) { } function getModuleTemplates(dir, modName) { - return fs.readdirSync(path.join(cfg.paths.modulesBaseDir, dir)).filter(isHbsFile).map(function(file) { + return fs.readdirSync(path.join(cfg.sources.modulesBaseDir, dir)).filter(isHbsFile).map(function(file) { return file2Template(file, dir, modName); }); } -function repositoryUri(path) { - return cfg.repository ? (cfg.repository + path) : null; +function repositoryUri(dir) { + dir = path.relative(cfg.appPath, dir); + return cfg.repository ? (cfg.repository + dir) : null; } function sortPinnedViews(a, b) { diff --git a/test/assets/config-assets-uri.json b/test/assets/config-assets-uri.json index 76829f7..e2beaca 100644 --- a/test/assets/config-assets-uri.json +++ b/test/assets/config-assets-uri.json @@ -1,28 +1,84 @@ { "enableSpritesBuilding": true - // File system paths relative to app.js, a property called app.config.pathsAbsolute will be generated from them - ,"paths": { - // helpers: hardcoded in apps.js - "inline" : "test/assets/fixtures/uri/_inline" - ,"base" : "test/assets/fixtures/uri/_base" - ,"application" : "test/assets/fixtures/uri/_application" + + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // Frontend sources + // Paths to frontend source folders relative to app.js, will be resolved to absolute paths + + // base path to the frontend sources, can be empty + ,"sourcesBasePath" : "test/assets/fixtures/uri" + ,"sources": { + "inline" : "_inline" + ,"base" : "_base" + ,"application" : "_application" //,"views" : "frontend/views" //,"templates" : "frontend/views/templates" // Path to the Terrific modules directories - ,"modulesBaseDir" : "test/assets/fixtures/uri/modules" - // Path to the static assets, used by Express and by the 'asset' template helper - ,"staticBaseDir" : "test/assets/expected/" + ,"modulesBaseDir" : "modules" } + ,"defaultLayoutName" : "default" + ,"moduleDirName" : "{{name}}" // A pattern for module folder names, {{name}} will be replaced. + ,"skinsDirName" : "skins" - // URI prefix for static assets, e.g. '/static', empty string for none - ,"staticUriPrefix": "/static" - ,"static": { - // URIs to generated assets - "build": { - // baseDirName is relative to paths.staticBaseDir - "baseDirNameDev": "../build" - ,"baseDirNameDist": "../dist" + + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // Frontend asset build destinations + // Destination paths and file names. Paths relative to app.js, will be resolved to absolute paths. + + ,"buildBasePath" : "test/assets" + ,"build": { + // baseDirNameX is relative to buildBasePath + "baseDirNameDev" : "build", + "baseDirNameDist" : "dist" + + // js and css are relative to baseDirNameX + ,"js": { + "dirName" : "" + // to inline scripts in a template, usage: {{inline "js"}} + ,"inline": { + "development" : "inline.js" + ,"production" : "inline.min.js" + } + // URI of the generated main js file, usage: {{static.build.js.external}} + , + "external": { + "development" : "external.js" + ,"production" : "external.min.js" + } + }, + "css": { + "dirName" : "" + // to inline styles in a template, usage: {{inline "css"}} + ,"inline": { + "development" : "inline.css" + ,"production" : "inline.min.css" + }, + // URI of the generated main css file, usage: {{static.build.css.external}} + "external": { + "development" : "external.css" + ,"production" : "external.min.css" + } } + ,"spriteSheets": { + "dirName" : "" + } + } + + + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // Routing + + // URIs for use in layouts are constructed from the following data + + // URI prefix for static assets, e.g. '/static', empty string for none + , "staticBaseUri" : "/static" + + // Physical path to the static assets, used by Express and by the 'asset' template helper + ,"staticPath" : "test/assets/expected/" + + // list static asset sub-paths to create direct references for, for use in templates. Relative to staticPath + , "static": { + "img" : "img" } } \ No newline at end of file diff --git a/test/assets/config-assets.json b/test/assets/config-assets.json index 19f099e..85fa539 100644 --- a/test/assets/config-assets.json +++ b/test/assets/config-assets.json @@ -1,26 +1,67 @@ { "enableSpritesBuilding": true - // File system paths relative to app.js, a property called app.config.pathsAbsolute will be generated from them - ,"paths": { - // helpers: hardcoded in apps.js - "inline" : "test/assets/fixtures/default/_inline" - ,"base" : "test/assets/fixtures/default/_base" - ,"application" : "test/assets/fixtures/default/_application" + + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // Frontend sources + // Paths to frontend source folders relative to app.js, will be resolved to absolute paths + + // base path to the frontend sources, can be empty + ,"sourcesBasePath" : "test/assets/fixtures/default" + ,"sources": { + "inline" : "_inline" + ,"base" : "_base" + ,"application" : "_application" //,"views" : "frontend/views" //,"templates" : "frontend/views/templates" // Path to the Terrific modules directories - ,"modulesBaseDir" : "test/assets/fixtures/default/modules" - // Path to the static assets, used by Express and by the 'asset' template helper - ,"staticBaseDir" : "test/assets/expected/" + ,"modulesBaseDir" : "modules" } + ,"defaultLayoutName" : "default" + ,"moduleDirName" : "{{name}}" // A pattern for module folder names, {{name}} will be replaced. + ,"skinsDirName" : "skins" + - ,"static": { - // URIs to generated assets - "build": { - // baseDirName is relative to paths.staticBaseDir - "baseDirNameDev": "../build" - ,"baseDirNameDist": "../dist" + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // Frontend asset build destinations + // Destination paths and file names. Paths relative to app.js, will be resolved to absolute paths. + + ,"buildBasePath" : "test/assets" + ,"build": { + // baseDirNameX is relative to buildBasePath + "baseDirNameDev" : "build", + "baseDirNameDist" : "dist" + + // js and css are relative to baseDirNameX + ,"js": { + "dirName" : "" + // to inline scripts in a template, usage: {{inline "js"}} + ,"inline": { + "development" : "inline.js" + ,"production" : "inline.min.js" + } + // URI of the generated main js file, usage: {{static.build.js.external}} + , + "external": { + "development" : "external.js" + ,"production" : "external.min.js" + } + }, + "css": { + "dirName" : "" + // to inline styles in a template, usage: {{inline "css"}} + ,"inline": { + "development" : "inline.css" + ,"production" : "inline.min.css" + }, + // URI of the generated main css file, usage: {{static.build.css.external}} + "external": { + "development" : "external.css" + ,"production" : "external.min.css" + } + } + ,"spriteSheets": { + "dirName" : "" } } } \ No newline at end of file diff --git a/test/configure/configure.js b/test/configure/configure.js index 9dd509e..0acf95b 100644 --- a/test/configure/configure.js +++ b/test/configure/configure.js @@ -41,7 +41,7 @@ describe('configure', function() { it('configure: creates absolute app paths', function() { assert.equal(config.appPath, appPath); - assert.equal(config.pathsAbsolute.staticBaseDir, path.join(appPath, 'frontend/_static/')); + assert.equal(config.staticPath, path.join(appPath, 'frontend/_static')); }); }); diff --git a/test/configure/fixtures/config-project.json b/test/configure/fixtures/config-project.json index 627f839..99771b2 100644 --- a/test/configure/fixtures/config-project.json +++ b/test/configure/fixtures/config-project.json @@ -1,10 +1,7 @@ // Never commit authentication data to a public repository! { "devPort": 3333 - // static assets URIs are relative to 'staticUriPrefix' - // file system paths relative to app.js, a property called app.config.pathsAbsolute will be generated from them - ,"paths": { - // path to the static assets, used by Express and by the 'asset' template helper, - "staticBaseDir": "frontend/_static/" - } + + // Physical path to the static assets, used by Express and by the 'asset' template helper + ,"staticPath": "frontend/_static" } \ No newline at end of file diff --git a/test/terrific-modules/config-terrific-annotate.json b/test/terrific-modules/config-terrific-annotate.json index eeed98e..5a639cf 100644 --- a/test/terrific-modules/config-terrific-annotate.json +++ b/test/terrific-modules/config-terrific-annotate.json @@ -3,8 +3,8 @@ "development": true } ,"repository": "https://github.com/" - // file system paths relative to app.js, a property called app.config.pathsAbsolute will be generated from them - ,"paths": { + ,"sourcesBasePath" : "" + ,"sources": { // path to the Terrific modules directories "modulesBaseDir": "test/terrific-modules/fixtures" } diff --git a/test/terrific-modules/config-terrific.json b/test/terrific-modules/config-terrific.json index 8b85eee..9139eb6 100644 --- a/test/terrific-modules/config-terrific.json +++ b/test/terrific-modules/config-terrific.json @@ -2,8 +2,8 @@ "annotateModules": { "development": false } - // file system paths relative to app.js, a property called app.config.pathsAbsolute will be generated from them - ,"paths": { + ,"sourcesBasePath" : "" + ,"sources": { // path to the Terrific modules directories "modulesBaseDir": "test/terrific-modules/fixtures" } diff --git a/test/terrific-modules/expected/basic/basic-read-error.html b/test/terrific-modules/expected/basic/basic-read-error.html deleted file mode 100644 index c87b39c..0000000 --- a/test/terrific-modules/expected/basic/basic-read-error.html +++ /dev/null @@ -1,3 +0,0 @@ -
-Can't read template file. Module: qwerty, Template: uiop.hbs.
Reason: ENOENT, no such file or directory 'test/terrific-modules/fixtures/mod-qwerty/qwerty-uiop.hbs' -
\ No newline at end of file diff --git a/test/terrific-modules/terrific.js b/test/terrific-modules/terrific.js index 6b109f5..abb23ac 100644 --- a/test/terrific-modules/terrific.js +++ b/test/terrific-modules/terrific.js @@ -35,8 +35,7 @@ describe('renderModule', function() { } catch (e) { // nothing to do here } - var expected = grunt.file.read('test/terrific-modules/expected/basic/basic-read-error.html'); - assert.equal(actual, expected); + assert.ok(actual.indexOf("Can't read template file. Module: qwerty, Template: uiop.hbs.
Reason: ENOENT, no such file or directory") !== -1); }); it('should render a module with alternate template', function() { var actual = renderModule({}, { name: 'basic', template: 'alternate' }); From 772aa4f98fe541243c8b46075e27d7660079daf0 Mon Sep 17 00:00:00 2001 From: Marc Diethelm Date: Tue, 28 Jan 2014 10:50:56 +0100 Subject: [PATCH 5/5] 0.8.0-beta3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a7206cd..c495507 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "xtc-project", "description": "an xtc project", "version": "0.0.0", - "xtcVersion": "0.8.0-beta2", + "xtcVersion": "0.8.0-beta3", "private": true, "main": "app.js", "dependencies": {