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

Commit a667ec6

Browse files
authored
Merge pull request #22 from manifoldjs/v1.0.0
V1.0.0 - Bug fixes and support for Edge extensions
2 parents 89b46fd + b97570a commit a667ec6

File tree

13 files changed

+292
-51
lines changed

13 files changed

+292
-51
lines changed

lib/constants.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ var validationConstants = {
2727
theme_color: 'theme_color',
2828
related_applications: 'related_applications',
2929
prefer_related_applications: 'prefer_related_applications',
30+
description: 'description',
31+
background_color: 'background_color',
32+
dir: 'dir',
3033
mjs_access_whitelist: 'mjs_access_whitelist',
3134
mjs_api_access: 'mjs_api_acces',
3235
mjs_extended_scope: 'mjs_extended_scope'
@@ -41,6 +44,6 @@ module.exports = {
4144
CHROME_MANIFEST_FORMAT: 'chromeos',
4245
FIREFOX_MANIFEST_FORMAT: 'firefox',
4346
WINDOWS10_MANIFEST_FORMAT: 'windows10',
44-
EDGE_EXTENSION_FORMAT: 'edgeextension',
47+
EDGE_EXTENSION_MANIFEST_FORMAT: 'edgeextension',
4548
validation: validationConstants
4649
};

lib/fileTools.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ function syncFiles (source, target, options, callback) {
205205

206206
// if fileOrDir is a directory, synchronize it
207207
if (info.isDirectory()) {
208-
return syncFiles(sourceFile, path.join(target, fileOrDir));
208+
return syncFiles(sourceFile, path.join(target, fileOrDir), options);
209209
}
210210

211211
// check to see if file should be skipped

lib/manifestTools/assets/web-manifest.json

Lines changed: 45 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,33 @@
4141
"theme_color": {
4242
"description": "background color for splash screen and icons",
4343
"type": "string"
44+
},
45+
"dir": {
46+
"description": "Specifies the base direction for the directionality-capable members of the manifest (the directionality-capable members are: description, name, short_name).",
47+
"enum": [ "ltr", "rtl", "auto" ]
48+
},
49+
"lang": {
50+
"description": "A language tag (string) that specifies the primary language for the values of the manifest's directionality-capable members.",
51+
"type": "string"
52+
},
53+
"description": {
54+
"description": "A string that allows the developer to describe the purpose of the web application.",
55+
"type": "string"
56+
},
57+
"background_color": {
58+
"description": "A string describing the expected background color of the web application.",
59+
"type": "string"
60+
},
61+
"related_applications": {
62+
"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.",
63+
"type": "array",
64+
"items": {
65+
"$ref": "#/definitions/application"
66+
}
67+
},
68+
"prefer_related_applications": {
69+
"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.",
70+
"type": "boolean"
4471
}
4572

4673
},
@@ -49,11 +76,6 @@
4976
"icon": {
5077
"type": "object",
5178
"properties": {
52-
"density": {
53-
"description": "The density member of an icon is the device pixel density for which this icon was designed.",
54-
"type": [ "number", "string" ],
55-
"default": [ 1.0, "1.0" ]
56-
},
5779
"sizes": {
5880
"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.",
5981
"oneOf": [
@@ -77,6 +99,24 @@
7799
"pattern": "^[\\sa-z0-9\\-+;\\.=\\/]+$"
78100
}
79101
}
102+
},
103+
"application": {
104+
"type": "object",
105+
"properties": {
106+
"platform": {
107+
"description": "The description member of an application is a string that represents the platform on which the application can be found.",
108+
"type": "string"
109+
},
110+
"url": {
111+
"description": "The url member of an application represents the URL at which the application can be found.",
112+
"type": "string",
113+
"format": "uri"
114+
},
115+
"id": {
116+
"description": "The id member of an application is a string that represents the id which is used to represent the application on the platform.",
117+
"type": "string"
118+
}
119+
}
80120
}
81121
}
82122
}

lib/manifestTools/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ module.exports = {
1010
writeToFile: manifestLoader.writeToFile,
1111
fetchManifestUrlFromSite: manifestLoader.fetchManifestUrlFromSite,
1212
downloadManifestFromUrl: manifestLoader.downloadManifestFromUrl,
13+
listAvailableManifestFormats: manifestLoader.listAvailableManifestFormats,
1314
convertTo: manifestConverter.convertTo,
1415
validateManifest: manifestValidator.validateManifest,
1516
loadValidationRules: manifestValidator.loadValidationRules,

lib/manifestTools/manifestLoader.js

Lines changed: 43 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ function fetchManifestUrlFromSite (siteUrl, callback) {
4848
return deferred.promise.nodeify(callback);
4949
}
5050

51-
function processManifestContents (data, callback) {
51+
function processManifestContents (data, manifestFormat, callback) {
5252
var manifestObj = utils.parseJSON(data);
5353

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

5858
var detectedFormat = manifestTypeDetector.detect(manifestObj);
5959

60-
if (!detectedFormat) {
61-
log.debug('Unable to detect the input manifest format.');
62-
return callback(new Error('Invalid manifest format.'));
60+
if (manifestFormat) {
61+
log.warn('Forcing to format ' + manifestFormat + '...');
62+
detectedFormat = manifestFormat;
63+
} else if (!detectedFormat) {
64+
var availableFormats = listAvailableManifestFormats().join(', ');
65+
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 + '.'));
6366
}
6467

6568
log.info('Found a ' + detectedFormat + ' manifest...');
@@ -90,15 +93,22 @@ function processManifestContents (data, callback) {
9093
});
9194
}
9295

