7

About

Tired of writing out userscript headers by hand? Of small typos in your @match headers leading to wasted time? Generate Headers to the rescue: this utility package automates header generation for popular userscript managers like Tampermonkey, Violentmonkey, and Greasemonkey.

Most of the information is sourced from your package.json file (on an off-chance you are unfamiliar, here are the NPM docs), and some headers you provide explicitly to either the CLI interface or the programmatic API (like @grant or @match).

Usage example

CLI usage:

generate-headers tampermonkey \
    -m "https://*.stackexchange.com/*" \
    -o "dist/headers.txt" \
    -g get set delete fetch \
    -p "./package.json" \
    -w tampermonkey.net

Programmatic usage as a module:

import { generate } from "@userscripters/generate-headers/dist/generate";

const content = await generate("greasemonkey", {
    direct: true,
    eol: "\n",
    grants: ["get", "set", "delete", "fetch"],
    matches: ["https://*.stackexchange.com/*"],
    packagePath: "./package.json",
    whitelist: ["self", "1.2.3.4", "google.com"],
});

Example output:

// ==UserScript==
// @name            bring-back-404
// @author          Oleg Valter <[email protected]>
// @connect         self
// @description     Brings back 404 pages to Stack Exchange network
// @grant           GM_deleteValue
// @grant           GM_getValue
// @grant           GM_listValues
// @grant           GM_setValue
// @grant           GM_xmlhttpRequest
// @homepage        https://github.com/userscripters/bring-back-404#readme
// @match           https://*.askubuntu.com/*
// @match           https://*.mathoverflow.net/*
// @match           https://*.serverfault.com/*
// @match           https://*.stackapps.com/*
// @match           https://*.stackexchange.com/*
// @match           https://*.stackoverflow.com/*
// @namespace       userscripters
// @source          git+https://github.com/userscripters/bring-back-404.git
// @supportURL      https://github.com/userscripters/bring-back-404/issues
// @version         0.9.0
// ==/UserScript==

License

The script is licensed under the GPL-3.0-or-later license.

Download

The package is published as both an NPM package and a GitHub package. Can be installed via a package manager like NPM as usual:

npm install --save-dev @userscripters/generate-headers

If you opt to install it from the GitHub registry, please note that it only supports scoped packages, you will need a simple .npmrc file at your project root:

@userscripters:registry=https://npm.pkg.github.com

You will also need to be logged in to GitHub. An easy way to do so is to have a global .npmrc with your PAT (personal access token) set as an access token:

//npm.pkg.github.com/:_authToken=<your token here>

CLI Usage

The package exposes a CLI interface with the following syntax:

generate-headers <tampermonkey | greasemonkey | violentmonkey> [options]

There are various options one can provide to customize the output:

