mirror of
https://github.com/cappuccino/cappuccino.git
synced 2026-10-12 11:37:07 +00:00
Fix support for MHTML. This uses feature detection to determine if DataURLs, and then if MHTML is supported, and falls back on the original unsprited images.
Closes #376.
This commit is contained in:
1 parent
b2179f14ab
commit
b7df6c1480
3 files changed
+96
-67
No files matched your search
+41
-23
@@ -283,7 +283,7 @@ function loadExecutableForBundle(/*Bundle*/ aBundle, success, failure)
|
||||
{
|
||||
try
|
||||
{
|
||||
decompileStaticFile(aBundle, anEvent.request.responseText());
|
||||
decompileStaticFile(aBundle, anEvent.request.responseText(), aBundle.executablePath());
|
||||
aBundle._loadStatus &= ~CFBundleLoadingExecutable;
|
||||
success();
|
||||
}
|
||||
@@ -319,7 +319,7 @@ function loadSpritedImagesForBundle(/*Bundle*/ aBundle, success, failure)
|
||||
{
|
||||
try
|
||||
{
|
||||
decompileStaticFile(aBundle, anEvent.request.responseText());
|
||||
decompileStaticFile(aBundle, anEvent.request.responseText(), spritedImagesPath);
|
||||
aBundle._loadStatus &= ~CFBundleLoadingSpritedImages;
|
||||
success();
|
||||
}
|
||||
@@ -356,9 +356,10 @@ function CFBundleTestSpriteSupport(/*String*/ MHTMLPath, /*Function*/ aCallback)
|
||||
CFBundleDataURLSpriteType,
|
||||
"data:image/gif;base64,R0lGODlhAQABAIAAAMc9BQAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==",
|
||||
CFBundleMHTMLSpriteType,
|
||||
MHTMLPath,
|
||||
MHTMLPath+"!test",
|
||||
CFBundleMHTMLUncachedSpriteType,
|
||||
MHTMLPath+"?"+CFCacheBuster]);
|
||||
MHTMLPath+"?"+CFCacheBuster+"!test"
|
||||
]);
|
||||
}
|
||||
|
||||
function CFBundleNotifySpriteSupportListeners()
|
||||
@@ -371,6 +372,13 @@ function CFBundleNotifySpriteSupportListeners()
|
||||
|
||||
function CFBundleTestSpriteTypes(/*Array*/ spriteTypes)
|
||||
{
|
||||
if (spriteTypes.length < 2)
|
||||
{
|
||||
CFBundleSupportedSpriteType = CFBundleNoSpriteType;
|
||||
CFBundleNotifySpriteSupportListeners();
|
||||
return;
|
||||
}
|
||||
|
||||
var image = new Image();
|
||||
|
||||
image.onload = function()
|
||||
@@ -386,21 +394,25 @@ function CFBundleTestSpriteTypes(/*Array*/ spriteTypes)
|
||||
|
||||
image.onerror = function()
|
||||
{
|
||||
if (spriteTypes.length === 2)
|
||||
{
|
||||
CFBundleSupportedSpriteType = CFBundleNoSpriteType;
|
||||
CFBundleNotifySpriteSupportListeners();
|
||||
}
|
||||
else
|
||||
CFBundleTestSpriteTypes(spriteTypes.slice(2));
|
||||
CFBundleTestSpriteTypes(spriteTypes.slice(2));
|
||||
}
|
||||
|
||||
image.src = spriteTypes[1];
|
||||
}
|
||||
|
||||
function mhtmlBasePath()
|
||||
{
|
||||
#ifdef BROWSER
|
||||
//FIXME: URL stuff is kind of broken
|
||||
return window.location.protocol + "//" + window.location.hostname + (window.location.port ? (":" + window.location.port) : "");
|
||||
#else
|
||||
return "";
|
||||
#endif
|
||||
}
|
||||
|
||||
function spritedImagesTestPathForBundle(/*Bundle*/ aBundle)
|
||||
{
|
||||
return FILE.join(aBundle.path(), aBundle.mostEligibleEnvironment() + ".environment", "MHTMLTest.txt");
|
||||
return "mhtml:" + mhtmlBasePath() + FILE.join(aBundle.path(), aBundle.mostEligibleEnvironment() + ".environment", "MHTMLTest.txt");
|
||||
}
|
||||
|
||||
function spritedImagesPathForBundle(/*Bundle*/ aBundle)
|
||||
@@ -408,12 +420,9 @@ function spritedImagesPathForBundle(/*Bundle*/ aBundle)
|
||||
if (CFBundleSupportedSpriteType === CFBundleDataURLSpriteType)
|
||||
return FILE.join(aBundle.path(), aBundle.mostEligibleEnvironment() + ".environment", "dataURLs.txt");
|
||||
|
||||
if (CFBundleSupportedSpriteType === CFBundleMHTMLSpriteType)
|
||||
return FILE.join(aBundle.path(), aBundle.mostEligibleEnvironment() + ".environment", "MHTML.txt");
|
||||
if (CFBundleSupportedSpriteType === CFBundleMHTMLSpriteType || CFBundleSupportedSpriteType === CFBundleMHTMLUncachedSpriteType)
|
||||
return mhtmlBasePath() + FILE.join(aBundle.path(), aBundle.mostEligibleEnvironment() + ".environment", "MHTMLPaths.txt");
|
||||
|
||||
if (CFBundleSupportedSpriteType === CFBundleMHTMLUncachedSpriteType)
|
||||
return FILE.join(aBundle.path(), aBundle.mostEligibleEnvironment() + ".environment", "MHTML.txt?" + CFCacheBuster);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -464,8 +473,7 @@ function executeBundle(/*Bundle*/ aBundle, /*Function*/ aCallback)
|
||||
var children = staticResource.children();
|
||||
|
||||
for (var name in children)
|
||||
if (hasOwnProperty.call(children, name))
|
||||
staticResources.push(children[name]);
|
||||
staticResources.push(children[name]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -483,15 +491,15 @@ var STATIC_MAGIC_NUMBER = "@STATIC",
|
||||
MARKER_IMPORT_STD = 'I',
|
||||
MARKER_IMPORT_LOCAL = 'i';
|
||||
|
||||
function decompileStaticFile(/*Bundle*/ aBundle, /*String*/ aString)
|
||||
function decompileStaticFile(/*Bundle*/ aBundle, /*String*/ aString, /*String*/ aPath)
|
||||
{
|
||||
var stream = new MarkedStream(aString);
|
||||
|
||||
if (stream.magicNumber() !== STATIC_MAGIC_NUMBER)
|
||||
throw new Error("Could not read static file.");
|
||||
throw new Error("Could not read static file: "+aPath);
|
||||
|
||||
if (stream.version() !== "1.0")
|
||||
throw new Error("Could not read static file.");
|
||||
throw new Error("Could not read static file: "+aPath);
|
||||
|
||||
var marker,
|
||||
bundlePath = aBundle.path(),
|
||||
@@ -514,8 +522,18 @@ function decompileStaticFile(/*Bundle*/ aBundle, /*String*/ aString)
|
||||
var URI = stream.getString();
|
||||
|
||||
if (URI.toLowerCase().indexOf("mhtml:") === 0)
|
||||
URI = "mhtml:" + FILE.join(bundlePath, URI.substr("mhtml:".length));
|
||||
{
|
||||
URI = "mhtml:" + mhtmlBasePath() + FILE.join(bundlePath, URI.substr("mhtml:".length));
|
||||
|
||||
if (CFBundleSupportedSpriteType === CFBundleMHTMLUncachedSpriteType)
|
||||
{
|
||||
var exclamationIndex = URI.indexOf("!"),
|
||||
firstPart = URI.substring(0, exclamationIndex),
|
||||
lastPart = URI.substring(exclamationIndex);
|
||||
|
||||
URI = firstPart + "?" + CFCacheBuster + lastPart;
|
||||
}
|
||||
}
|
||||
aBundle._URIMap[text] = URI;
|
||||
|
||||
// The unresolved directories must not be bundles.
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
/*
|
||||
Content-Type: multipart/related; boundary="_SEPARATOR_"
|
||||
|
||||
--_SEPARATOR_
|
||||
Content-Location:test
|
||||
Content-Transfer-Encoding:base64
|
||||
|
||||
R0lGODlhAQABAIAAAMc9BQAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==
|
||||
*/
|
||||
@@ -317,7 +317,17 @@ BundleTask.prototype.buildProductStaticPathForEnvironment = function(anEnvironme
|
||||
|
||||
BundleTask.prototype.buildProductMHTMLPathForEnvironment = function(anEnvironment)
|
||||
{
|
||||
return FILE.join(this.buildProductPath(), anEnvironment.name() + ".environment", "MHTML.txt");
|
||||
return FILE.join(this.buildProductPath(), anEnvironment.name() + ".environment", "MHTMLPaths.txt");
|
||||
}
|
||||
|
||||
BundleTask.prototype.buildProductMHTMLDataPathForEnvironment = function(anEnvironment)
|
||||
{
|
||||
return FILE.join(this.buildProductPath(), anEnvironment.name() + ".environment", "MHTMLData.txt");
|
||||
}
|
||||
|
||||
BundleTask.prototype.buildProductMHTMLTestPathForEnvironment = function(anEnvironment)
|
||||
{
|
||||
return FILE.join(this.buildProductPath(), anEnvironment.name() + ".environment", "MHTMLTest.txt");
|
||||
}
|
||||
|
||||
BundleTask.prototype.buildProductDataURLPathForEnvironment = function(anEnvironment)
|
||||
@@ -460,8 +470,7 @@ BundleTask.prototype.defineResourceTask = function(aResourcePath, aDestinationPa
|
||||
FILE.write(spritedDestinationPath, base64.encode(FILE.read(aResourcePath, "b")), { charset:"UTF-8" });
|
||||
});
|
||||
|
||||
filedir (this.buildProductDataURLPathForEnvironment(anEnvironment), [spritedDestinationPath]);
|
||||
filedir (this.buildProductMHTMLPathForEnvironment(anEnvironment), [spritedDestinationPath]);
|
||||
task (anEnvironment.name() + "-sprites", [spritedDestinationPath]);
|
||||
}, this);
|
||||
}
|
||||
|
||||
@@ -571,6 +580,10 @@ BundleTask.prototype.defineResourceTasks = function()
|
||||
}, this);
|
||||
}
|
||||
|
||||
|
||||
var RESOURCES_PATH = FILE.join(FILE.absolute(FILE.dirname(module.path)), "RESOURCES"),
|
||||
MHTMLTestPath = FILE.join(RESOURCES_PATH, "MHTMLTest.txt");
|
||||
|
||||
BundleTask.prototype.defineSpritedImagesTask = function()
|
||||
{
|
||||
this.environments().forEach(function(/*Environment*/ anEnvironment)
|
||||
@@ -580,16 +593,23 @@ BundleTask.prototype.defineSpritedImagesTask = function()
|
||||
|
||||
var folder = anEnvironment.name() + ".environment",
|
||||
resourcesPath = FILE.join(this.buildIntermediatesProductPath(), folder, "Resources", ""),
|
||||
productName = this.productName(),
|
||||
dataURLPath = this.buildProductDataURLPathForEnvironment(anEnvironment);
|
||||
dataURLPath = this.buildProductDataURLPathForEnvironment(anEnvironment),
|
||||
MHTMLPath = this.buildProductMHTMLPathForEnvironment(anEnvironment),
|
||||
MHTMLDataPath = this.buildProductMHTMLDataPathForEnvironment(anEnvironment),
|
||||
MHTMLTestDestinationPath = this.buildProductMHTMLTestPathForEnvironment(anEnvironment),
|
||||
productName = this.productName();
|
||||
|
||||
filedir (dataURLPath, function(aTask)
|
||||
task(anEnvironment.name() + "-sprites", function(aTask)
|
||||
{
|
||||
TERM.stream.print("Creating data URLs file... \0green(" + dataURLPath + "\0)");
|
||||
TERM.stream.print("Creating sprited images file... \0green(" + dataURLPath +"\0)");
|
||||
|
||||
var dataURLStream = FILE.open(dataURLPath, "w+", { charset:"UTF-8" });
|
||||
var dataURLStream = FILE.open(dataURLPath, "w+", { charset:"UTF-8" }),
|
||||
MHTMLStream = FILE.open(MHTMLPath, "w+", { charset:"UTF-8" }),
|
||||
MHTMLDataStream = FILE.open(MHTMLDataPath, "w+", { charset:"UTF-8" });
|
||||
|
||||
dataURLStream.write("@STATIC;1.0;");
|
||||
MHTMLStream.write("@STATIC;1.0;");
|
||||
MHTMLDataStream.write("/*\r\nContent-Type: multipart/related; boundary=\"_ANY_STRING_WILL_DO_AS_A_SEPARATOR\"\r\n\r\n");
|
||||
|
||||
aTask.prerequisites().forEach(function(aFilename)
|
||||
{
|
||||
@@ -599,56 +619,39 @@ BundleTask.prototype.defineSpritedImagesTask = function()
|
||||
var resourcePath = "Resources/" + FILE.relative(resourcesPath, aFilename);
|
||||
|
||||
dataURLStream.write("u;" + resourcePath.length + ";" + resourcePath);
|
||||
MHTMLStream.write("u;" + resourcePath.length + ";" + resourcePath);
|
||||
|
||||
// As data URL...
|
||||
var contents = "data:" + mimeType(aFilename) +
|
||||
";base64," + FILE.read(aFilename, "b").decodeToString("UTF-8");
|
||||
|
||||
dataURLStream.write(contents.length + ";" + contents);
|
||||
});
|
||||
|
||||
dataURLStream.write("e;");
|
||||
dataURLStream.close();
|
||||
});
|
||||
|
||||
this.enhance([dataURLPath]);
|
||||
|
||||
var MHTMLPath = this.buildProductMHTMLPathForEnvironment(anEnvironment);
|
||||
|
||||
filedir (MHTMLPath, function(aTask)
|
||||
{
|
||||
TERM.stream.print("Creating MHTML images file... \0green(" + MHTMLPath +"\0)");
|
||||
|
||||
var MHTMLStream = FILE.open(MHTMLPath, "w+", { charset:"UTF-8" }),
|
||||
MHTMLContents = "/*\r\nContent-Type: multipart/related; boundary=\"_ANY_STRING_WILL_DO_AS_A_SEPARATOR\"\r\n\r\n";
|
||||
|
||||
MHTMLStream.write("@STATIC;1.0;");
|
||||
|
||||
aTask.prerequisites().forEach(function(aFilename)
|
||||
{
|
||||
if (!FILE.isFile(aFilename) || aFilename.indexOf(resourcesPath) !== 0 || !isImage(aFilename))
|
||||
return;
|
||||
|
||||
var resourcePath = "Resources/" + FILE.relative(resourcesPath, aFilename);
|
||||
|
||||
MHTMLStream.write("u;" + resourcePath.length + ";" + resourcePath);
|
||||
|
||||
// As MHTML...
|
||||
contents = "mhtml:" + FILE.join(folder, productName + ".sj!") + resourcePath;
|
||||
contents = "mhtml:" + FILE.join(folder, "MHTMLData.txt!") + resourcePath;
|
||||
|
||||
MHTMLContents += "--_ANY_STRING_WILL_DO_AS_A_SEPARATOR\r\n";
|
||||
MHTMLContents += "Content-Location:" + resourcePath + "\r\nContent-Transfer-Encoding:base64\r\n\r\n";
|
||||
MHTMLContents += FILE.read(aFilename, "b").decodeToString("UTF-8");
|
||||
MHTMLContents += "\r\n";
|
||||
MHTMLDataStream.write("--_ANY_STRING_WILL_DO_AS_A_SEPARATOR\r\n");
|
||||
MHTMLDataStream.write("Content-Location:" + resourcePath + "\r\nContent-Transfer-Encoding:base64\r\n\r\n");
|
||||
MHTMLDataStream.write(FILE.read(aFilename, "b").decodeToString("UTF-8"));
|
||||
MHTMLDataStream.write("\r\n");
|
||||
|
||||
MHTMLStream.write(contents.length + ";" + contents);
|
||||
});
|
||||
|
||||
dataURLStream.write("e;");
|
||||
dataURLStream.close();
|
||||
|
||||
MHTMLStream.write("e;");
|
||||
MHTMLStream.write(MHTMLContents + "*/");
|
||||
MHTMLStream.close();
|
||||
|
||||
MHTMLDataStream.write("*/");
|
||||
MHTMLDataStream.close();
|
||||
|
||||
// copy the MHTML test file into this environment
|
||||
FILE.copy(MHTMLTestPath, MHTMLTestDestinationPath);
|
||||
});
|
||||
|
||||
this.enhance([MHTMLPath]);
|
||||
this.enhance([anEnvironment.name() + "-sprites"]);
|
||||
|
||||
}, this);
|
||||
}
|
||||
@@ -668,8 +671,7 @@ BundleTask.prototype.defineStaticTask = function()
|
||||
{
|
||||
TERM.stream.print("Creating static file... \0green(" + staticPath +"\0)");
|
||||
|
||||
var fileStream = FILE.open(staticPath, "w+", { charset:"UTF-8" }),
|
||||
MHTMLContents = "";
|
||||
var fileStream = FILE.open(staticPath, "w+", { charset:"UTF-8" });
|
||||
|
||||
fileStream.write("@STATIC;1.0;");
|
||||
|
||||
|
||||
Reference in new issue
Block a user