Skip to content
This repository has been archived by the owner on Jan 14, 2022. It is now read-only.

Commit

Permalink
Merge pull request #22 from manifoldjs/v1.0.0
Browse files Browse the repository at this point in the history
V1.0.0 - Bug fixes and support for Edge extensions
  • Loading branch information
f2bo authored Jul 7, 2016
2 parents 89b46fd + b97570a commit a667ec6
Show file tree
Hide file tree
Showing 13 changed files with 292 additions and 51 deletions.
5 changes: 4 additions & 1 deletion lib/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ var validationConstants = {
theme_color: 'theme_color',
related_applications: 'related_applications',
prefer_related_applications: 'prefer_related_applications',
description: 'description',
background_color: 'background_color',
dir: 'dir',
mjs_access_whitelist: 'mjs_access_whitelist',
mjs_api_access: 'mjs_api_acces',
mjs_extended_scope: 'mjs_extended_scope'
Expand All @@ -41,6 +44,6 @@ module.exports = {
CHROME_MANIFEST_FORMAT: 'chromeos',
FIREFOX_MANIFEST_FORMAT: 'firefox',
WINDOWS10_MANIFEST_FORMAT: 'windows10',
EDGE_EXTENSION_FORMAT: 'edgeextension',
EDGE_EXTENSION_MANIFEST_FORMAT: 'edgeextension',
validation: validationConstants
};
2 changes: 1 addition & 1 deletion lib/fileTools.js
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ function syncFiles (source, target, options, callback) {

// if fileOrDir is a directory, synchronize it
if (info.isDirectory()) {
return syncFiles(sourceFile, path.join(target, fileOrDir));
return syncFiles(sourceFile, path.join(target, fileOrDir), options);
}

// check to see if file should be skipped
Expand Down
50 changes: 45 additions & 5 deletions lib/manifestTools/assets/web-manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,33 @@
"theme_color": {
"description": "background color for splash screen and icons",
"type": "string"
},
"dir": {
"description": "Specifies the base direction for the directionality-capable members of the manifest (the directionality-capable members are: description, name, short_name).",
"enum": [ "ltr", "rtl", "auto" ]
},
"lang": {
"description": "A language tag (string) that specifies the primary language for the values of the manifest's directionality-capable members.",
"type": "string"
},
"description": {
"description": "A string that allows the developer to describe the purpose of the web application.",
"type": "string"
},
"background_color": {
"description": "A string describing the expected background color of the web application.",
"type": "string"
},
"related_applications": {
"description": "The related_applications member is an array of applications objects that lists related applications and serves as an indication of such a relationship between web application and related applications.",
"type": "array",
"items": {
"$ref": "#/definitions/application"
}
},
"prefer_related_applications": {
"description": "A boolean value that is used as a hint for the user agent to say that related applications should be preferred over the web application.",
"type": "boolean"
}

},
Expand All @@ -49,11 +76,6 @@
"icon": {
"type": "object",
"properties": {
"density": {
"description": "The density member of an icon is the device pixel density for which this icon was designed.",
"type": [ "number", "string" ],
"default": [ 1.0, "1.0" ]
},
"sizes": {
"description": "The sizes member is a string consisting of an unordered set of unique space-separated tokens which are ASCII case-insensitive that represents the dimensions of an icon for visual media.",
"oneOf": [
Expand All @@ -77,6 +99,24 @@
"pattern": "^[\\sa-z0-9\\-+;\\.=\\/]+$"
}
}
},
"application": {
"type": "object",
"properties": {
"platform": {
"description": "The description member of an application is a string that represents the platform on which the application can be found.",
"type": "string"
},
"url": {
"description": "The url member of an application represents the URL at which the application can be found.",
"type": "string",
"format": "uri"
},
"id": {
"description": "The id member of an application is a string that represents the id which is used to represent the application on the platform.",
"type": "string"
}
}
}
}
}
1 change: 1 addition & 0 deletions lib/manifestTools/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ module.exports = {
writeToFile: manifestLoader.writeToFile,
fetchManifestUrlFromSite: manifestLoader.fetchManifestUrlFromSite,
downloadManifestFromUrl: manifestLoader.downloadManifestFromUrl,
listAvailableManifestFormats: manifestLoader.listAvailableManifestFormats,
convertTo: manifestConverter.convertTo,
validateManifest: manifestValidator.validateManifest,
loadValidationRules: manifestValidator.loadValidationRules,
Expand Down
56 changes: 43 additions & 13 deletions lib/manifestTools/manifestLoader.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ function fetchManifestUrlFromSite (siteUrl, callback) {
return deferred.promise.nodeify(callback);
}

function processManifestContents (data, callback) {
function processManifestContents (data, manifestFormat, callback) {
var manifestObj = utils.parseJSON(data);

if (!manifestObj) {
Expand All @@ -57,9 +57,12 @@ function processManifestContents (data, callback) {

var detectedFormat = manifestTypeDetector.detect(manifestObj);

if (!detectedFormat) {
log.debug('Unable to detect the input manifest format.');
return callback(new Error('Invalid manifest format.'));
if (manifestFormat) {
log.warn('Forcing to format ' + manifestFormat + '...');
detectedFormat = manifestFormat;
} else if (!detectedFormat) {
var availableFormats = listAvailableManifestFormats().join(', ');
return callback(new Error('Unable to detect the input manifest format. Try specifying the correct format using the -f <format> option. Available formats are: ' + availableFormats + '.'));
}

log.info('Found a ' + detectedFormat + ' manifest...');
Expand Down Expand Up @@ -90,15 +93,22 @@ function processManifestContents (data, callback) {
});
}

function downloadManifestFromUrl (manifestUrl, callback) {

function downloadManifestFromUrl (manifestUrl, manifestFormat, callback) {

if (arguments.length < 3) {
if (utils.isFunction(manifestFormat)) {
callback = manifestFormat;
manifestFormat = undefined;
}
}

var deferred = Q.defer();
request({ uri: manifestUrl }, function (err, response, data) {
if (err || response.statusCode !== 200) {
return deferred.reject(new Error('Failed to download manifest data.'));
}

Q.nfcall(processManifestContents, data).then(function (manifestInfo) {
Q.nfcall(processManifestContents, data, manifestFormat).then(function (manifestInfo) {
if (manifestInfo) {
manifestInfo.generatedUrl = manifestUrl;
}
Expand All @@ -113,11 +123,18 @@ function downloadManifestFromUrl (manifestUrl, callback) {
return deferred.promise.nodeify(callback);
}

function getManifestFromSite (siteUrl, callback) {

function getManifestFromSite (siteUrl, manifestFormat, callback) {

if (arguments.length < 3) {
if (utils.isFunction(manifestFormat)) {
callback = manifestFormat;
manifestFormat = undefined;
}
}

return fetchManifestUrlFromSite(siteUrl).then(function (manifestUrl) {
if (manifestUrl) {
return Q.nfcall(downloadManifestFromUrl, manifestUrl);
return Q.nfcall(downloadManifestFromUrl, manifestUrl, manifestFormat);
} else {
// TODO: review what to do in this case. (manifest meta tag is not present)
log.warn('No manifest found. A new manifest will be created.');
Expand All @@ -137,9 +154,17 @@ function getManifestFromSite (siteUrl, callback) {
.nodeify(callback);
}

function getManifestFromFile (filePath, callback) {
function getManifestFromFile (filePath, manifestFormat, callback) {

if (arguments.length < 3) {
if (utils.isFunction(manifestFormat)) {
callback = manifestFormat;
manifestFormat = undefined;
}
}

return Q.nfcall(fs.readFile, filePath).then(function (data) {
return Q.nfcall(processManifestContents, data);
return Q.nfcall(processManifestContents, data, manifestFormat);
})
.nodeify(callback);
}
Expand All @@ -153,10 +178,15 @@ function writeToFile (manifestInfo, filePath, callback) {
return Q.reject(new Error('Manifest content is empty or invalid.')).nodeify(callback);
}

function listAvailableManifestFormats() {
return [constants.BASE_MANIFEST_FORMAT, constants.CHROME_MANIFEST_FORMAT, constants.EDGE_EXTENSION_MANIFEST_FORMAT];
}

module.exports = {
getManifestFromSite: getManifestFromSite,
getManifestFromFile: getManifestFromFile,
writeToFile: writeToFile,
fetchManifestUrlFromSite: fetchManifestUrlFromSite,
downloadManifestFromUrl: downloadManifestFromUrl
downloadManifestFromUrl: downloadManifestFromUrl,
listAvailableManifestFormats: listAvailableManifestFormats
};
12 changes: 6 additions & 6 deletions lib/manifestTools/manifestValidator.js
Original file line number Diff line number Diff line change
Expand Up @@ -136,15 +136,15 @@ function applyValidationRules(w3cManifestInfo, platformModules, platforms) {
return Q.allSettled(platformTasks);
}

// Don't run the "All Platform" validattion for Edge Extensions since they are not w3c compliant
if (platforms.length === 1 && platforms[0] === constants.EDGE_EXTENSION_FORMAT) {
return validatePlatform()
.thenResolve(allResults);
} else {
// Only run the "All Platform" validations for W3C manifests
if (w3cManifestInfo.format === constants.BASE_MANIFEST_FORMAT) {
return validateAllPlatforms()
.then(validatePlatform)
.thenResolve(allResults);
}
} else {
return validatePlatform()
.thenResolve(allResults);
}
}

function validateManifest(w3cManifestInfo, platforms, callback) {
Expand Down
15 changes: 8 additions & 7 deletions lib/manifestTools/transformations/w3c.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
'use strict';

var fs = require('fs'),
path = require('path');

function convertToBase (manifestInfo, callback) {
if (!manifestInfo || !manifestInfo.content) {
return callback(new Error('Manifest content is empty or not initialized.'));
Expand All @@ -16,26 +19,24 @@ function convertFromBase (manifestInfo, callback) {
return callback(undefined, manifestInfo);
}

var validRootProperties = ['name', 'short_name', 'scope', 'icons', 'display',
'orientation', 'start_url', 'lang', 'theme_color'];

var validIconProperties = ['density', 'sizes', 'src', 'type'];

function matchFormat (manifestObj) {
var schemaFile = path.resolve(__dirname, '..', 'assets', 'web-manifest.json');
var schema = JSON.parse(fs.readFileSync(schemaFile).toString());

var lowercasePropName;

for (var prop in manifestObj) {
if (manifestObj.hasOwnProperty(prop)) {
lowercasePropName = prop.toLowerCase();
if (validRootProperties.indexOf(lowercasePropName) === -1 && lowercasePropName.indexOf('_') <= 0) {
if (!schema.properties.hasOwnProperty(lowercasePropName) && lowercasePropName.indexOf('_') <= 0) {
return false;
}

if (lowercasePropName === 'icons') {
var icons = manifestObj[prop];
for (var i = 0; i < icons.length; i++) {
for (var iconProp in icons[i]) {
if (icons[i].hasOwnProperty(iconProp) && validIconProperties.indexOf(iconProp) === -1) {
if (icons[i].hasOwnProperty(iconProp) && !schema.definitions.icon.properties.hasOwnProperty(iconProp)) {
return false;
}
}
Expand Down
31 changes: 19 additions & 12 deletions lib/packageTools.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,28 +62,35 @@ function downloadFile (inputUri, callback) {
}

// returns package information (package.json) given a package name
function getPackageInformation (packageName) {
function getPackageInformation (packageName, parentPackagePath) {

try {
var packagePath = path.dirname(require.main.filename);
var modulesPath = path.join(packagePath, node_modules);

try { fs.statSync(modulesPath).isDirectory(); }
catch (er) {
modulesPath = path.resolve(packagePath, '..');
if (!parentPackagePath) {
parentPackagePath = path.dirname(require.main.filename);
}

var modulePath = parentPackagePath;

if (packageName) {
packagePath = path.join(modulesPath, packageName);
modulePath = modulePath.endsWith(node_modules) ? modulePath : path.join(modulePath, node_modules);
modulePath = path.join(modulePath, packageName);
}
modulePath = path.join(modulePath, packageJson);

packagePath = path.join(packagePath, packageJson);

return require(packagePath);
return require(modulePath);
}
catch (err) {
throw new Error('Error retrieving information for module: \'' + (packageName || 'main') + '\'.');
if (err.code !== 'MODULE_NOT_FOUND') {
throw err;
}

var next = path.resolve(parentPackagePath, '..');
if (parentPackagePath !== next) {
return getPackageInformation(packageName, next);
}
}

throw new Error('Error retrieving information for module: \'' + (packageName || 'main') + '\'.');
}

// returns package information (package.json) given a file or directory
Expand Down
11 changes: 9 additions & 2 deletions lib/validations.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'use strict';

var platformTools = require('./platformTools');
var platformTools = require('./platformTools'),
manifestTools = require('./manifestTools');

function platformsValid(platforms) {
var availablePlatforms = platformTools.listPlatforms();
Expand Down Expand Up @@ -29,8 +30,14 @@ function logLevelValid(level) {
return availableLevels.indexOf(level.toLowerCase()) >= 0;
}

function manifestFormatValid(format) {
var availableFormats = manifestTools.listAvailableManifestFormats();
return availableFormats.indexOf(format.toLowerCase()) >= 0;
}

module.exports = {
platformsValid: platformsValid,
platformToRunValid: platformToRunValid,
logLevelValid: logLevelValid
logLevelValid: logLevelValid,
manifestFormatValid: manifestFormatValid
};
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "manifoldjs-lib",
"version": "0.1.2",
"version": "1.0.0",
"description": "ManifoldJS Core Library",
"repository": {
"type": "git",
Expand Down
3 changes: 1 addition & 2 deletions test/assets/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@
},
{
"src": "icon/hd_hi",
"sizes": "128x128",
"density": "2"
"sizes": "128x128"
}
],
"start_url": "/start.html",
Expand Down
2 changes: 1 addition & 1 deletion test/manifestTools.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ describe('Manifest Tools', function () {
it('Should return an Error if manifest format is invalid', function (done) {
manifestTools.getManifestFromFile(inputFiles.invalidManifestFormat, function (err){
should.exist(err);
err.should.have.property('message', 'Invalid manifest format.');
err.should.have.property('message', 'Unable to detect the input manifest format. Try specifying the correct format using the -f <format> option. Available formats are: w3c, chromeos, edgeextension.');
done();
});
});
Expand Down
Loading

0 comments on commit a667ec6

Please sign in to comment.