Options:
      --version              Show version number                       [boolean]
      --help                 Show help                                 [boolean]
  -c, --collapse             When using `match all <template>` option value, col
                             lapses all *.stackexchange.com sites into one wildc
                             ard match                 [boolean] [default: true]
      --ch, --custom-header  Generates custom headers given a <name> and [value]
                                                                        [string]
  -d, --direct               Directs headers content to `process.stdout`
                                                      [boolean] [default: false]
      --du, --download-url   URL for the @downloadURL header            [string]
  -e, --eol                  Sets the end-of-line character(s) (affects the chec
                             k for existing headers)        [string] [default: "
                                                                              "]
  -h, --homepage             Overrides homepage for @homepage header    [string]
  -i, --inject               Adds @inject-into header for Violentmonkey, no-op o
                             therwise                                   [string]
  -g, --grant                Generates @grant headers, can be repeated   [array]
  -l, --lint                 Lints the generated headers with ESLint
                                                      [boolean] [default: false]
      --lf, --lint-fix       Fixes lint issues found with ESLint (implies --lint
                             )                        [boolean] [default: false]
  -m, --match                Generates valid @match headers (repeatable) [array]
  -n, --namespace            Overrides namespace for @namespace header  [string]
      --nf, --noframes       Adds @noframes header                     [boolean]
  -o, --output               Creates and populates a file with headers content
                                         [string] [default: "./dist/headers.js"]
  -p, --package              Path to package.json to extract info from
                                            [string] [default: "./package.json"]
  -q, --require              Generates valid @require headers (repeatable)
                                                                         [array]
  -r, --run                  Adds @run-at header (values missing in manager are
                             silently dropped)       [string] [default: "start"]
  -s, --spaces               Number of spaces to indent header values with (tota
                             l is the longest name + this value)
                                                           [number] [default: 4]
  -u, --update-url           URL for the @updateURL header for Tampermonkey, no-
                             op otherwise                               [string]
  -w, --whitelist            Generates @connect headers (repeatable)     [array]
  -x, --exclude              Generates @exclude[-match] headers (repeatable)
                                                                         [array]
      --pretty               Prettifies outputted headers where possible
                                                      [boolean] [default: false]

Some options accept shortcut values for convenience:

Long Value Description Since
grant all Generates all @grant headers available for the userscript manager v2.5.0
match all [template=https://domain/*] Fetches the current list of the Stack Exchange network sites and generates @match headers according to the template. The latter must contain the word domain — it will be replaced with the site domain for each of the generated entries.

Since v2.11.0, paths containing |characters will be expanded, for example,://test.com/a | b/cwill yield://test.com/a/cand://test.com/b/c.
v2.7.3
match meta Generates @match headers for meta sites too (compatible with all) v2.9.0

A special pretty option improves the generated output while preserving backward compatibility:

Header Description Since Example
name Splits the package name on - and capitalizes words 2.6.0 "generate-headers" -> "Generate Headers"

Valid grants

To use some of the sensitive functions exposed by userscript managers, you have to add a @grant header for each of those you use. Generate Headers standardizes and simplifies the process for you (with static analysis of your code coming soon). In both CLI and programmatic API, you can provide multiple grant values (i.e. set), and the package will generate appropriate headers:

Value Tampermonkey Greasemonkey Violentmonkey
set GM_setValue GM.setValue GM_setValue
get GM_getValue GM.getValue GM_getValue
delete GM_deleteValue GM.deleteValue GM_deleteValue
list GM_listValues GM.listValues GM_listValues
unsafe unsafeWindow unsafeWindow unsafeWindow
change window.onurlchange - -
close window.close - window.close
focus window.focus - window.focus
notify - GM.notification GM_notification
clip - GM.setClipboard GM_setClipboard
fetch GM_xmlhttpRequest GM.xmlHttpRequest GM_xmlhttpRequest (yes, h)
style - - GM_addStyle

Valid whitelists

When granted GM_xmlhttpRequest, Tampermonkey presents the user with a confirmation dialog every time the function is called. To avoid this, the script author must add @connect headers for each of the target domains or values with special semantics. The whitelist option generates these headers for you (no-op for other script managers):

Value Description Example
* any domain -
localhost localhost connection -
self domain the script is running at -
IPv4 address any valid IPv4 address 1.2.3.4
FQDN any valid fully qualified domain name tampermonkey.net

Common and manager-specific headers

There are headers common to all userscript managers - for these, the package will source the values from your package.json file and convert the information into headers if available:

Common headers

Header Package field Required Description Example
@author author yes Author of the userscript. Parses both string and object patterns Oleg Valter [email protected]
@contributors contributors no Contributors to the userscript. Greasemonkey will warn, but we believe contributors must always be listed Double Beep
@description description yes Description of the userscript Userscript manager header generator
@icon icon no Icon of the userscript https://example.com/icon.svg
@name name yes Name of the userscript (for scoped packages - value after the /) generate-headers
@namespace name no Namespace of the userscript - only present for scoped packages userscripters
@noframes - no Disallow the script from being loaded in <iframe>
@version version yes Version of the userscript (will be validated for correctness) 2.1.0

Tampermonkey headers

Header Package field Required Description Example
@downloadURL homepage no Download URL override https://github.com/userscripters/generate-headers/dist/index.js
@homepage homepage no (^2.5) Homepage of the userscript https://github.com/userscripters/generate-headers#readme
@supportURL bugs.url no (^2.5) Where to report issues https://github.com/userscripters/generate-headers/issues
@source repository.url no (^2.5) Where to find the source code git+https://github.com/userscripters/generate-headers.git
@updateURL homepage no Update URL override https://github.com/userscripters/generate-headers/dist/index.js

Violentmonkey headers

Header Package field Required Description Example
@homepageURL homepage no (^2.5) Homepage of the userscript https://github.com/userscripters/generate-headers#readme
@supportURL bugs.url no (^2.5) Where to report issues https://github.com/userscripters/generate-headers/issues

Field and header validation

Since v2.0.0, the package validates @match headers according to the rules specified here (and that userscript managers follow). Providing incorrect values will result in an error message and those headers being dropped from the output:

invalid @match header value console message

Since v2.3.0, Generate Headers also checks the presence of required fields in package.json, as well as validates some of them for correctness. Contrary to the above, failing validation of these headers results in early termination, so no output will be generated:

Field Validation
author must be present
description must be present
name must be present
homepage homepage URL must be a valid URL
version the version must be a valid semver version

And here is an example output if the package.json has major issues:

example output failing validation

Since v2.10.0, Generate Headers validates @connect headers for complying with allowed values (see the "Valid whitelists" section above for details). Just as with @match headers, incorrect values will be dropped from the output, and an error will be logged.

Since v2.12.0, Generate Headers validates @require headers for being valid URLs and not file URLs (as they are disallowed by userscript managers).

Linting

Since v3.4.0, Generate Headers has --lint and --lint-fix options (both CLI and programmatic API) that integrate with the eslint-plugin-userscripts plugin for ESLint. The package guarantees that generated headers pass linting by default, but those options are useful if you want to enforce consistent addition of both @homepage and @homepageURL headers to userscript managers that support them, as well as for future-proofing against changes to metadata block schemas.

Platform

This is a Node.js package (tested on LTS 16.13.2), so it requires Node to be installed. Best used with TypeScript, but contains type declaration files for autocompletion as well.

Since v3.0.0, the package is distributed as ES modules and not CommonJS.

Contact

Author: Oleg Valter
Organization: UserScripters

Please, submit bug reports on the source repository.
Before adding a new one, please check if it hasn't been raised before.

You can also drop by to chat, we are a friendly bunch.

Code

Source code is written in TypeScript.

Contributions are welcome, you can always submit a PR here.

3
  • 1
    It is worth mentioning that you need a somewhat complete package.json. I had one without a "name" and then the error message is far from helpful.
    – rene
    Commented Aug 11, 2021 at 18:42
  • @rene yup, I only recently added required fields validation, but didn't have enough time to spare to add more descriptive error message for the validation - coming soon! I tried to outline the "required" fields as best as I could in the docs here, for now, though (column "required"). Also, I plan to add granular override options for v3.0.0
    – 0Valt
    Commented Aug 11, 2021 at 18:50
  • P.s. if you make it as a feature request to make validation messages more helpful, I will gladly fulfill it as soon as I can - the next iteration brings in Violentmonkey headers, and as soon as that's done, I can shift to making the package more feature-rich
    – 0Valt
    Commented Aug 11, 2021 at 18:57

2 Answers 2

2

I would like an option to have the generator expand a single match argument to all known Stack Exchange domains.

So for example -m "https://*.stackexchange.com/reviews/*" -all results in

// @match           https://*.askubuntu.com/reviews/*
// @match           https://*.mathoverflow.net/reviews/*
// @match           https://*.serverfault.com/reviews/*
// @match           https://*.stackapps.com/reviews/*
// @match           https://*.stackexchange.com/reviews/*
// @match           https://*.superuser.com/reviews/*
// @match           https://*.stackoverflow.com/reviews/*

I can imagine being able to include/exclude chat would be useful but nice to have for now.

3
  • Agree - I have @include / @exclude headers is also coming soon - the workload is just a bit too much to handle at the same time :) As for the expansion to all stackexchange domains - good idea, thank you, added to the list of features to add!
    – 0Valt
    Commented Aug 11, 2021 at 19:31
  • status-completed - version 2.7.3 extends the --match option with a special syntax --match all [template] where template is a valid match with a word domain in it (it is used to map sites to custom custom paths). If only all is provided, a https://domain/* will be used. --collapse option controls if stackexchange.com sites will be put under *.stackexchange.com or exploded individually. I am still experimenting with the default value, though, for now it is set to false, but it is probably a good idea to switch to true as a more intuitive option.
    – 0Valt
    Commented Nov 28, 2021 at 2:44
  • P.S. After some deliberation, it does make more sense to set the default to true - this is the new default since 2.7.5 (should not be a breaking change de facto, so I just bumped the patch version).
    – 0Valt
    Commented Nov 30, 2021 at 17:50
1

The package.json needs to exist and the required properties need to have a value. While it is documented it is easily overlooked.

My use case is slightly different. I wanted to generate headers for userscripts I have written over the years and those don't have a package.json and I wasn't planning on adding one.

I prefer the error message is more clear about what is missing and where. So instead of "cannot read property 'match' of undefined" I'd rather see: "The name property is missing from the package.json" but an alternative could be to offer a reasonable default. That would work for my use case.

3
  • 1
    done and soon will be published - small preview for missing properties
    – 0Valt
    Commented Aug 11, 2021 at 20:00
  • Done and published - best consumed starting v2.5.0 (latest) - I connected the required fields to validators and made prettier console logs for each of them (+for those fields that have special validation), as well as reduced the number of required fields to author, description, name, and version (as you will need them in any case). Please, add [status-completed] when (and if) you are able to confirm that the request is granted :) On an off-note, the next major version will expose the required fields to user overrides so as you don't even have to have a package.json to run it.
    – 0Valt
    Commented Aug 12, 2021 at 0:43
  • The reason why the initial version relied heavily on a valid package.json is that it was intended to be an internal package for the org integrated into automated versioning system, but since the project kept growing, I decided to make it a proper library useful to everyone :) Oh, before I forget - the package is now available as both NPM package and GitHub package
    – 0Valt
    Commented Aug 12, 2021 at 0:45

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .