Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accessing Greasemonkey metadata from within your script?

Is there any way that my script can retrieve metadata values that are declared in its own header? I don't see anything promising in the API, except perhaps GM_getValue(). That would of course involve a special name syntax. I have tried, for example: GM_getValue("@name").

The motivation here is to avoid redundant specification.

If GM metadata is not directly accessible, perhaps there's a way to read the body of the script itself. It's certainly in memory somewhere, and it wouldn't be too awfully hard to parse for "// @". (That may be necessary in my case any way, since the value I'm really interested in is @version, which is an extended value read by userscripts.org.)

like image 644
Chris Noe Avatar asked Sep 19 '08 19:09

Chris Noe


3 Answers

This answer is out of date : As of Greasemonkey 0.9.16 (Feb 2012) please see Brock's answer regarding GM_info


Yes. A very simple example is:

var metadata=<> 
// ==UserScript==
// @name           Reading metadata
// @namespace      http://www.afunamatata.com/greasemonkey/
// @description    Read in metadata from the header
// @version        0.9
// @include        https://stackoverflow.com/questions/104568/accessing-greasemonkey-metadata-from-within-your-script
// ==/UserScript==
</>.toString();

GM_log(metadata); 

See this thread on the greasemonkey-users group for more information. A more robust implementation can be found near the end.

like image 186
Athena Avatar answered Oct 23 '22 00:10

Athena


Use the GM_info object, which was added to Greasemonkey in version 0.9.16.

For example, if You run this script:

// ==UserScript==
// @name            _GM_info demo
// @namespace       Stack Overflow
// @description     Tell me more about me, me, ME!
// @include         http://stackoverflow.com/questions/*
// @version         8.8
// ==/UserScript==

unsafeWindow.console.clear ();
unsafeWindow.console.log (GM_info);


It will output this object:

{
    version:            (new String("0.9.18")),
    scriptWillUpdate:   false,
    script: {
        description:    "Tell me more about me, me, ME!",
        excludes:       [],
        includes:       ["http://stackoverflow.com/questions/*"],
        matches:        [],
        name:           "_GM_info demo",
        namespace:      "Stack Overflow",
        'run-at':       "document-end",
        unwrap:         false,
        version:        "8.8"
    },
    scriptMetaStr:      "// @name            _GM_info demo\r\n// @namespace       Stack Overflow\r\n// @description     Tell me more about me, me, ME!\r\n// @include         http://stackoverflow.com/questions/*\r\n// @version         8.8\r\n"
}
like image 23
Brock Adams Avatar answered Oct 23 '22 00:10

Brock Adams


Building on Athena's answer, here is my generalized solution that yields an object of name/value pairs, each representing a metadata property. Note that certain properties can have multiple values, (@include, @exclude, @require, @resource), therefore my parser captures those as Arrays - or in the case of @resource, as a subordinate Object of name/value pairs.

var scriptMetadata = parseMetadata(.toString());

function parseMetadata(headerBlock)
{
    // split up the lines, omitting those not containing "// @"
    function isAGmParm(element) { return /\/\/ @/.test(element); }
    var lines = headerBlock.split(/[\r\n]+/).filter(isAGmParm);
    // initialize the result object with empty arrays for the enumerated properties
    var metadata = { include: [], exclude: [], require: [], resource: {} };
    for each (var line in lines)
    {
        [line, name, value] = line.match(/\/\/ @(\S+)\s*(.*)/);
        if (metadata[name] instanceof Array)
            metadata[name].push(value);
        else if (metadata[name] instanceof Object) {
            [rName, rValue] = value.split(/\s+/); // each resource is named
            metadata[name][rName] = rValue;
        }
        else
            metadata[name] = value;
    }
    return metadata;
}

// example usage
GM_log("version: " + scriptMetadata["version"]);
GM_log("res1: " + scriptMetadata["resource"]["res1"]);

This is working nicely in my scripts.

EDIT: Added @resource and @require, which were introduced in Greasemonkey 0.8.0.

EDIT: FF5+ compatibility, Array.filter() no longer accepts a regular expression

like image 32
Chris Noe Avatar answered Oct 23 '22 01:10

Chris Noe