Skip to content

Commit

Permalink
Merge pull request #135 from appcelerator/ALOY-612
Browse files Browse the repository at this point in the history
[ALOY-612] Make styles available at runtime
  • Loading branch information
tonylukasavage committed May 24, 2013
2 parents 67798f1 + f9c16fb commit e53a614
Show file tree
Hide file tree
Showing 10 changed files with 153 additions and 13 deletions.
42 changes: 33 additions & 9 deletions Alloy/commands/compile/index.js
Expand Up @@ -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")._,
Expand Down Expand Up @@ -131,13 +132,19 @@ 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);
});

// copy in test specs if not in production
if (alloyConfig.deploytype !== 'production') {
Expand Down Expand Up @@ -292,6 +299,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 = {};

Expand Down Expand Up @@ -327,9 +335,12 @@ 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');
});

// we are processing a view, not just a controller
if (!noView) {
Expand Down Expand Up @@ -517,14 +528,17 @@ 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');
}

// generate the code and source map for the current controller
Expand All @@ -541,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) {
Expand Down Expand Up @@ -643,6 +666,7 @@ function optimizeCompiledCode() {
'app.js',
'alloy/CFG.js',
'alloy/controllers/',
'alloy/styles/',
'alloy/backbone.js',
'alloy/underscore.js'
];
Expand Down
6 changes: 3 additions & 3 deletions Alloy/commands/compile/sourceMapper.js
Expand Up @@ -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 + '"');
};
};
5 changes: 5 additions & 0 deletions Alloy/commands/compile/styler.js
Expand Up @@ -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;
Expand Down
4 changes: 3 additions & 1 deletion Alloy/common/constants.js
Expand Up @@ -75,6 +75,7 @@ exports.FILE_EXT = {
exports.DIR = {
VIEW: 'views',
STYLE: 'styles',
RUNTIME_STYLE: 'styles',
CONTROLLER: 'controllers',
MODEL: 'models',
MODELCODE: 'models',
Expand All @@ -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
Expand Down
16 changes: 16 additions & 0 deletions 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));
}
});
});
}
14 changes: 14 additions & 0 deletions 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'
}
41 changes: 41 additions & 0 deletions 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'
}
8 changes: 8 additions & 0 deletions test/apps/testing/ALOY-612/views/index.xml
@@ -0,0 +1,8 @@
<Alloy>
<Window>
<Label id="info">Click anything to see its ID style entry</Label>
<Button id="button1">button1</Button>
<Button id="button2">button2</Button>
<Button id="button3">button3</Button>
</Window>
</Alloy>
5 changes: 5 additions & 0 deletions test/lib/testUtils.js
Expand Up @@ -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');
},
Expand Down
25 changes: 25 additions & 0 deletions test/specs/compile.js
Expand Up @@ -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; }
Expand Down Expand Up @@ -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');
Expand Down

0 comments on commit e53a614

Please sign in to comment.