Skip to content

Bundlemonkey is a userscript bundler designed to make developing browser userscripts blazing fast and efficient 🔥

License

Notifications You must be signed in to change notification settings

mkobayashime/bundlemonkey

Repository files navigation

Bundlemonkey

Bundlemonkey is a userscript bundler designed to make developing browser userscripts blazing fast and efficient 🔥.

With TypeScript support and type-safe header comments, managing your code becomes a breeze ✨.

Works well with Tampermonkey, Violentmonkey or Greasemonkey ✅.

Features ✨

  • Lightning-Fast Builds
    Incredibly fast bundling speeds, thanks to esbuild.

  • TypeScript Support

  • Module Bundling

  • Type-Safe Header Comments
    Write userscript header metadata in a type-safe and straightforward way. This not only minimizes errors but also makes your code much more maintainable 🛡️.

  • Watch mode

Compilation Example

source

// src/sample/message.ts

export const message = "Hello from sample script and bundlemonkey!";
// src/sample/index.user.ts

import { defineUserScript } from "bundlemonkey";
import { message } from "./message";

export default defineUserScript({
  name: "Sample userscript",
  version: "1.0.0",
  description: "Write userscripts with ease using bundlemonkey!",
  match: ["https://example.com/*"],
  main: () => {
    console.log(message);
  },
});

output

// ==UserScript==
// @name         Sample userscript
// @version      1.0.0
// @description  Write userscripts with ease using bundlemonkey!
// @match        https://example.com/*
// ==/UserScript==

// src/sample/message.ts
var message = "Hello from sample script and bundlemonkey!";

// src/sample/index.user.ts
void (() => {
  console.log(message);
})();

Quick Start 🚀

1. Setup

You can set up new project quickly using the template (1a), or do it manually (1b).

1a. Use template

npx bundlemonkey --create

# or like
pnpx bundlemonkey --create
bunx bundlemonkey --create

1b. Setup manually

Install Bundlemonkey using npm, pnpm, or bun:

npm install --save bundlemonkey

# or like
pnpm add bundlemonkey
bun add bundlemonkey

Create a directory for your userscripts named with the slug under src directory. Your project structure might look like this:

├── src/ # configurable
│   ├── script-a/
│   │   ├── index.user.ts
│   │   └── some-module.ts
│   └── script-b/
│       └── index.user.ts
├── dist/ # configurable
│   └── # bundled code goes here
├── bundlemonkey.config.ts # optional
└── package.json

Tip

Source scripts are collected by glob src/*/index.user.{ts,js} by default, and srcDir is configurable.

2. Write your code

Head into any of the source scripts (index.user.ts or index.user.js) and start writing your code! See Define UserScript section for more details.

3. Build

Run the following command to compile your code:

npx bundlemonkey

# or like
pnpx bundlemonkey
bunx bundlemonkey

Bundlemonkey compiles your code into dist directory 🎉.

Watch mode and Remote watch mode are supported as well, so you can have it rebuild your scripts automatically. See CLI docs below for more details.

Define Userscript 📝

Each source script must define its main code, name, version, etc. using defineUserScript and export it as the default export. It might look like:

import { defineUserScript } from "bundlemonkey";

export default defineUserScript({
  name: "Sample userscript",
  version: "1.0.0",
  description: "Write userscripts with ease using bundlemonkey!",
  match: ["https://example.com/*"],
  config: {
    message: "hello!",
  },
  main: (config) => {
    // your main code here!
    console.log(config.message)
  },
});

Props of defineUserScript

Please see docs of Tampermonkey or Violentmonkey for more details about props other than config and main.

✅ - required

name type default
config T extends any
main (config: T) => unknown ---
name ✅ string ---
namespace string
copyright string
version ✅ string ---
description string
icon string
grant Grant[] | "none" []
author string
homepage string
antiFeature AntiFeature[] []
require string[] []
resource { name: string; url: string; }[] []
match string[] []
excludeMatch string[] []
include string[] []
exclude string[] []
runAt RunAt
runIn string[] []
sandbox "raw" | "JavaScript" | "DOM"
injectInto "page" | "content" | "auto"
tag string[] []
connect string[] []
noframes boolean false
updateURL string
downloadURL string
supportURL string
unwrap boolean false
topLevelAwait boolean false

Config

Config for the script which is intended to be modifiable by the users of your script.

If present, the value will be defined at the beginning of the compiled userscript as a variable named userscriptConfig to make it easy for users to edit.

For example:

export default defineUserScript({
  // ...
  config: {
    /**
     * Edit this to change the message
     * @type string
     */
    message: "hello!"
  },
  main: (config) => {
    window.alert(config.message);
  },
});

