bookmarklet-output-webpack-plugin
TypeScript icon, indicating that this package has built-in type declarations

1.2.0 • Public • Published

Bookmarklet Output Webpack Plugin

Webpack Plugin to output JavaScript in bookmarklet format.

Installation

npm i -D bookmarklet-output-webpack-plugin

Usage

// webpack.config.js
const path = require('path');
const BookmarkletOutputWebpackPlugin = require("bookmarklet-output-webpack-plugin");

module.exports = {
  // ...
  mode: "production",
  output: {
    path: path.resolve(__dirname, "dist"),
    filename: "example-bookmarklet.js"
  },
  plugins: [
    new BookmarkletOutputWebpackPlugin()
  ]
};
// dist/example-bookmarklet.js
javascript:alert(%22Hello%22)%3B

Output as a New File

new BookmarkletOutputWebpackPlugin({
  newFile: true
})
// dist/example-bookmarklet.js
alert("Hello");
// dist/example-bookmarklet.bookmarklet.js
javascript:alert(%22Hello%22)%3B

Create HTML File of the List of Bookmarklets

new BookmarkletOutputWebpackPlugin({
  bookmarkletsList: true
})
// dist/example-bookmarklet.js
javascript:alert(%22Hello%22)%3B
<!-- dist/bookmarklets.html -->
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Bookmarklets</title><style>body{font:18px sans-serif;margin:20px}</style></head><body><p>You can drag the following bookmarklets and register for the bookmark.</p><ul><li><a href="javascript:alert(%22Hello%22)%3B">example-bookmarklet.js</a></li></ul></body></html>

Load Scripts Dynamically in Watch

Register a dedicated bookmarklet and load the script dynamically from localhost while developing in watch mode.

  1. webpack --watch
  2. Visit http://localhost:3300
  3. Register bookmarklets on the page

There are a few things to keep in mind about this feature.

Restrictions on Accessing Localhost

Different browsers have different restrictions on accessing localhost.

For example, Chrome allows access from HTTPS pages, but blocks it from HTTP pages. However, this can be disabled from chrome://flags/#block-insecure-private-network-requests.

In Safari, access from HTTPS is blocked as Mixed Content.

For more information, visit Private Network Access update: Introducing a deprecation trial - Chrome for Developers

CSP

The script element is added to the page and may be blocked by CSP.

Difference from Direct Execution

The script does not run as a bookmarklet, resulting in the following problems.

  • Some browsers reject processes that must be handled by user gestures
  • The value of document.currentScript will not be null
  • Completion values of terminal statement do not affect the page

Ensure That the Completion Values of Terminal Statement Is undefined

When you run the bookmarklet, if the completion value of the terminal statement is not undefined, the contents of the page will be replaced with the completion value.

Webpack wraps the code in an IIFE unless the output.iife option is false, so the completion value is usually undefined. Also, the ensureUndefined option of this plugin adds ;void 0; to the end of the code, so the completion value is always undefined. However, when the code is minified, the IIFE and ;void 0; may be removed.

Therefore, it is recommended to enable the expression option of the Terser Webpack Plugin.

npm i -D terser-webpack-plugin
// webpack.config.js
const TerserPlugin = require("terser-webpack-plugin");

module.exports = {
  // ...
  optimization: {
    minimizer: [
      new TerserPlugin({
        terserOptions: {
          compress: {
            expression: true
          }
        }
      })
    ]
  }
};
// dist/example-bookmarklet.js
javascript:void alert("Hello");

Options

type Bookmarklet = {
  filename: string;
  bookmarklet: string;
};

type PluginOptions = {
  /**
   * URL encoding.
   * @default true
   */
  urlEncode: boolean;

  /**
   * Ensure that the completion values of terminal statement is undefined.
   * If you use Terser to minify, you need to enable Terser's 'expression' option.
   * For Other minimizers, you need to use a similar feature.
   * @default true
   */
  ensureUndefined: boolean;

  /**
   * Regular expression for filenames to include.
   * @default /\.js$/
   */
  include: RegExp;

  /**
   * Output as a new file.
   * @default false
   */
  newFile: boolean;

  /**
   * Name of the new output file.
   * "[path]", "[name]", and "[ext]" will be replaced.
   * @default "[path][name].bookmarklet[ext]"
   */
  newFileName: string;

  /**
   * Output HTML file of the list of bookmarklets.
   * @default false
   */
  bookmarkletsList: boolean;

  /**
   * File name of the bookmarklets list.
   * @default "bookmarklets.html"
   */
  bookmarkletsListName: string;

  /**
   * Remove entry js file.
   * Use with bookmarkletsList option and output only bookmarklets list.
   * @default false
   */
  removeEntryFile: boolean;

  /**
   * Function to create a bookmarklets list.
   * You can customize bookmarklets list with this option.
   */
  createBookmarkletsList: (bookmarklets: Bookmarklet[]) => string;

  /**
   * Use dynamic scripting feature when running in watch mode.
   * @default true
   */
  dynamicScripting: boolean;

  /**
   * Server port for dynamic scripting.
   * @default 3300
   */
  serverPort: number;

  /**
   * Fall back if the port was already in use.
   * @default true
   */
  fallbackPort: boolean;

  /**
   * Server hostname for dynamic scripting.
   * @default "localhost"
   */
  serverHost: string;

  /**
   * Function that return a hash value to protect the filename when loading dynamic scripts.
   * The default is SHA-256, but customization improves security.
   */
  createFilenameHash: (filename: string) => string | Promise<string>;
};

License

MIT

Package Sidebar

Install

npm i bookmarklet-output-webpack-plugin

Weekly Downloads

3

Version

1.2.0

License

MIT

Unpacked Size

31.1 kB

Total Files

23

Last publish

Collaborators

  • level222