93-
function downloadManifestFromUrl (manifestUrl, callback) {
94-
96+
function downloadManifestFromUrl (manifestUrl, manifestFormat, callback) {
97+
98+
if (arguments.length < 3) {
99+
if (utils.isFunction(manifestFormat)) {
100+
callback = manifestFormat;
101+
manifestFormat = undefined;
102+
}
103+
}
104+
95105
var deferred = Q.defer();
96106
request({ uri: manifestUrl }, function (err, response, data) {
97107
if (err || response.statusCode !== 200) {
98108
return deferred.reject(new Error('Failed to download manifest data.'));
99109
}
100110

101-
Q.nfcall(processManifestContents, data).then(function (manifestInfo) {
111+
Q.nfcall(processManifestContents, data, manifestFormat).then(function (manifestInfo) {
102112
if (manifestInfo) {
103113
manifestInfo.generatedUrl = manifestUrl;
104114
}
@@ -113,11 +123,18 @@ function downloadManifestFromUrl (manifestUrl, callback) {
113123
return deferred.promise.nodeify(callback);
114124
}
115125

116-
function getManifestFromSite (siteUrl, callback) {
117-
126+
function getManifestFromSite (siteUrl, manifestFormat, callback) {
127+
128+
if (arguments.length < 3) {
129+
if (utils.isFunction(manifestFormat)) {
130+
callback = manifestFormat;
131+
manifestFormat = undefined;
132+
}
133+
}
134+
118135
return fetchManifestUrlFromSite(siteUrl).then(function (manifestUrl) {
119136
if (manifestUrl) {
120-
return Q.nfcall(downloadManifestFromUrl, manifestUrl);
137+
return Q.nfcall(downloadManifestFromUrl, manifestUrl, manifestFormat);
121138
} else {
122139
// TODO: review what to do in this case. (manifest meta tag is not present)
123140
log.warn('No manifest found. A new manifest will be created.');
@@ -137,9 +154,17 @@ function getManifestFromSite (siteUrl, callback) {
137154
.nodeify(callback);
138155
}
139156

140-
function getManifestFromFile (filePath, callback) {
157+
function getManifestFromFile (filePath, manifestFormat, callback) {
158+
159+
if (arguments.length < 3) {
160+
if (utils.isFunction(manifestFormat)) {
161+
callback = manifestFormat;
162+
manifestFormat = undefined;
163+
}
164+
}
165+
141166
return Q.nfcall(fs.readFile, filePath).then(function (data) {
142-
return Q.nfcall(processManifestContents, data);
167+
return Q.nfcall(processManifestContents, data, manifestFormat);
143168
})
144169
.nodeify(callback);
145170
}
@@ -153,10 +178,15 @@ function writeToFile (manifestInfo, filePath, callback) {
153178
return Q.reject(new Error('Manifest content is empty or invalid.')).nodeify(callback);
154179
}
155180

181+
function listAvailableManifestFormats() {
182+
return [constants.BASE_MANIFEST_FORMAT, constants.CHROME_MANIFEST_FORMAT, constants.EDGE_EXTENSION_MANIFEST_FORMAT];
183+
}
184+
156185
module.exports = {
157186
getManifestFromSite: getManifestFromSite,
158187
getManifestFromFile: getManifestFromFile,
159188
writeToFile: writeToFile,
160189
fetchManifestUrlFromSite: fetchManifestUrlFromSite,
161-
downloadManifestFromUrl: downloadManifestFromUrl
190+
downloadManifestFromUrl: downloadManifestFromUrl,
191+
listAvailableManifestFormats: listAvailableManifestFormats
162192
};

lib/manifestTools/manifestValidator.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -136,15 +136,15 @@ function applyValidationRules(w3cManifestInfo, platformModules, platforms) {
136136
return Q.allSettled(platformTasks);
137137
}
138138

139-
// Don't run the "All Platform" validattion for Edge Extensions since they are not w3c compliant
140-
if (platforms.length === 1 && platforms[0] === constants.EDGE_EXTENSION_FORMAT) {
141-
return validatePlatform()
142-
.thenResolve(allResults);
143-
} else {
139+
// Only run the "All Platform" validations for W3C manifests
140+
if (w3cManifestInfo.format === constants.BASE_MANIFEST_FORMAT) {
144141
return validateAllPlatforms()
145142
.then(validatePlatform)
146143
.thenResolve(allResults);
147-
}
144+
} else {
145+
return validatePlatform()
146+
.thenResolve(allResults);
147+
}
148148
}
149149

150150
function validateManifest(w3cManifestInfo, platforms, callback) {

lib/manifestTools/transformations/w3c.js

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
'use strict';
22

3+
var fs = require('fs'),
4+
path = require('path');
5+
36
function convertToBase (manifestInfo, callback) {
47
if (!manifestInfo || !manifestInfo.content) {
58
return callback(new Error('Manifest content is empty or not initialized.'));
@@ -16,26 +19,24 @@ function convertFromBase (manifestInfo, callback) {
1619
return callback(undefined, manifestInfo);
1720
}
1821

19-
var validRootProperties = ['name', 'short_name', 'scope', 'icons', 'display',
20-
'orientation', 'start_url', 'lang', 'theme_color'];
21-
22-
var validIconProperties = ['density', 'sizes', 'src', 'type'];
23-
2422
function matchFormat (manifestObj) {
23+
var schemaFile = path.resolve(__dirname, '..', 'assets', 'web-manifest.json');
24+
var schema = JSON.parse(fs.readFileSync(schemaFile).toString());
25+
2526
var lowercasePropName;
2627

2728
for (var prop in manifestObj) {
2829
if (manifestObj.hasOwnProperty(prop)) {
2930
lowercasePropName = prop.toLowerCase();
30-
if (validRootProperties.indexOf(lowercasePropName) === -1 && lowercasePropName.indexOf('_') <= 0) {
31+
if (!schema.properties.hasOwnProperty(lowercasePropName) && lowercasePropName.indexOf('_') <= 0) {
3132
return false;
3233
}
3334

3435
if (lowercasePropName === 'icons') {
3536
var icons = manifestObj[prop];
3637
for (var i = 0; i < icons.length; i++) {
3738
for (var iconProp in icons[i]) {
38-
if (icons[i].hasOwnProperty(iconProp) && validIconProperties.indexOf(iconProp) === -1) {
39+
if (icons[i].hasOwnProperty(iconProp) && !schema.definitions.icon.properties.hasOwnProperty(iconProp)) {
3940
return false;
4041
}
4142
}

lib/packageTools.js

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -62,28 +62,35 @@ function downloadFile (inputUri, callback) {
6262
}
6363

6464
// returns package information (package.json) given a package name
65-
function getPackageInformation (packageName) {
65+
function getPackageInformation (packageName, parentPackagePath) {
6666

6767
try {
68-
var packagePath = path.dirname(require.main.filename);
69-
var modulesPath = path.join(packagePath, node_modules);
70-
71-
try { fs.statSync(modulesPath).isDirectory(); }
72-
catch (er) {
73-
modulesPath = path.resolve(packagePath, '..');
68+
if (!parentPackagePath) {
69+
parentPackagePath = path.dirname(require.main.filename);
7470
}
7571

72+
var modulePath = parentPackagePath;
73+
7674
if (packageName) {
77-
packagePath = path.join(modulesPath, packageName);
75+
modulePath = modulePath.endsWith(node_modules) ? modulePath : path.join(modulePath, node_modules);
76+
modulePath = path.join(modulePath, packageName);
7877
}
78+
modulePath = path.join(modulePath, packageJson);
7979

80-
packagePath = path.join(packagePath, packageJson);
81-
82-
return require(packagePath);
80+
return require(modulePath);
8381
}
8482
catch (err) {
85-
throw new Error('Error retrieving information for module: \'' + (packageName || 'main') + '\'.');
83+
if (err.code !== 'MODULE_NOT_FOUND') {
84+
throw err;
85+
}
86+
87+
var next = path.resolve(parentPackagePath, '..');
88+
if (parentPackagePath !== next) {
89+
return getPackageInformation(packageName, next);
90+
}
8691
}
92+
93+
throw new Error('Error retrieving information for module: \'' + (packageName || 'main') + '\'.');
8794
}
8895

8996
// returns package information (package.json) given a file or directory

lib/validations.js

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
'use strict';
22

3-
var platformTools = require('./platformTools');
3+
var platformTools = require('./platformTools'),
4+
manifestTools = require('./manifestTools');
45

56
function platformsValid(platforms) {
67
var availablePlatforms = platformTools.listPlatforms();
@@ -29,8 +30,14 @@ function logLevelValid(level) {
2930
return availableLevels.indexOf(level.toLowerCase()) >= 0;
3031
}
3132

33+
function manifestFormatValid(format) {
34+
var availableFormats = manifestTools.listAvailableManifestFormats();
35+
return availableFormats.indexOf(format.toLowerCase()) >= 0;
36+
}
37+
3238
module.exports = {
3339
platformsValid: platformsValid,
3440
platformToRunValid: platformToRunValid,
35-
logLevelValid: logLevelValid
41+
logLevelValid: logLevelValid,
42+
manifestFormatValid: manifestFormatValid
3643
};

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "manifoldjs-lib",
3-
"version": "0.1.2",
3+
"version": "1.0.0",
44
"description": "ManifoldJS Core Library",
55
"repository": {
66
"type": "git",

0 commit comments

Comments
 (0)