Changeset 625
- Timestamp:
- 01/19/08 14:13:14 (11 months ago)
- Files:
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
branches/jhs1/chrome/chromeFiles/content/config.js
r548 r625 283 283 }; 284 284 285 function ScriptDependency( ){286 this.url = null285 function ScriptDependency(url) { 286 this.url = url || null; 287 287 this.file = null; 288 288 this.filename = null; 289 289 }; 290 290 291 function ScriptResource( ){292 this.url = null;293 this.name = n ull;291 function ScriptResource(name, url) { 292 this.url = url || null; 293 this.name = name || null; 294 294 this.file = null; 295 295 this.filename = null; branches/jhs1/chrome/chromeFiles/content/scriptdownloader.js
r609 r625 227 227 228 228 ScriptDownloader.prototype.parseScript = function(source, uri) { 229 function resolveURL(url, baseurl) { 230 url = ioservice.newURI(url, null, baseurl); 231 return url.spec; 232 } 229 233 var ioservice = Components.classes["@mozilla.org/network/io-service;1"] 230 234 .getService(); … … 233 237 script.uri = uri; 234 238 script.enabled = true; 235 script.includes = []; 236 script.excludes = []; 237 238 // read one line at a time looking for start meta delimiter or EOF 239 var lines = source.match(/.+/g); 240 var lnIdx = 0; 241 var result = {}; 242 var foundMeta = false; 243 244 while ((result = lines[lnIdx++])) { 245 if (result.indexOf("// ==UserScript==") == 0) { 246 foundMeta = true; 247 break; 248 } 249 } 250 251 // gather up meta lines 252 if (foundMeta) { 253 // used for duplicate resource name detection 254 var previousResourceNames = {}; 255 256 while ((result = lines[lnIdx++])) { 257 if (result.indexOf("// ==/UserScript==") == 0) { 258 break; 239 var headers = GM_parseScriptHeaders(source, { 240 // verbatim string, last value only: 241 name:1, 242 namespace:1, 243 description:1, 244 245 // verbatim array of strings, all occurrences: 246 include:0, 247 exclude:0, 248 249 // derived data, all occurrences: 250 require:function(url, prior) { 251 url = resolveURL(url, uri); 252 if (url == uri.spec) 253 return null; 254 for (var i = 0; i < prior.length; i++) { 255 var seen = prior[i]; 256 if (seen && seen.url == url) 257 return null; 259 258 } 260 261 var match = result.match(/\/\/ \@(\S+)\s+([^\n]+)/); 262 if (match != null) { 263 switch (match[1]) { 264 case "name": 265 case "namespace": 266 case "description": 267 script[match[1]] = match[2]; 268 break; 269 case "include": 270 case "exclude": 271 script[match[1]+"s"].push(match[2]); 272 break; 273 case "require": 274 var reqUri = ioservice.newURI(match[2], null, uri); 275 var scriptDependency = new ScriptDependency(); 276 scriptDependency.url = reqUri.spec; 277 script.requires.push(scriptDependency); 278 break; 279 case "resource": 280 var res = match[2].match(/(\S+)\s+(.*)/); 281 if (res === null) { 282 // NOTE: Unlocalized strings 283 throw new Error("Invalid syntax for @resource declaration '" + 284 match[2] + "'. Resources are declared like: " + 285 "@resource <name> <url>."); 286 } 287 288 var resName = res[1]; 289 if (previousResourceNames[resName]) { 290 throw new Error("Duplicate resource name '" + resName + "' " + 291 "detected. Each resource must have a unique " + 292 "name."); 293 } else { 294 previousResourceNames[resName] = true; 295 } 296 297 var resUri = ioservice.newURI(res[2], null, uri); 298 var scriptResource = new ScriptResource(); 299 scriptResource.name = resName; 300 scriptResource.url = resUri.spec; 301 script.resources.push(scriptResource); 302 break; 303 } 259 return new ScriptDependency(url); 260 }, 261 resource:function(name_url, prior) { 262 var args = name_url.match(/(\S+)\s+(.*)/); 263 if (args === null) { 264 throw new Error("Invalid syntax for @resource declaration '" + 265 name_url + "'. Resources are declared like: " + 266 "@resource <name> <url>."); // TODO: i18n 304 267 } 305 } 306 } 307 308 // if no meta info, default to reasonable values 309 if (script.name == null) { 310 script.name = parseScriptName(uri); 311 } 312 313 if (script.namespace == null) { 314 script.namespace = uri.host; 315 } 316 317 if (script.includes.length == 0) { 318 script.includes.push("*"); 319 } 268 var name = args[1]; 269 for (var i = 0; i < prior.length; i++) { 270 if (prior[i].name == name) 271 throw new Error("Duplicate resource name '" + resName + "' " + 272 "detected. Each resource must have a unique " + 273 "name."); // TODO: i18n 274 } 275 var url = args[2]; 276 return new ScriptResource(name, resolveURL(url, uri)); 277 } 278 }); 279 280 script.name = headers.name || parseScriptName(uri); 281 script.namespace = headers.namespace || uri.host; 282 script.description = headers.description || ""; 283 script.includes = headers.include || ["*"]; 284 script.excludes = headers.exclude || []; 285 script.requires = (headers.require || []).filter(function(r) { return r; }); 286 script.resources = headers.resource || []; 320 287 321 288 this.script = script; branches/jhs1/chrome/chromeFiles/content/utils.js
r621 r625 474 474 }; 475 475 476 /** 477 * Returns true if the given script should be invoked on url, otherwise false. 478 */ 476 479 function GM_scriptMatchesUrl(script, url) { 477 480 for (var i = 0, glob; glob = script.includes[i]; i++) { … … 488 491 return false; 489 492 } 493 494 /** 495 * Returns an associative array from header name (sans @ prefix) to value. 496 * Values are arrays, unless headerSpec[name] was 1, in which case the value 497 * is a string only (the value of the last header with that name). 498 * 499 * If, instead of 1, a callback function is provided, the return value of that 500 * callback is becomes appended to the array instead. This callback is invoked 501 * with two arguments: the raw header, and the array with all prior callback 502 * results for this header (or the empty array). 503 * 504 * oldHeaders (optional) is used as the target object headers are appended to. 505 */ 506 function GM_parseScriptHeaders(source, headerSpec, oldHeaders) { 507 var headerRe = /.*/; 508 if (headerSpec) { 509 var allHeaders = []; 510 for (var header in headerSpec) 511 allHeaders.push(header); 512 headerRe = new RegExp("^(" + allHeaders.join("|") + ")$"); 513 } 514 515 // read one line at a time looking for start meta delimiter or EOF 516 var lines = source.match(/.+/g); 517 var lnIdx = 0; 518 var result; 519 var foundMeta = false; 520 var headers = oldHeaders || {}; 521 522 while ((result = lines[lnIdx++])) { 523 if (result.indexOf("// ==UserScript==") == 0) { 524 GM_log("* found metadata"); 525 foundMeta = true; 526 break; 527 } 528 } 529 530 // gather up meta lines 531 if (foundMeta) { 532 while ((result = lines[lnIdx++])) { 533 if (result.indexOf("// ==/UserScript==") == 0) { 534 break; 535 } 536 537 var match = result.match(/\/\/ \@(\S+)\s+([^\n]+)/); 538 if (match != null) { 539 var name = match[1], value = match[2]; 540 if (!name.match(headerRe)) 541 continue; 542 if (headerSpec && headerSpec[name] == 1) { 543 headers[name] = value; // only wanted the last value 544 } 545 else { // want an array of all values 546 if (!headers.hasOwnProperty(name)) 547 headers[name] = []; 548 var callback = headerSpec && headerSpec[name] || 549 function(header) { return header; }; 550 headers[name].push(callback(value, headers[name])); 551 } 552 } 553 } 554 } 555 return headers; 556 };
