Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add basic support for (site/project) key prefixing #226

Merged
merged 9 commits into from
Jun 29, 2014
90 changes: 69 additions & 21 deletions controllers/scriptStorage.js
Original file line number Diff line number Diff line change
Expand Up @@ -131,20 +131,39 @@ exports.sendMeta = function (req, res, next) {
Script.findOne({ installName: caseInsensitive(installName) },
function (err, script) {
var meta = null;
var name = null;
var data = null;
var prefix = null;
var key = null;
var whitespace = ' ';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this a tab or multiple spaces? Maybe a comment would be nice.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it was a tab I would use '\t'... but it's a good point on whether we should be using this or just keep the spaces... I did see something a few months back about something like string(char, count) type method but I lost the link to it. Might have been a different language too. heh... and I'm just about done searching for the evening. :)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A-ha... finally refound the bugger in ES6 draft ... applies to #226 and changed in #267 to Unicode notation of space manually repeating string... time to see if V8 currently supports this in node.js... nope... that's too bad.

See also:


if (!script) { return next(); }

res.set('Content-Type', 'text/javascript; charset=UTF-8');
meta = script.meta;

res.write('// ==UserScript==\n');
Object.keys(meta).reverse().forEach(function (key) {
if (meta[key] instanceof Array) {
meta[key].forEach(function (value) {
res.write('// @' + key + ' ' + value + '\n');
Object.keys(meta).reverse().forEach(function (name) {
if (meta[name] instanceof Array) {
meta[name].forEach(function (value) {
res.write('// @' + name + (value ? whitespace + value : '') + '\n');
});
} else if (meta[name] instanceof Object) {
prefix = name;
for (key in meta[name]) {
data = meta[prefix][key];
if (data instanceof Array) {
data.forEach(function (value) {
res.write('// @' + prefix + ':' + key + (value ? whitespace + value : '') + '\n');
});
}
else {
res.write('// @' + prefix + ':' + key + (data ? whitespace + data : '') + '\n');
}
}
} else {
res.write('// @' + key + ' ' + meta[key] + '\n');
data = meta[name];
res.write('// @' + name + (data ? whitespace + data : '') + '\n');
}
});
res.end('// ==/UserScript==\n');
Expand All @@ -157,18 +176,22 @@ function parseMeta(aString) {
var re = /\/\/ @(\S+)(?:\s+(.*))?/;
var headers = {};
var name = null;
var prefix = null;
var key = null;
var value = null;
var line = null;
var lineMatches = null;
var lines = {};
var unique = {
var uniques = {
'name': true,
'namespace': true,
'description': true,
'version': true,
'author': true
'oujs:author': true
};
var unique = null;
var one = null;
var matches = null;

lines = aString.split(/[\r\n]+/).filter(function (e, i, a) {
return (e.match(re));
Expand All @@ -187,16 +210,41 @@ function parseMeta(aString) {
name = 'homepageURL';
break;
}
if (!headers[name] || unique[name]) {
headers[name] = value || '';
} else {
if (!(headers[name] instanceof Array)) {
headers[name] = [headers[name]];
name = name.split(/:/).reverse();
key = name[0];
prefix = name[1];
if (key) {
if (prefix) {
if (!headers[prefix]) {
headers[prefix] = {};
}
header = headers[prefix];
unique = {};
for (one in uniques) {
matches = one.match(/(.*):(.*)$/);
if (uniques[one] && matches && matches[1] === prefix) {
unique[matches[2]] = true;
}
}
} else {
header = headers;
unique = {};
for (one in uniques) {
if (uniques[one] && !/:/.test(one)) {
unique[one] = true;
}
}
}
if (!header[key] || unique[key]) {
header[key] = value || '';
} else {
if (!(header[key] instanceof Array)) {
header[key] = [header[key]];
}
header[key].push(value || '');
}
headers[name].push(value || '');
}
}

return headers;
}
exports.parseMeta = parseMeta;
Expand Down Expand Up @@ -242,14 +290,14 @@ exports.storeScript = function (user, meta, buf, callback, update) {
// Can't install a script without a @name (maybe replace with random value)
if (!scriptName) { return callback(null); }

if (!isLibrary && meta.author
&& meta.author != user.name && meta.collaborator) {
collaborators = meta.collaborator;
if (!isLibrary && meta.oujs && meta.oujs.author
&& meta.oujs.author != user.name && meta.oujs.collaborator) {
collaborators = meta.oujs.collaborator;
if ((typeof collaborators === 'string'
&& collaborators === user.name)
|| (collaborators instanceof Array
&& collaborators.indexOf(user.name) > -1)) {
installName = meta.author + '/';
installName = meta.oujs.author + '/';
} else {
collaborators = null;
}
Expand Down Expand Up @@ -300,9 +348,9 @@ exports.storeScript = function (user, meta, buf, callback, update) {
});
} else {
if (!script.isLib) {
if (collaborators && (script.meta.author != meta.author
|| JSON.stringify(script.meta.collaborator) !=
JSON.stringify(meta.collaborator))) {
if (collaborators && (script.meta.oujs && script.meta.oujs.author != meta.oujs.author
|| (script.meta.oujs && JSON.stringify(script.meta.oujs.collaborator) !=
JSON.stringify(meta.oujs.collaborator)))) {
return callback(null);
}
script.meta = meta;
Expand Down
8 changes: 4 additions & 4 deletions controllers/user.js
Original file line number Diff line number Diff line change
Expand Up @@ -1362,11 +1362,11 @@ function getExistingScript(req, options, authedUser, callback) {

if (!script) { return callback(null); }

if (script.meta.collaborator) {
if (typeof script.meta.collaborator === 'string') {
collaborators.push(script.meta.collaborator);
if (script.meta.oujs && script.meta.oujs.collaborator) {
if (typeof script.meta.oujs.collaborator === 'string') {
collaborators.push(script.meta.oujs.collaborator);
} else {
collaborators = script.meta.collaborator;
collaborators = script.meta.oujs.collaborator;
}
}

Expand Down
8 changes: 4 additions & 4 deletions views/pages/newScriptPage.html
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,11 @@ <h4 class="list-group-item-heading"><code>@supportURL url</code></h4>
<p class="list-group-item-text">A url of http, https or mailto protocol. Specially formatted on the script page. Last value shown.</p>
</div>
<div class="list-group-item inactive">
<h4 class="list-group-item-heading"><code>@author {{#authedUser}}{{authedUser.name}}{{/authedUser}}{{^authedUser}}username{{/authedUser}}</code></h4>
<p class="list-group-item-text">The author of the script. Required for <a href="#collaboration">Collaboration</a>. Only the author may edit. Last value shown. This key is subject to change.</p>
<h4 class="list-group-item-heading"><code>@oujs:author {{#authedUser}}{{authedUser.name}}{{/authedUser}}{{^authedUser}}username{{/authedUser}}</code></h4>
<p class="list-group-item-text">The author of the script. Required to enable <a href="#collaboration">Collaboration</a>. Last value shown.</p>
</div>
<div class="list-group-item inactive">
<h4 class="list-group-item-heading"><code>@collaborator username</code></h4>
<h4 class="list-group-item-heading"><code>@oujs:collaborator username</code></h4>
<p class="list-group-item-text">Can be defined multiple times. Required for <a href="#collaboration">Collaboration</a>. All values shown in reverse order. This key is subject to change.</p>
</div>
</div>
Expand All @@ -63,7 +63,7 @@ <h4 class="list-group-item-heading"><code>@collaborator username</code></h4>
<h3>Collaboration</h3>
<div class="panel panel-default">
<div class="panel-body">
<p>To allow other users to upload modified versions of your script to your account, add <code>@author Zren</code> to the metadata of your script, along with <code>@collaborator username</code> for every user you wish to give write access. Only the real author of the script can modify these metadata keys. Collaborators cannot use GitHub integration to update the script. Add them as collaborators to the GitHub repo instead.</p>
<p>To allow other users to upload modified versions of your script to your account, add <code>@oujs:author Zren</code> to the metadata of your script, along with <code>@oujs:collaborator username</code> for every user you wish to give write access. Only the real author of the script can modify these metadata keys. Collaborators cannot use GitHub integration to update the script. Add them as collaborators to the GitHub repo instead.</p>
</div>
</div>
{{/newUserJS}}
Expand Down