will be compiled into:

// ==UserScript==
// ...
// ==/UserScript==

var userscriptConfig = {
  /**
   * Edit this to change the message
   * @type string
   */
  message: "hello!"
};

void ((config) => {
  window.alert(config.message);
})(userscriptConfig);

Main

Your main userscript code.

It can be either a synchronous or an asynchronous function, and can receive config as a prop.

Grant

Tampermonkey docs

All APIs supported by Tampermonkey, Violentmonkey and Greasemonkey (GM_*, GM.*, unsafeWindow, window.onurlchange, window.close and window.focus) can be specified.

type Grant =
  | "unsafeWindow"
  | "GM_addElement"
  | "GM_addStyle"
  // ...
  | "GM.addStyle"
  | "GM.setValue"
  // ...
  | "window.onurlchange"
  | "window.close"
  | "window.focus";

AntiFeature

Tampermonkey docs

type AntiFeature = {
  type: "ads" | "tracking" | "miner";
  description: string;
};

RunAt

Tampermonkey docs

type RunAt =
  | "document-end"
  | "document-start"
  | "document-body"
  | "document-idle"
  | "context-menu";

Build Modes 🛠️

Production Mode

All source scripts will be compiled at once.

Compiled scripts will be located in dist.production directory.

Watch Mode

Bundlemonkey monitors edits to the source scripts. When an edit is detected, it compiles the source and copies the output to the clipboard. Please paste and save it in your userscripts manager's editor for use.

Compiled scripts will be located in dist.dev directory.

Remote Watch Mode

Similar to Watch mode, it monitors edits to the source scripts; however, in this mode, you do not need to paste into the editor every time you make changes.

When a source script is edited, a remote script will be copied to the clipboard only the first time. Once you paste and save this remote script in your userscripts manager's editor, subsequent edits to the source script will be automatically reflected.

You need to allow your userscript manager access to local files to use this mode. Please refer to Tampermonkey's FAQ for more details.

Tip

A remote script is a plain userscript that simply @requires the actual userscript code.

CLI ⌨️

bundlemonkey [--watch [--remote]] [--create]

--watch

Enable Watch mode.

--remote

Use with --watch to enable Remote watch mode.

Configuration ⚙️

If you need to customize Bundlemonkey’s behavior, you can create a configuration file named bundlemonkey.config.ts or bundlemonkey.config.js in your project’s root directory.

Example

bundlemonkey.config.ts

import type { Config } from "bundlemonkey";

const config: Config = {
  srcDir: "src", // default value
  dist: {
    dev: ".dev", // default value
    production: "dist", // default value
  },
  defaultMeta: {
    author: "John Doe",
    namespace: "johndoe",
    homepage: "https://github.com/johndoe/userscripts",
    updateURL: ({ scriptName }) =>
      `https://github.com/johndoe/userscripts/raw/main/dist/${scriptName}.user.js`,
    downloadURL: ({ scriptName }) =>
      `https://github.com/johndoe/userscripts/raw/main/dist/${scriptName}.user.js`,
  },
};

export default config;

srcDir

  • type: string
  • Default: "src"

Directory where your source scripts are located.

Note

The glob for collecting the source files is like: <cwd>/<srcDir>/*/index.user.{ts,js}

dist

  • type: object

dist.dev

  • type: string
  • Default: ".dev"

Dist directory in watch mode.

dist.production

  • type: string
  • Default: "dist"

defaultMeta

  • type: object
  • Default: undefined

Default meta used for all userscripts. Metadata defined in defineUserScript overrides this.

All meta properties in defineUserScript can be used here as well, while updateURL/downloadURL have different signatures like below.

defaultMeta.updateURL

  • type: (args: { scriptName: string; version: string }) => string
  • Default: undefined

defaultMeta.downloadURL

  • type: (args: { scriptName: string; version: string }) => string
  • Default: undefined

About

Bundlemonkey is a userscript bundler designed to make developing browser userscripts blazing fast and efficient 🔥

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published