From c1e7d98fe379625f91ced45b6a44fb2caf3f1520 Mon Sep 17 00:00:00 2001 From: tonylukasavage Date: Thu, 23 May 2013 17:40:08 -0400 Subject: [PATCH 1/5] style arrays are now available at runtime! --- Alloy/commands/compile/index.js | 51 +++++++++++++++++++++++++++------ Alloy/common/constants.js | 4 ++- 2 files changed, 45 insertions(+), 10 deletions(-) diff --git a/Alloy/commands/compile/index.js b/Alloy/commands/compile/index.js index a88322f9c..792758c00 100755 --- a/Alloy/commands/compile/index.js +++ b/Alloy/commands/compile/index.js @@ -3,6 +3,7 @@ var path = require('path'), wrench = require('wrench'), vm = require('vm'), uglifyjs = require('uglify-js'), + jsonlint = require('jsonlint'), sourceMapper = require('./sourceMapper'), styler = require('./styler'), _ = require("../../lib/alloy/underscore")._, @@ -131,13 +132,26 @@ module.exports = function(args, program) { logger.debug('----- BASE RUNTIME FILES -----'); U.installPlugin(path.join(alloyRoot,'..'), paths.project); - // Copy in all assets, libs, and Alloy runtime files + // copy in all lib resources from alloy module U.updateFiles(path.join(alloyRoot, 'lib'), paths.resources); - wrench.mkdirSyncRecursive(path.join(paths.resourcesAlloy, CONST.DIR.COMPONENT), 0777); - wrench.mkdirSyncRecursive(path.join(paths.resourcesAlloy, CONST.DIR.WIDGET), 0777); - U.updateFiles(path.join(paths.app,CONST.DIR.ASSETS), paths.resources); - U.updateFiles(path.join(paths.app,CONST.DIR.LIB), paths.resources); - U.updateFiles(path.join(paths.app,'vendor'), paths.resources); + + // create runtime folder structure for alloy + _.each(['COMPONENT','WIDGET','RUNTIME_STYLE'], function(type) { + var p = path.join(paths.resourcesAlloy, CONST.DIR[type]); + wrench.mkdirSyncRecursive(p, 0777); + }); + + // Copy in all developer assets, libs, and additional resources + _.each(['ASSETS','LIB','VENDOR'], function(type) { + U.updateFiles(path.join(paths.app,CONST.DIR[type]), paths.resources); + }); + + // wrench.mkdirSyncRecursive(path.join(paths.resourcesAlloy, CONST.DIR.RUNTIME_STYLE), 0777); + // wrench.mkdirSyncRecursive(path.join(paths.resourcesAlloy, CONST.DIR.COMPONENT), 0777); + // wrench.mkdirSyncRecursive(path.join(paths.resourcesAlloy, CONST.DIR.WIDGET), 0777); + // U.updateFiles(path.join(paths.app,CONST.DIR.ASSETS), paths.resources); + // U.updateFiles(path.join(paths.app,CONST.DIR.LIB), paths.resources); + // U.updateFiles(path.join(paths.app,'vendor'), paths.resources); // copy in test specs if not in production if (alloyConfig.deploytype !== 'production') { @@ -292,6 +306,7 @@ function parseAlloyComponent(view,dir,manifest,noView) { __MAPMARKER_CONTROLLER_CODE__: '', }, widgetDir = dirname ? path.join(CONST.DIR.COMPONENT,dirname) : CONST.DIR.COMPONENT, + widgetStyleDir = dirname ? path.join(CONST.DIR.RUNTIME_STYLE,dirname) : CONST.DIR.RUNTIME_STYLE, state = { parent: {}, styles: [] }, files = {}; @@ -327,9 +342,16 @@ function parseAlloyComponent(view,dir,manifest,noView) { } files[fileType] = baseFile; }); - files.COMPONENT = path.join(compileConfig.dir.resourcesAlloy,CONST.DIR.COMPONENT); - if (dirname) { files.COMPONENT = path.join(files.COMPONENT,dirname); } - files.COMPONENT = path.join(files.COMPONENT,viewName+'.js'); + + _.each(['COMPONENT','RUNTIME_STYLE'], function(fileType) { + files[fileType] = path.join(compileConfig.dir.resourcesAlloy,CONST.DIR[fileType]); + if (dirname) { files[fileType] = path.join(files[fileType],dirname); } + files[fileType] = path.join(files[fileType],viewName+'.js'); + }); + + // files.COMPONENT = path.join(compileConfig.dir.resourcesAlloy,CONST.DIR.COMPONENT); + // if (dirname) { files.COMPONENT = path.join(files.COMPONENT,dirname); } + // files.COMPONENT = path.join(files.COMPONENT,viewName+'.js'); // we are processing a view, not just a controller if (!noView) { @@ -517,16 +539,27 @@ function parseAlloyComponent(view,dir,manifest,noView) { // prep the controller paths based on whether it's an app // controller or widget controller var targetFilepath = files.COMPONENT; + var runtimeStylePath = files.RUNTIME_STYLE; if (manifest) { wrench.mkdirSyncRecursive(path.join(compileConfig.dir.resourcesAlloy, CONST.DIR.WIDGET, manifest.id, widgetDir), 0777); + wrench.mkdirSyncRecursive(path.join(compileConfig.dir.resourcesAlloy, CONST.DIR.WIDGET, manifest.id, widgetStyleDir), 0777); CU.copyWidgetResources( [path.join(dir,CONST.DIR.ASSETS), path.join(dir,CONST.DIR.LIB)], compileConfig.dir.resources, manifest.id ); targetFilepath = path.join(compileConfig.dir.resourcesAlloy, CONST.DIR.WIDGET, manifest.id, widgetDir, viewName + '.js'); + runtimeStylePath = path.join(compileConfig.dir.resourcesAlloy, CONST.DIR.WIDGET, manifest.id, widgetStyleDir, viewName + '.js'); } + // write the compiled style array to a runtime module + var relativeStylePath = path.relative(compileConfig.dir.project,runtimeStylePath); + logger.info(' style: "' + relativeStylePath + '"'); + fs.writeFileSync( + runtimeStylePath, + 'module.exports = ' + JSON.stringify(state.styles) + ); + // generate the code and source map for the current controller sourceMapper.generateCodeAndSourceMap({ target: { diff --git a/Alloy/common/constants.js b/Alloy/common/constants.js index 4ea6a92d5..9272c9bf2 100755 --- a/Alloy/common/constants.js +++ b/Alloy/common/constants.js @@ -75,6 +75,7 @@ exports.FILE_EXT = { exports.DIR = { VIEW: 'views', STYLE: 'styles', + RUNTIME_STYLE: 'styles', CONTROLLER: 'controllers', MODEL: 'models', MODELCODE: 'models', @@ -84,7 +85,8 @@ exports.DIR = { WIDGET: 'widgets', LIB: 'lib', COMPONENT: 'controllers', - MAP: 'build/map' + MAP: 'build/map', + VENDOR: 'vendor' }; // constants identifying JS reserved words From 04cab0c4821b98324f646d77638048d32de8b36d Mon Sep 17 00:00:00 2001 From: tonylukasavage Date: Fri, 24 May 2013 10:00:12 -0400 Subject: [PATCH 2/5] clean undefined style keys out of the generated style array --- Alloy/commands/compile/styler.js | 5 +++++ test/lib/testUtils.js | 5 +++++ test/specs/compile.js | 25 +++++++++++++++++++++++++ 3 files changed, 35 insertions(+) diff --git a/Alloy/commands/compile/styler.js b/Alloy/commands/compile/styler.js index e3fbae834..ff29be637 100644 --- a/Alloy/commands/compile/styler.js +++ b/Alloy/commands/compile/styler.js @@ -141,6 +141,11 @@ exports.sortStyles = function(style, opts) { U.die('Invalid style specifier "' + key + '"'); } var newKey = match[2]; + + // skip any invalid style entries + if (newKey === 'undefined' && !match[1]) { continue; } + + // get the style key type switch(match[1]) { case '#': obj.isId = true; diff --git a/test/lib/testUtils.js b/test/lib/testUtils.js index 579bea231..306b6e451 100644 --- a/test/lib/testUtils.js +++ b/test/lib/testUtils.js @@ -150,6 +150,11 @@ exports.addMatchers = function() { toBeJavascript: toBeJavascript, toBeJavascriptFile: toBeJavascriptFile, toBeTssFile: toBeTssFile, + toHaveNoUndefinedStyles: function() { + return !_.find(this.actual, function(o) { + return o.key === 'undefined' && o.isApi + }); + }, toHaveSameContentAs: function(expected) { return fs.readFileSync(this.actual,'utf8') === fs.readFileSync(expected,'utf8'); }, diff --git a/test/specs/compile.js b/test/specs/compile.js index 2ff827eb2..444b05356 100644 --- a/test/specs/compile.js +++ b/test/specs/compile.js @@ -27,6 +27,8 @@ var alloyRoot = path.join(__dirname,'..','..'), // The alloy command test suite describe('alloy compile', function() { + TU.addMatchers(); + // Iterate through each test app and make sure it compiles for all platforms _.each(wrench.readdirSyncRecursive(paths.apps), function(file) { if (process.env.app && file !== process.env.app) { return; } @@ -76,6 +78,29 @@ describe('alloy compile', function() { }); }); + it('has no undefined style entries', function() { + var hrDir = path.join(paths.harness,'Resources'); + var cPaths = [ + path.join(hrDir,'alloy','styles'), + path.join(hrDir,platform.titaniumFolder,'alloy','styles') + ]; + + _.each(cPaths, function(cPath) { + if (!fs.existsSync(cPath)) { return; } + var files = wrench.readdirSyncRecursive(cPath); + _.each(files, function(file) { + var fullpath = path.join(cPath,file); + if (!fs.statSync(fullpath).isFile() || + !/\.js$/.test(fullpath)) { + return; + } + + var json = require(fullpath); + expect(json).toHaveNoUndefinedStyles(); + }); + }); + }); + var genFolder = path.join(paths.apps,file,GEN_FOLDER,platform.platform); if (!fs.existsSync(genFolder)) { return; } var hrFolder = path.join(paths.harness,'Resources'); From c5ecbdd69b721ef36f845270b899c832e28153a2 Mon Sep 17 00:00:00 2001 From: tonylukasavage Date: Fri, 24 May 2013 12:29:20 -0400 Subject: [PATCH 3/5] comment touch up --- Alloy/commands/compile/sourceMapper.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Alloy/commands/compile/sourceMapper.js b/Alloy/commands/compile/sourceMapper.js index 357fc304a..686efb5a1 100644 --- a/Alloy/commands/compile/sourceMapper.js +++ b/Alloy/commands/compile/sourceMapper.js @@ -116,18 +116,18 @@ exports.generateCodeAndSourceMap = function(generator, compileConfig) { })); ast.print(stream); - // create the generated code + // write the generated controller code var outfile = target.filepath; var relativeOutfile = path.relative(compileConfig.dir.project,outfile); wrench.mkdirSyncRecursive(path.dirname(outfile), 0777); fs.writeFileSync(outfile, stream.toString()); logger.info(' created: "' + relativeOutfile + '"'); - // create source map for the generated file + // write source map for the generated file var mapDir = path.join(compileConfig.dir.project,CONST.DIR.MAP); outfile = path.join(mapDir,relativeOutfile) + '.' + CONST.FILE_EXT.MAP; relativeOutfile = path.relative(compileConfig.dir.project,outfile); wrench.mkdirSyncRecursive(path.dirname(outfile), 0777); fs.writeFileSync(outfile, sourceMap.toString()); logger.debug(' map: "' + relativeOutfile + '"'); -}; \ No newline at end of file +}; From cc5588e5d984ad3bd49e1ae9b1b6d3a188387f54 Mon Sep 17 00:00:00 2001 From: tonylukasavage Date: Fri, 24 May 2013 12:45:34 -0400 Subject: [PATCH 4/5] ensure that full folder structure of potential styles is supported --- Alloy/commands/compile/index.js | 29 ++++++++++------------------- 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/Alloy/commands/compile/index.js b/Alloy/commands/compile/index.js index 792758c00..cd2244662 100755 --- a/Alloy/commands/compile/index.js +++ b/Alloy/commands/compile/index.js @@ -146,13 +146,6 @@ module.exports = function(args, program) { U.updateFiles(path.join(paths.app,CONST.DIR[type]), paths.resources); }); - // wrench.mkdirSyncRecursive(path.join(paths.resourcesAlloy, CONST.DIR.RUNTIME_STYLE), 0777); - // wrench.mkdirSyncRecursive(path.join(paths.resourcesAlloy, CONST.DIR.COMPONENT), 0777); - // wrench.mkdirSyncRecursive(path.join(paths.resourcesAlloy, CONST.DIR.WIDGET), 0777); - // U.updateFiles(path.join(paths.app,CONST.DIR.ASSETS), paths.resources); - // U.updateFiles(path.join(paths.app,CONST.DIR.LIB), paths.resources); - // U.updateFiles(path.join(paths.app,'vendor'), paths.resources); - // copy in test specs if not in production if (alloyConfig.deploytype !== 'production') { U.updateFiles(path.join(paths.app,'specs'), path.join(paths.resources,'specs')); @@ -349,10 +342,6 @@ function parseAlloyComponent(view,dir,manifest,noView) { files[fileType] = path.join(files[fileType],viewName+'.js'); }); - // files.COMPONENT = path.join(compileConfig.dir.resourcesAlloy,CONST.DIR.COMPONENT); - // if (dirname) { files.COMPONENT = path.join(files.COMPONENT,dirname); } - // files.COMPONENT = path.join(files.COMPONENT,viewName+'.js'); - // we are processing a view, not just a controller if (!noView) { // validate view @@ -552,14 +541,6 @@ function parseAlloyComponent(view,dir,manifest,noView) { runtimeStylePath = path.join(compileConfig.dir.resourcesAlloy, CONST.DIR.WIDGET, manifest.id, widgetStyleDir, viewName + '.js'); } - // write the compiled style array to a runtime module - var relativeStylePath = path.relative(compileConfig.dir.project,runtimeStylePath); - logger.info(' style: "' + relativeStylePath + '"'); - fs.writeFileSync( - runtimeStylePath, - 'module.exports = ' + JSON.stringify(state.styles) - ); - // generate the code and source map for the current controller sourceMapper.generateCodeAndSourceMap({ target: { @@ -574,6 +555,15 @@ function parseAlloyComponent(view,dir,manifest,noView) { } } }, compileConfig); + + // write the compiled style array to a runtime module + var relativeStylePath = path.relative(compileConfig.dir.project,runtimeStylePath); + logger.info(' created: "' + relativeStylePath + '"'); + wrench.mkdirSyncRecursive(path.dirname(runtimeStylePath), 0777); + fs.writeFileSync( + runtimeStylePath, + 'module.exports = ' + JSON.stringify(state.styles) + ); } function findModelMigrations(name, inDir) { @@ -676,6 +666,7 @@ function optimizeCompiledCode() { 'app.js', 'alloy/CFG.js', 'alloy/controllers/', + 'alloy/styles/', 'alloy/backbone.js', 'alloy/underscore.js' ]; From f9c16fbd6751a1a49f5d2d5402601b9ff9556355 Mon Sep 17 00:00:00 2001 From: tonylukasavage Date: Fri, 24 May 2013 14:53:49 -0400 Subject: [PATCH 5/5] testing/ALOY-612 test app --- .../testing/ALOY-612/controllers/index.js | 16 ++++++++ test/apps/testing/ALOY-612/styles/app.tss | 14 +++++++ test/apps/testing/ALOY-612/styles/index.tss | 41 +++++++++++++++++++ test/apps/testing/ALOY-612/views/index.xml | 8 ++++ 4 files changed, 79 insertions(+) create mode 100644 test/apps/testing/ALOY-612/controllers/index.js create mode 100644 test/apps/testing/ALOY-612/styles/app.tss create mode 100644 test/apps/testing/ALOY-612/styles/index.tss create mode 100644 test/apps/testing/ALOY-612/views/index.xml diff --git a/test/apps/testing/ALOY-612/controllers/index.js b/test/apps/testing/ALOY-612/controllers/index.js new file mode 100644 index 000000000..8aaaac257 --- /dev/null +++ b/test/apps/testing/ALOY-612/controllers/index.js @@ -0,0 +1,16 @@ +$.index.open(); + +var style = require('alloy/styles/index'); +var i, len; +for (i = 0, len = $.index.children.length; i < len; i++) { + var child = $.index.children[i]; + child.addEventListener('click', function(e) { + var id = e.source.id; + _.each(style, function(o) { + if (o.key === id && o.isId) { + // print each style that applies by ID to the source + Ti.API.info(JSON.stringify(o)); + } + }); + }); +} \ No newline at end of file diff --git a/test/apps/testing/ALOY-612/styles/app.tss b/test/apps/testing/ALOY-612/styles/app.tss new file mode 100644 index 000000000..c10f4ab81 --- /dev/null +++ b/test/apps/testing/ALOY-612/styles/app.tss @@ -0,0 +1,14 @@ +"Window": { + backgroundColor: '#fff', + fullscreen: false +} + +"Label": { + color: '#000', + height: Ti.UI.SIZE, + width: Ti.UI.SIZE +} + +"Button": { + color: '#500' +} \ No newline at end of file diff --git a/test/apps/testing/ALOY-612/styles/index.tss b/test/apps/testing/ALOY-612/styles/index.tss new file mode 100644 index 000000000..205c08b04 --- /dev/null +++ b/test/apps/testing/ALOY-612/styles/index.tss @@ -0,0 +1,41 @@ +"Button": { + top: '15dp' +} + +"#index": { + layout: 'vertical' +} + +"#index[platform=android]": { + exitOnClose: true +} + +"#info": { + top: '15dp', + textAlign: 'center', + width: '250dp', + font: { + fontSize: '18dp', + fontWeight: 'normal' + } +} + +"#button1": { + height: '70dp', + width: '250dp', + borderRadius: 8, + borderWidth: 2, + borderColor: '#500' +} + +"#button2": { + width: '100dp' +} + +"#button3": { + height: '40dp', + width: '200dp', + borderRadius: 32, + borderWidth: 1, + borderColor: '#0f0' +} \ No newline at end of file diff --git a/test/apps/testing/ALOY-612/views/index.xml b/test/apps/testing/ALOY-612/views/index.xml new file mode 100644 index 000000000..0f23885fc --- /dev/null +++ b/test/apps/testing/ALOY-612/views/index.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file