diff --git a/AppKit/Jakefile b/AppKit/Jakefile index 52a6c43be..899a0fe9f 100644 --- a/AppKit/Jakefile +++ b/AppKit/Jakefile @@ -19,7 +19,6 @@ appKitTask = framework ("AppKit", function(appKitTask) appKitTask.setLicense(BundleTask.License.LGPL_v2_1); appKitTask.setSources(AppKitFiles); appKitTask.setResources(new FileList("Resources/**/*")); - appKitTask.setPlatforms([BundleTask.Platform.Browser, BundleTask.Platform.CommonJS]); appKitTask.setFlattensSources(true); appKitTask.setInfoPlistPath("Info.plist"); diff --git a/AppKit/Themes/Aristo/Jakefile b/AppKit/Themes/Aristo/Jakefile index fac29cbd4..dccab04a2 100644 --- a/AppKit/Themes/Aristo/Jakefile +++ b/AppKit/Themes/Aristo/Jakefile @@ -8,7 +8,6 @@ blend ("Aristo.blend", function(aristoTask) aristoTask.setBuildPath(FILE.join($BUILD_DIR, $CONFIGURATION)); aristoTask.setThemeDescriptors(new FileList("ThemeDescriptors.j")); - aristoTask.setPlatforms([BundleTask.Platform.Browser, BundleTask.Platform.CommonJS]); aristoTask.setIdentifier("com.280n.blend.Aristo"); aristoTask.setResources(new FileList("Resources/*")); }); diff --git a/AppKit/Themes/CommonJS/blendtask.j b/AppKit/Themes/CommonJS/blendtask.j index ec852c43b..69c4d348b 100644 --- a/AppKit/Themes/CommonJS/blendtask.j +++ b/AppKit/Themes/CommonJS/blendtask.j @@ -14,7 +14,7 @@ var FILE = require("file"), function BlendTask(aName) { BundleTask.apply(this, arguments); - + this._themeDescriptors = []; this._keyedThemes = []; } @@ -31,7 +31,7 @@ BlendTask.prototype.infoPlist = function() { var infoPlist = BundleTask.prototype.infoPlist.apply(this, arguments); - infoPlist.setValue("CPKeyedThemes", this._keyedThemes); + infoPlist.setValue("CPKeyedThemes", require("util").unique(this._keyedThemes)); return infoPlist; } @@ -54,52 +54,56 @@ BlendTask.prototype.defineTasks = function() } BlendTask.prototype.defineSourceTasks = function() -{ +{ } BlendTask.prototype.defineThemeDescriptorTasks = function() { - var themeDescriptors = this.themeDescriptors(), - resourcesPath = this.resourcesPath(), - intermediatesPath = FILE.join(this.buildIntermediatesProductPath(), "Browser" + ".platform", "Resources"), - staticPath = this.buildProductStaticPathForPlatform("Browser"), - keyedThemes = this._keyedThemes, - themesTaskName = this.name() + ":themes"; - - this.enhance(themesTaskName); - - objj_import(themeDescriptors.toArray(), YES, function() + this.flattenedEnvironments().forEach(function(anEnvironment) { - [BKThemeDescriptor allThemeDescriptorClasses].forEach(function(aClass) + var folder = anEnvironment.name() + ".environment", + themeDescriptors = this.themeDescriptors(), + resourcesPath = this.resourcesPath(), + intermediatesPath = FILE.join(this.buildIntermediatesProductPath(), folder, "Resources"), + staticPath = this.buildProductStaticPathForEnvironment(anEnvironment), + keyedThemes = this._keyedThemes, + themesTaskName = this.name() + ":themes"; + + this.enhance(themesTaskName); + + objj_import(themeDescriptors.toArray(), YES, function() { - var keyedThemePath = FILE.join(intermediatesPath, [aClass themeName] + ".keyedtheme"); + [BKThemeDescriptor allThemeDescriptorClasses].forEach(function(aClass) + { + var keyedThemePath = FILE.join(intermediatesPath, [aClass themeName] + ".keyedtheme"); - filedir (keyedThemePath, themesTaskName); - filedir (staticPath, [keyedThemePath]); + filedir (keyedThemePath, themesTaskName); + filedir (staticPath, [keyedThemePath]); - keyedThemes.push([aClass themeName] + ".keyedtheme"); + keyedThemes.push([aClass themeName] + ".keyedtheme"); + }); }); - }); - require("browser/timeout").serviceTimeouts(); + require("browser/timeout").serviceTimeouts(); - task (themesTaskName, function() - { - [BKThemeDescriptor allThemeDescriptorClasses].forEach(function(aClass) + task (themesTaskName, function() { - var themeTemplate = [[BKThemeTemplate alloc] init]; + [BKThemeDescriptor allThemeDescriptorClasses].forEach(function(aClass) + { + var themeTemplate = [[BKThemeTemplate alloc] init]; - [themeTemplate setValue:[aClass themeName] forKey:@"name"]; + [themeTemplate setValue:[aClass themeName] forKey:@"name"]; - var objectTemplates = [aClass themedObjectTemplates], - data = cibDataFromTopLevelObjects(objectTemplates.concat([themeTemplate])), - fileContents = themeFromCibData(data); + var objectTemplates = [aClass themedObjectTemplates], + data = cibDataFromTopLevelObjects(objectTemplates.concat([themeTemplate])), + fileContents = themeFromCibData(data); - // No filedir in this case, so we have to make it ourselves. - FILE.mkdirs(intermediatesPath); - FILE.write(FILE.join(intermediatesPath, [aClass themeName] + ".keyedtheme"), MARKER_TEXT + ";" + fileContents.length + ";" + fileContents, { charset:"UTF-8" }); + // No filedir in this case, so we have to make it ourselves. + FILE.mkdirs(intermediatesPath); + FILE.write(FILE.join(intermediatesPath, [aClass themeName] + ".keyedtheme"), MARKER_TEXT + ";" + fileContents.length + ";" + fileContents, { charset:"UTF-8" }); + }); }); - }); + }, this); } function cibDataFromTopLevelObjects(objects) @@ -113,7 +117,7 @@ function cibDataFromTopLevelObjects(objects) var index = 0, count = objects.length; - + for (; index < count; ++index) { objectData._objectsValues[index] = objectData._fileOwner; @@ -131,7 +135,7 @@ function themeFromCibData(data) { var cib = [[CPCib alloc] initWithData:data], topLevelObjects = []; - + [cib _setAwakenCustomResources:NO]; [cib instantiateCibWithExternalNameTable:[CPDictionary dictionaryWithObject:topLevelObjects forKey:CPCibTopLevelObjects]]; @@ -142,7 +146,7 @@ function themeFromCibData(data) while (count--) { var object = topLevelObjects[count]; - + templates = templates.concat([object blendThemeObjectTemplates]); if ([object isKindOfClass:[BKThemeTemplate class]]) @@ -175,22 +179,22 @@ function themeFromCibData(data) - (CPArray)blendThemeObjectTemplates { var theClass = [self class]; - + if ([theClass isKindOfClass:[BKThemedObjectTemplate class]]) return [self]; - + if ([theClass isKindOfClass:[CPView class]]) { var templates = [], subviews = [self subviews], count = [subviews count]; - + while (count--) templates = templates.concat([subviews[count] blendThemeObjectTemplates]); - + return templates; } - + return []; } @@ -201,19 +205,19 @@ function themeFromCibData(data) - (void)blendAddThemedObjectAttributesToTheme:(CPTheme)aTheme { var themedObject = [self valueForKey:@"themedObject"]; - + if (!themedObject) { var subviews = [self subviews]; - + if ([subviews count] > 0) themedObject = subviews[0]; } - + if (themedObject) { print(" Recording themed properties for " + [themedObject className] + "."); - + [aTheme takeThemeFromObject:themedObject]; } } diff --git a/Foundation/CPBundle.j b/Foundation/CPBundle.j index 7357ec8fd..23d9a2041 100644 --- a/Foundation/CPBundle.j +++ b/Foundation/CPBundle.j @@ -98,9 +98,9 @@ return className ? CPClassFromString(className) : Nil; } -+ (CPString)firstCompatibleEngineFromArray:(CPArray)engines ++ (CPString)mostEligibleEnvironmentFromArray:(CPArray)environments { - return objj_firstCompatibleEngineFromArray(engines); + return objj_mostEligibleEnvironmentFromArray(environments); } - (CPString)pathForResource:(CPString)aFilename @@ -132,11 +132,14 @@ self._infoConnection = [CPURLConnection connectionWithRequest:[CPURLRequest requestWithURL:[self bundlePath] + "/Info.plist"] delegate:self]; } -- (CPString)firstEligiblePlatform +- (CPArray)supportedEnvironments { - var platforms = [self objectForInfoDictionaryKey:"CPBundlePlatforms"]; + return [self objectForInfoDictionaryKey:"CPBundleEnvironments"] || ["ObjJ"]; +} - return [platforms firstObjectCommonWithArray:OBJJ_PLATFORMS] || nil; +- (CPString)mostEligibleEnvironment +{ + return [[self class] mostEligibleEnvironmentFromArray:[self supportedEnvironments]]; } - (void)connection:(CPURLConnection)aConnection didReceiveData:(CPString)data @@ -145,12 +148,12 @@ { info = CPPropertyListCreateFromData([CPData dataWithString:data]); - var platform = [self firstEligiblePlatform]; + var environment = [self mostEligibleEnvironment]; - if (!platform) - throw "Engine not supported for " + [self bundlePath] + ". Supported engines: " + [self objectForInfoDictionaryKey:"CPBundlePlatforms"] + "."; + if (!environment) + throw "Environment not supported for " + [self bundlePath] + ". Supported environments: " + [self objectForInfoDictionaryKey:"CPBundleEnvironments"] + "."; - [CPURLConnection connectionWithRequest:[CPURLRequest requestWithURL:[self bundlePath] + '/' + platform + ".platform/" + [self objectForInfoDictionaryKey:"CPBundleExecutable"]] delegate:self]; + [CPURLConnection connectionWithRequest:[CPURLRequest requestWithURL:[self bundlePath] + '/' + environment + ".environment/" + [self objectForInfoDictionaryKey:"CPBundleExecutable"]] delegate:self]; } else { @@ -161,7 +164,7 @@ if ([_delegate respondsToSelector:@selector(bundleDidFinishLoading:)]) context.didCompleteCallback = function() { [_delegate bundleDidFinishLoading:self]; }; - var files = [[self objectForInfoDictionaryKey:@"CPBundleReplacedFiles"] objectForKey:[self firstEligiblePlatform]], + var files = [[self objectForInfoDictionaryKey:@"CPBundleReplacedFiles"] objectForKey:[self mostEligibleEnvironment]], count = files ? files.length : 0, // Perhaps no files? Be liberal in what you accept... bundlePath = [self bundlePath]; diff --git a/Foundation/Jakefile b/Foundation/Jakefile index 479b7b34c..36b065a9d 100644 --- a/Foundation/Jakefile +++ b/Foundation/Jakefile @@ -38,6 +38,7 @@ foundationTask = framework ("Foundation", function(foundationTask) foundationTask.setResources(new FileList("Resources/**/*")); foundationTask.setFlattensSources(true); foundationTask.setInfoPlistPath("Info.plist"); + foundationTask.setEnvironments(require("objective-j/jake/environment").ObjJ); if ($CONFIGURATION === "Release") foundationTask.setCompilerFlags("-O"); diff --git a/Objective-J/CommonJS/lib/objective-j.js b/Objective-J/CommonJS/lib/objective-j.js index 1dda5b168..1a9f81474 100644 --- a/Objective-J/CommonJS/lib/objective-j.js +++ b/Objective-J/CommonJS/lib/objective-j.js @@ -13,7 +13,7 @@ if (system.engine === "rhino") window.OBJJ_HOME = exports.OBJJ_HOME = FILE.resolve(module.path, ".."); var frameworksPath = FILE.resolve(window.OBJJ_HOME, "Frameworks/"), - objectivejPath = FILE.resolve(frameworksPath, "Objective-J/", "CommonJS.platform/", "Objective-J.js"); + objectivejPath = FILE.resolve(frameworksPath, "Objective-J/", "CommonJS.environment/", "Objective-J.js"); var OBJJ_INCLUDE_PATHS = window.OBJJ_INCLUDE_PATHS = exports.OBJJ_INCLUDE_PATHS = []; diff --git a/Objective-J/CommonJS/lib/objective-j/jake/applicationtask.js b/Objective-J/CommonJS/lib/objective-j/jake/applicationtask.js index aa04fa8ff..bef6094d6 100644 --- a/Objective-J/CommonJS/lib/objective-j/jake/applicationtask.js +++ b/Objective-J/CommonJS/lib/objective-j/jake/applicationtask.js @@ -42,7 +42,7 @@ ApplicationTask.prototype.indexFilePath = function() ApplicationTask.prototype.defineFrameworksTask = function() { // FIXME: platform requires... - if (this.platforms().indexOf(BundleTask.Platform.Browser) === -1) + if (this.flattenedEnvironments().indexOf(require("objective-j/jake/environment").Browsers) === -1) return; var frameworks = FILE.join(this.buildProductPath(), "Frameworks"), diff --git a/Objective-J/CommonJS/lib/objective-j/jake/bundletask.js b/Objective-J/CommonJS/lib/objective-j/jake/bundletask.js index 2b7555848..67d78174c 100644 --- a/Objective-J/CommonJS/lib/objective-j/jake/bundletask.js +++ b/Objective-J/CommonJS/lib/objective-j/jake/bundletask.js @@ -5,21 +5,41 @@ var FILE = require("file"), Jake = require("jake"), CLEAN = require("jake/clean").CLEAN, CLOBBER = require("jake/clean").CLOBBER, - base64 = require("base64"); + base64 = require("base64"), + environment = require("objective-j/jake/environment"); var Task = Jake.Task, filedir = Jake.filedir; +function isImage(/*String*/ aFilename) +{ + return FILE.isFile(aFilename) && + UTIL.has([".png", ".jpg", ".jpeg", ".gif", ".tif", ".tiff"], FILE.extension(aFilename).toLowerCase()); +} + +function mimeType(/*String*/ aFilename) +{ + return { + ".png" : "image/png", + ".jpg" : "image/jpeg", + ".jpeg" : "image/jpeg", + ".gif" : "image/gif", + ".tif" : "image/tiff", + ".tiff" : "image/tiff" + }[FILE.extension(aFilename).toLowerCase()]; +} + function BundleTask(aName, anApplication) { Task.apply(this, arguments); + this.setEnvironments([environment.Browsers, environment.CommonJS]); + this._author = null; this._email = null; this._summary = null; this._license = null; - this._platforms = [BundleTask.Platform.ObjJ]; this._sources = null; this._resources = null; this._spritesResources = true; @@ -57,17 +77,32 @@ BundleTask.defineTask = function(/*String*/ aName, /*Function*/ aFunction) return bundleTask; } -BundleTask.Platform = { - "ObjJ" : "ObjJ", - "CommonJS" : "CommonJS", - "Browser" : "Browser" - }; +BundleTask.prototype.setEnvironments = function(environments) +{ + if (arguments.length < 1) + this._environments = []; -BundleTask.PLATFORM_DEFAULT_FLAGS = { - "ObjJ" : [], - "CommonJS" : ['-DPLATFORM_RHINO -DPLATFORM_COMMONJS'], - "Browser" : ['-DPLATFORM_BROWSER', '-DPLATFORM_DOM'] - }; + else if (arguments.length > 1) + this._environments = Array.prototype.slice.apply(environments); + + else if (typeof environments.slice === "function") + this._environments = environments.slice(); + + else + this._environments = [environments]; + + this._flattenedEnvironments = environment.Environment.flattenedEnvironments(this._environments); +} + +BundleTask.prototype.environments = function() +{ + return this._environments; +} + +BundleTask.prototype.flattenedEnvironments = function() +{ + return this._flattenedEnvironments; +} BundleTask.prototype.setAuthor = function(anAuthor) { @@ -119,16 +154,6 @@ BundleTask.prototype.version = function() return this._version; } -BundleTask.prototype.setPlatforms = function(platforms) -{ - this._platforms = platforms; -} - -BundleTask.prototype.platforms = function() -{ - return this._platforms; -} - BundleTask.prototype.setSources = function(sources) { this._sources = sources; @@ -271,9 +296,14 @@ BundleTask.prototype.buildIntermediatesProductPath = function() return this.buildIntermediatesPath() || FILE.join(this.buildPath(), this.productName() + ".build"); } -BundleTask.prototype.buildProductStaticPathForPlatform = function(aPlatform) +BundleTask.prototype.buildProductStaticPathForEnvironment = function(anEnvironment) { - return FILE.join(this.buildProductPath(), aPlatform + ".platform", this.productName() + ".sj"); + return FILE.join(this.buildProductPath(), anEnvironment.name() + ".environment", this.productName() + ".sj"); +} + +BundleTask.prototype.buildProductMHTMLPathForEnvironment = function(anEnvironment) +{ + return FILE.join(this.buildProductPath(), anEnvironment.name() + ".environment", this.productName() + ".mhtml"); } BundleTask.prototype.defineTasks = function() @@ -283,6 +313,7 @@ BundleTask.prototype.defineTasks = function() this.defineInfoPlistTask(); this.defineLicenseTask(); this.defineStaticTask(); + this.defineMHTMLTask(); CLEAN.include(this.buildIntermediatesProductPath()); CLOBBER.include(this.buildProductPath()); @@ -309,7 +340,10 @@ BundleTask.prototype.infoPlist = function() infoPlist.setValue("CPBundleIdentifier", this.identifier()); infoPlist.setValue("CPBundleVersion", this.version()); infoPlist.setValue("CPBundlePackageType", this.packageType()); - infoPlist.setValue("CPBundlePlatforms", this.platforms()); + infoPlist.setValue("CPBundleEnvironments", this.flattenedEnvironments().map(function(anEnvironment) + { + return anEnvironment.name(); + })); infoPlist.setValue("CPBundleExecutable", this.productName() + ".sj"); var principalClass = this.principalClass(); @@ -376,36 +410,34 @@ BundleTask.prototype.resourcesPath = function() return FILE.join(this.buildProductPath(), "Resources", ""); } -var IMAGE_EXTENSIONS = [ ".png", ".jpg", ".jpeg", ".gif", ".tif", ".tiff"]; - -var MIME_TYPES = { - ".png" : "image/png", - ".jpg" : "image/jpeg", - ".jpeg" : "image/jpeg", - ".gif" : "image/gif", - ".tif" : "image/tiff", - ".tiff" : "image/tiff" - }; - BundleTask.prototype.defineResourceTask = function(aResourcePath, aDestinationPath) { - var extension = FILE.extension(aResourcePath).toLowerCase(), - extensionless = aResourcePath.substr(0, aResourcePath.length - extension.length); - // Don't sprite images larger than 32KB, IE 8 doesn't like it. - if (this.spritesResources() && IMAGE_EXTENSIONS.indexOf(extension) !== -1 && FILE.size(aResourcePath) < 32768) + if (this.spritesResources() && isImage(aResourcePath) && FILE.size(aResourcePath) < 32768) { - var spritedDestinationPath = FILE.join(this.buildIntermediatesProductPath(), "Browser" + ".platform", "Resources", FILE.relative(this.resourcesPath(), aDestinationPath)); - - filedir (spritedDestinationPath, function() + this.flattenedEnvironments().forEach(function(/*Environment*/ anEnvironment) { - var dataURI = "data:" + MIME_TYPES[extension] + ";base64," + base64.encode(FILE.read(aResourcePath, { mode : 'b'})); - FILE.write(spritedDestinationPath, dataURI.length + ";" + dataURI, { charset:"UTF-8" }); - }); + if (!anEnvironment.spritesImages()) + return; - filedir (this.buildProductStaticPathForPlatform("Browser"), [spritedDestinationPath]); + var folder = anEnvironment.name() + ".environment", + spritedDestinationPath = FILE.join(this.buildIntermediatesProductPath(), folder, "Resources", FILE.relative(this.resourcesPath(), aDestinationPath)); + + filedir (spritedDestinationPath, function() + { + FILE.write(spritedDestinationPath, base64.encode(FILE.read(aResourcePath, { mode : 'b'})), { charset:"UTF-8" }); + }); + + if (anEnvironment.spritesImagesToMHTMLFile()) + filedir (this.buildProductMHTMLPathForEnvironment(anEnvironment), [spritedDestinationPath]); + + // Add this as a dependency unconditionally because we need to set up the URL map either way. + filedir (this.buildProductStaticPathForEnvironment(anEnvironment), [spritedDestinationPath]); + }, this); } + var extension = FILE.extension(aResourcePath), + extensionless = aResourcePath.substr(0, aResourcePath.length - extension.length); // NOT: // (extname === ".cib" && (FILE.exists(extensionless + '.xib') || FILE.exists(extensionless + '.nib')) || // (extname === ".xib" || extname === ".nib") && !this.shouldIncludeNibsAndXibs()) @@ -457,18 +489,18 @@ function directoryInCommon(filenames) if (!aCommonDirectory) aCommonDirectory = directory; - + else { var index = 0, count = Math.min(directory.length, aFilename.length); - + for (; index < count && aCommonDirectory.charAt(index) === directory.charAt(index); ++index) ; - + aCommonDirectory = directory.substr(0, index); } }); -print("DIRECTORY IN COMMON IS " + aCommonDirectory); + return aCommonDirectory; } @@ -508,12 +540,14 @@ BundleTask.prototype.defineResourceTasks = function() BundleTask.prototype.defineStaticTask = function() { - this.platforms().forEach(function(/*String*/ aPlatform) + this.flattenedEnvironments().forEach(function(/*Environment*/ anEnvironment) { - var sourcesPath = FILE.join(this.buildIntermediatesProductPath(), aPlatform + ".platform", "Sources", ""), - resourcesPath = FILE.join(this.buildIntermediatesProductPath(), aPlatform + ".platform", "Resources", ""), - staticPath = this.buildProductStaticPathForPlatform(aPlatform), - flattensSources = this.flattensSources(); + var folder = anEnvironment.name() + ".environment", + sourcesPath = FILE.join(this.buildIntermediatesProductPath(), folder, "Sources", ""), + resourcesPath = FILE.join(this.buildIntermediatesProductPath(), folder, "Resources", ""), + staticPath = this.buildProductStaticPathForEnvironment(anEnvironment), + flattensSources = this.flattensSources(), + productName = this.productName(); filedir (staticPath, function(aTask) { @@ -536,23 +570,36 @@ BundleTask.prototype.defineStaticTask = function() var relativePath = flattensSources ? FILE.basename(aFilename) : FILE.relative(sourcesPath, aFilename); fileStream.write("p;" + relativePath.length + ";" + relativePath); + + // FIXME: We need to do this for now due to file.read adding newlines. Revert when fixed. + //fileStream.write(FILE.read(aFilename, { charset:"UTF-8" })); + fileStream.write(FILE.read(aFilename, { mode:"b" }).decodeToString("UTF-8")); } else if (aFilename.indexOf(resourcesPath) === 0) { - var resourcePath = "Resources/" + FILE.relative(resourcesPath, aFilename); + var contents = "", + resourcePath = "Resources/" + FILE.relative(resourcesPath, aFilename); - if (IMAGE_EXTENSIONS.indexOf(FILE.extension(aFilename)) !== -1) + if (isImage(aFilename)) + { fileStream.write("u;"); + + if (anEnvironment.spritesImagesToStaticFile()) + contents += "data:" + mimeType(aFilename) + ";base64," + FILE.read(aFilename, { charset:"UTF-8" }); + else if (anEnvironment.spritesImagesToMHTMLFile()) + contents = "mhtml:" + FILE.join(folder, productName + ".mhtml!") + resourcePath; + + contents = contents.length + ";" + contents; + } else + { fileStream.write("p;"); + contents = FILE.read(aFilename, { charset:"UTF-8" }); + } - fileStream.write(resourcePath.length + ";" + resourcePath); + fileStream.write(resourcePath.length + ";" + resourcePath + contents); } - - // FIXME: We need to do this for now due to file.read adding newlines. Revert when fixed. - //fileStream.write(FILE.read(aFilename, { charset:"UTF-8" })); - fileStream.write(FILE.read(aFilename, { mode:"b" }).decodeToString("UTF-8")); }, this); fileStream.close(); @@ -562,6 +609,59 @@ BundleTask.prototype.defineStaticTask = function() }, this); } +BundleTask.prototype.defineMHTMLTask = function() +{ + var environments = this.flattenedEnvironments(); + + if (!environments.some(function(anEnvironment) + { + return anEnvironment.spritesImagesToMHTMLFile(); + })) + return; + + environments.filter(function(/*Environment*/ anEnvironment) + { + return anEnvironment.spritesImagesToMHTMLFile(); + }).forEach(function(/*Environment*/ anEnvironment) + { + var folder = anEnvironment.name() + ".environment", + resourcesPath = FILE.join(this.buildIntermediatesProductPath(), folder, "Resources", ""), + MHTMLPath = this.buildProductMHTMLPathForEnvironment(anEnvironment); + + filedir (MHTMLPath, function(aTask) + { + print("Creating MHTML file... " + MHTMLPath); + + var fileStream = FILE.open(MHTMLPath, "w+", { charset:"UTF-8" }); + + fileStream.write("/*\r\nContent-Type: multipart/related; boundary=\"_ANY_STRING_WILL_DO_AS_A_SEPARATOR\"\r\n\r\n"); + + aTask.prerequisites().forEach(function(aFilename) + { + // Our prerequisites will contain directories due to filedir. + if (!isImage(aFilename)) + return; + + var resourcePath = "Resources/" + FILE.relative(resourcesPath, aFilename); + + fileStream.write("--_ANY_STRING_WILL_DO_AS_A_SEPARATOR\r\n"); + fileStream.write("Content-Location:" + resourcePath + "\r\nContent-Transfer-Encoding:base64\r\n\r\n"); + + var contents = FILE.read(aFilename, { charset:"UTF-8" }); + + fileStream.write(contents); + fileStream.write("\r\n"); + + }, this); + + fileStream.write("*/"); + fileStream.close(); + }); + + this.enhance([MHTMLPath]); + }, this); +} + BundleTask.prototype.defineSourceTasks = function() { var sources = this.sources(); @@ -578,40 +678,43 @@ BundleTask.prototype.defineSourceTasks = function() else if (compilerFlags.join) compilerFlags = compilerFlags.join(" "); - this.platforms().forEach(function(/*String*/ aPlatform) + var environments = this.flattenedEnvironments(); + + environments.forEach(function(/*Environment*/ anEnvironment) { - var platformSources = sources, - sourcesPath = FILE.join(this.buildIntermediatesProductPath(), aPlatform + ".platform", "Sources", ""), - staticPath = this.buildProductStaticPathForPlatform(aPlatform), - flags = BundleTask.PLATFORM_DEFAULT_FLAGS[aPlatform].join(" "); + var environmentSources = sources, + folder = anEnvironment.name() + ".environment", + sourcesPath = FILE.join(this.buildIntermediatesProductPath(), folder, "Sources", ""), + staticPath = this.buildProductStaticPathForEnvironment(anEnvironment); - if (!Array.isArray(platformSources) && platformSources.constructor !== Jake.FileList) - platformSources = platformSources[aPlatform]; + if (!Array.isArray(environmentSources) && environmentSources.constructor !== Jake.FileList) + environmentSources = environmentSources[anEnvironment]; - var replacedFiles = []; + var replacedFiles = [], + environmentCompilerFlags = anEnvironment.compilerFlags().join(" ") + " " + compilerFlags; - platformSources.forEach(function(/*String*/ aFilename) + environmentSources.forEach(function(/*String*/ aFilename) { // if this file doesn't exist or isn't a .j file, don't preprocess it. if (!FILE.exists(aFilename) || FILE.extension(aFilename) !== '.j') return; - var compiledPlatformSource = FILE.join(sourcesPath, FILE.basename(aFilename)); + var compiledEnvironmentSource = FILE.join(sourcesPath, FILE.basename(aFilename)); - filedir (compiledPlatformSource, [aFilename], function() + filedir (compiledEnvironmentSource, [aFilename], function() { - print("Compiling " + aFilename + "..."); - FILE.write(compiledPlatformSource, require("objective-j/compiler").compile(aFilename, flags + " " + compilerFlags), { charset:"UTF-8" }); + print("Compiling [" + anEnvironment + "] " + aFilename + "..."); + FILE.write(compiledEnvironmentSource, require("objective-j/compiler").compile(aFilename, environmentCompilerFlags), { charset:"UTF-8" }); }); - filedir (staticPath, [compiledPlatformSource]); + filedir (staticPath, [compiledEnvironmentSource]); // FIXME: how do we non flatten? // dir in common replacedFiles.push(flattensSources ? FILE.basename(aFilename) : FILE.relative(sourcesPath, aFilename)); }, this); - this._replacedFiles[aPlatform] = replacedFiles; + this._replacedFiles[anEnvironment] = replacedFiles; }, this); } diff --git a/Objective-J/CommonJS/lib/objective-j/jake/environment.js b/Objective-J/CommonJS/lib/objective-j/jake/environment.js new file mode 100644 index 000000000..f52036356 --- /dev/null +++ b/Objective-J/CommonJS/lib/objective-j/jake/environment.js @@ -0,0 +1,143 @@ + +var environments = { }; + +function Environment(/*String*/ aName) +{ + this._name = aName; + this._compilerFlags = []; + this._spritesImagesToMHTMLFile = false; + this._spritesImagesToStaticFile = false; + + environments[aName] = this; +} + +Environment.environmentWithName = function(/*String*/ aName) +{ + return environments[aName]; +} + +Environment.flattenedEnvironments = function(/*Array*/ environments) +{ + var flattenedEnvironments = []; + + environments.forEach(function(/*Environment*/ anEnvironment) + { + Array.prototype.push.apply(flattenedEnvironments, anEnvironment.flattenedEnvironments()); + }); + + return flattenedEnvironments; +} + +Environment.prototype.name = function() +{ + return this._name; +} + +Environment.prototype.toString = function() +{ + return this._name; +} + +Environment.prototype.flattenedEnvironments = function() +{ + return [this]; +} + +Environment.prototype.compilerFlags = function() +{ + return this._compilerFlags; +} + +Environment.prototype.setCompilerFlags = function(flags) +{ + this._compilerFlags = flags; +} + +Environment.prototype.setSpritesImagesToMHTMLFile = function(/*Boolean*/ shouldSpriteImagesToMHTMLFile) +{ + this._spritesImagesToMHTMLFile = !!shouldSpriteImagesToMHTMLFile; +} + +Environment.prototype.spritesImagesToMHTMLFile = function() +{ + return this._spritesImagesToMHTMLFile; +} + +Environment.prototype.setSpritesImagesToStaticFile = function(/*Boolean*/ shouldSpriteImagesToStaticFile) +{ + this._spritesImagesToStaticFile = !!shouldSpriteImagesToStaticFile; +} + +Environment.prototype.spritesImagesToStaticFile = function() +{ + return this._spritesImagesToStaticFile; +} + +Environment.prototype.spritesImages = function() +{ + return this.spritesImagesToMHTMLFile() || this.spritesImagesToStaticFile(); +} + +exports.Environment = Environment; + +exports.ObjJ = new Environment("ObjJ"); + +var CommonJS = new Environment("CommonJS"); + +CommonJS.setCompilerFlags(["-DPLATFORM_COMMONJS"]); + +exports.CommonJS = CommonJS; + +var W3C = new Environment("W3C"); + +W3C.setCompilerFlags(["-DPLATFORM_BROWSER", "-DPLATFORM_DOM"]); +W3C.setSpritesImagesToStaticFile(true); + +exports.W3C = W3C; + +var IE7 = new Environment("IE7"); + +IE7.setCompilerFlags(["-DPLATFORM_BROWSER", "-DPLATFORM_DOM"]); +IE7.setSpritesImagesToMHTMLFile(true); + +exports.IE7 = IE7; + +var IE8 = new Environment("IE8"); + +IE8.setCompilerFlags(["-DPLATFORM_BROWSER", "-DPLATFORM_DOM"]); +IE8.setSpritesImagesToStaticFile(true); + +exports.IE8 = IE8; + +function EnvironmentCollection(/*String*/ aName, /*Array*/ environments) +{ + this._name = aName; + this._environments = environments; + + environments[aName] = this; +} + +EnvironmentCollection.prototype.name = function() +{ + return this._name; +} + +EnvironmentCollection.prototype.toString = function() +{ + return this._name; +} + +EnvironmentCollection.prototype.flattenedEnvironments = function() +{ + var environments = []; + + this._environments.forEach(function(anEnvironment) + { + Array.prototype.push.apply(environments, anEnvironment.flattenedEnvironments()); + }); + + return environments; +} + +exports.Browsers = new EnvironmentCollection("Browsers", [W3C, IE7, IE8]); + diff --git a/Objective-J/Jakefile b/Objective-J/Jakefile index c7350a25b..06eb01c7c 100644 --- a/Objective-J/Jakefile +++ b/Objective-J/Jakefile @@ -34,16 +34,16 @@ if ($CONFIGURATION === "Debug") Files.include("Runtime/debug.js"); $BUILD_BROWSER_FILE = FILE.join($BUILD_OBJECTIVE_J, "Objective-J.js"); -$BUILD_CJS_FILE = FILE.join($BUILD_OBJECTIVE_J, "CommonJS.platform", "Objective-J.js"); +$BUILD_CJS_FILE = FILE.join($BUILD_OBJECTIVE_J, "CommonJS.environment", "Objective-J.js"); filedir ($BUILD_BROWSER_FILE, Files, function(aTask) { - build_product(aTask.name(), platform_flags('Browser', 'ObjJ')); + build_product(aTask.name(), environmentFlags("ObjJ") + " -DPLATFORM_USERAGENT"); }); filedir ($BUILD_CJS_FILE, Files, function(aTask) { - flags = platform_flags('CommonJS', 'ObjJ'); + flags = environmentFlags("CommonJS", "ObjJ"); flags += ' -DRHINO' build_product(aTask.name(), flags) @@ -90,11 +90,11 @@ filedir ($BUILD_CJS_OBJECTIVE_J_FRAMEWORK, function() CLOBBER.include($BUILD_OBJECTIVE_J); -function platform_flags() +function environmentFlags() { - return "-DPLATFORMS=\"[" + Array.prototype.map.apply(arguments, [function(aPlatform) + return "-DENVIRONMENTS=\"[" + Array.prototype.map.apply(arguments, [function(anEnvironment) { - return "\\\"" + aPlatform + "\\\""; + return "\\\"" + anEnvironment + "\\\""; }]).join(", ") + "]\""; } diff --git a/Objective-J/Runtime/file.js b/Objective-J/Runtime/file.js index e5f6e56bb..f705a1fcf 100644 --- a/Objective-J/Runtime/file.js +++ b/Objective-J/Runtime/file.js @@ -27,31 +27,39 @@ // Look inside bundleResponseCallback. -var OBJJ_PLATFORMS = PLATFORMS; +var OBJJ_ENVIRONMENTS = ENVIRONMENTS; + +#ifdef PLATFORM_USERAGENT +var userAgent = window.navigator.userAgent; + +if (userAgent.indexOf("MSIE 7") !== -1) + OBJJ_ENVIRONMENTS.unshift("IE7"); +if (userAgent.indexOf("MSIE 8") !== -1) + OBJJ_ENVIRONMENTS.unshift("IE8"); +else + OBJJ_ENVIRONMENTS.unshift("W3C"); +#endif + #define DIRECTORY(aPath) (aPath).substr(0, (aPath).lastIndexOf('/') + 1) -function objj_firstCompatibleEngineFromArray(engines) +function objj_mostEligibleEnvironmentFromArray(environments) { - var engine = NULL, - index = 0, - count = OBJJ_PLATFORMS.length, - innerCount = engines.length; + var index = 0, + count = OBJJ_ENVIRONMENTS.length, + innerCount = environments.length; // Ugh, no indexOf, no objects-in-common. for(; index < count; ++index) { var innerIndex = 0, - currentEngine = OBJJ_PLATFORMS[index]; + environment = OBJJ_ENVIRONMENTS[index]; for (; innerIndex < innerCount; ++innerIndex) - if(currentEngine=== engines[innerIndex]) - { - engine = currentEngine; - break; - } + if(environment === environments[innerIndex]) + return environment; } - return engine; + return NULL; } var OBJJFileNotFoundException = "OBJJFileNotFoundException", @@ -393,16 +401,16 @@ objj_search.prototype.didReceiveBundleResponse = function(aResponse) if (executablePath) { - var platform = objj_firstCompatibleEngineFromArray(dictionary_getValue(bundle.info, "CPBundlePlatforms")); + var environment = objj_mostEligibleEnvironmentFromArray(dictionary_getValue(bundle.info, "CPBundleEnvironments")); - executablePath = platform + ".platform/" + executablePath; + executablePath = environment + ".environment/" + executablePath; this.request(DIRECTORY(aResponse.filePath) + executablePath, this.didReceiveExecutableResponse); // FIXME: Is this the right approach? // Request the compiled file regardless of whether our current inquiry var directory = DIRECTORY(aResponse.filePath), - replacedFiles = dictionary_getValue(dictionary_getValue(bundle.info, "CPBundleReplacedFiles"), platform), + replacedFiles = dictionary_getValue(dictionary_getValue(bundle.info, "CPBundleReplacedFiles"), environment), index = 0, count = replacedFiles.length; @@ -628,7 +636,11 @@ function objj_decompile(aString, bundle) break; - case MARKER_URI: bundle._URIMap[text] = stream.getString(); + case MARKER_URI: var URI = stream.getString(); + if (URI.toLowerCase().indexOf("mhtml:") === 0) + URI = "mhtml:" + DIRECTORY(window.location.href) + '/' + DIRECTORY(bundle.path) + '/' + URI.substr("mhtml:".length); + bundle._URIMap[text] = URI; + break; case MARKER_BUNDLE: var bundlePath = DIRECTORY(bundle.path) + '/' + text; diff --git a/Tools/capp/Jakefile b/Tools/capp/Jakefile index 9e794edb5..3fb533ef3 100644 --- a/Tools/capp/Jakefile +++ b/Tools/capp/Jakefile @@ -17,7 +17,7 @@ app ("capp", function(cappTask) cappTask.setSources(new FileList("*.j")); cappTask.setResources(new FileList("Resources/*")); cappTask.setIncludesNibsAndXibs(true); - cappTask.setPlatforms([BundleTask.Platform.CommonJS]); + cappTask.setEnvironments(require("objective-j/jake/environment").CommonJS); cappTask.setFlattensSources(true); cappTask.setSpritesResources(false); diff --git a/Tools/nib2cib/Jakefile b/Tools/nib2cib/Jakefile index 7a4066523..66915639a 100644 --- a/Tools/nib2cib/Jakefile +++ b/Tools/nib2cib/Jakefile @@ -16,9 +16,9 @@ app ("nib2cib", function(nib2cibTask) nib2cibTask.setAuthor("280 North, Inc."); nib2cibTask.setEmail("feedback @nospam@ 280north.com"); nib2cibTask.setSummary("nib2cib converts Cocoa nib and xibs to Cappuccino cibs"); - nib2cibTask.setSources(FILE.glob("*.j"));// t.sources = FileList['**/*.j'] + nib2cibTask.setSources(FILE.glob("**/*.j")); nib2cibTask.setResources(FILE.glob("Resources/*")); - nib2cibTask.setPlatforms([BundleTask.Platform.CommonJS]); + nib2cibTask.setEnvironments(require("objective-j/jake/environment").CommonJS); nib2cibTask.setFlattensSources(true); if ($CONFIGURATION === "Release") diff --git a/Tools/press/Jakefile b/Tools/press/Jakefile index c4f7e3b80..d63b0fb75 100644 --- a/Tools/press/Jakefile +++ b/Tools/press/Jakefile @@ -16,7 +16,8 @@ app ("press", function(pressTask) pressTask.setVersion("0.7.9"); pressTask.setSources(FILE.glob("*.j")); pressTask.setResources(FILE.glob("Resources/*")); - pressTask.setPlatforms([BundleTask.Platform.CommonJS]); + pressTask.setEnvironments(require("objective-j/jake/environment").CommonJS); + pressTask.setFlattensSources(true); if ($CONFIGURATION === "Release") pressTask.setCompilerFlags("-O"); diff --git a/common.jake b/common.jake index c2f308973..3dc345d68 100644 --- a/common.jake +++ b/common.jake @@ -115,7 +115,7 @@ function partial_require(path, exports) global.setupEnvironment = function() { if (partial_require(FILE.join($BUILD_CONFIGURATION_DIR, "CommonJS", "objective-j")) || - partial_require(FILE.join($HOME_DIR, "Objective-J", "CommonJS", "objective-j"))) + partial_require(FILE.join($HOME_DIR, "Objective-J", "CommonJS"))) { var OBJECTIVE_J_JAKE = require("objective-j/jake"); @@ -174,8 +174,6 @@ global.mv = function(/*String*/ from, /*String*/ to) FILE.move(from, to); } -//require 'objective-j' - function serializedENV() { var serialized = "";