npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

bookmarklet-output-webpack-plugin

v1.2.0

Published

Webpack Plugin to output JavaScript in bookmarklet format.

Downloads

10

Readme

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