Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@ node_modules
_site
dist
.vscode
data/bookmarklets.json
data/auditing.json
153 changes: 153 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
# Contributing

Thanks for your interest in contributing to this bookmarklet collection.

## Quick start

1. Run the scaffolding script:
```bash
npm run new -- --name "My Tool" --author "Your Name" --description "What it does" --tags "accessibility"
```

2. Edit the generated JS file in `bookmarklets/`

3. Add test content to the generated HTML file (if applicable)

4. Run `npm start` to test locally

5. Submit a PR

## Manual setup

If you prefer to create files manually:

1. Create a JS file in `bookmarklets/` with a JSDoc metadata block
2. Optionally create a matching HTML test page (no frontmatter needed)
3. Run `npm start` to lint, build, and preview

## Metadata fields

Every bookmarklet needs a JSDoc comment block at the top of the file:

```javascript
/**
* @bookmarklet My Bookmarklet Name
* @description What the bookmarklet does
* @author Your Name
* @authorUrl https://example.com
* @tags accessibility, wcag:1.4.3
* @pageTest true
*/
(function() {
// Your bookmarklet code here
})();
```

| Field | Required | Description |
|-------|----------|-------------|
| `@bookmarklet` | Yes | Display name of the bookmarklet |
| `@description` | Yes | Brief description of what it does |
| `@author` | No | Original author's name |
| `@authorUrl` | No | Link to author or source |
| `@tags` | Yes | Comma-separated list of tags (see taxonomy below) |
| `@auditing` | No | Set to `true` for auditing favorites |
| `@pageTest` | No | `true`, `false`, or `self` (see test pages below) |

## Tag taxonomy

Tags are validated at build time. Each bookmarklet needs at least one category tag.

### Category tags (required, pick one)

| Tag | Description |
|-----|-------------|
| `accessibility` | Accessibility testing and visualization tools |
| `diagnostic` | Page information and debugging tools |
| `utility` | Convenience and productivity tools |

### Modifier tags (optional)

| Tag | Description |
|-----|-------------|
| `external` | Loads external scripts or redirects to external services |

### WCAG tags (optional)

Format: `wcag:X.X.X` where X.X.X is the success criterion number.

Examples:
- `wcag:1.4.3` (Contrast)
- `wcag:2.4.7` (Focus Visible)
- `wcag:4.1.2` (Name, Role, Value)

### Tag examples

```javascript
// Accessibility tool for checking headings
@tags accessibility, wcag:1.3.1, wcag:2.4.6

// External accessibility tool
@tags accessibility, external

// Simple utility
@tags utility
```

## Test pages

Test pages let users try a bookmarklet on sample content.

### `@pageTest` values

| Value | Meaning | HTML file needed? |
|-------|---------|-------------------|
| `true` | Dedicated test page with specific content | Yes |
| `self` | Works on any page, use the bookmarklet listing page | No |
| `false` | No test needed (e.g., redirects to external service) | No |

### Creating a test page

If `@pageTest` is `true`, create an HTML file with the same base name:
- `bookmarklets/my-tool.js` needs `bookmarklets/my-tool.html`

The HTML file contains only the test content (no frontmatter needed):

```html
<h1>Test page for My Tool</h1>
<p>Content that exercises the bookmarklet's functionality.</p>
```

## Build process

The build process:
1. Lints all JS files with ESLint and Prettier
2. Extracts metadata from JS files
3. Generates `data/bookmarklets.json` and `data/auditing.json`
4. Minifies and encodes each bookmarklet
5. Generates Netscape bookmark HTML files
6. Validates metadata completeness and tag taxonomy
7. Builds the static site with Eleventy

### Commands

| Command | Description |
|---------|-------------|
| `npm start` | Lint, build, and start dev server |
| `npm test` | Lint and build (CI) |
| `npm run build` | Build data files only |
| `npm run new -- --name "Name"` | Scaffold a new bookmarklet |

## Submitting a PR

1. Fork the repository
2. Create a feature branch
3. Make your changes
4. Run `npm test` to verify linting and build pass
5. Submit a pull request

### PR checklist

- [ ] Bookmarklet has all required metadata fields
- [ ] Tags follow the taxonomy (category + optional WCAG)
- [ ] Test page exists if `@pageTest` is `true`
- [ ] `npm test` passes
49 changes: 44 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,50 @@ Tools for the browser.

## Adding a bookmarklet

1. Edit [`data/bookmarklets.json`](/data/bookmarklets.json) and add a new entry, following the schema used on the rest of the file
2. Create a new JS file (and optionally a test HTML page) for the new entry
3. Add code
4. Run `npm start` to lint JS, build data file, and generate static site
5. New entry will be added to the table of bookmarklets in `index.html`
Use the scaffolding script to create the required files:

```bash
npm run new -- --name "My Bookmarklet" --author "Your Name" --description "What it does" --tags "accessibility"
```

This creates:
- `bookmarklets/my-bookmarklet.js` with metadata template
- `bookmarklets/my-bookmarklet.html` test page stub

Then edit the generated files and run `npm start` to test locally.

### Manual setup

Alternatively, create files manually:

1. Create a JS file in `bookmarklets/` with a JSDoc metadata block:
```javascript
/**
* @bookmarklet My Bookmarklet Name
* @description What the bookmarklet does
* @author Your Name
* @authorUrl https://example.com
* @tags accessibility, utility
* @pageTest true
*/
(function() {
// Your bookmarklet code here
})();
```
2. Optionally create a test HTML page in `bookmarklets/` with the same base name (no frontmatter needed)
3. Run `npm start` to lint JS, build data files, and generate the static site

### Metadata fields

| Field | Required | Description |
|-------|----------|-------------|
| `@bookmarklet` | Yes | Display name of the bookmarklet |
| `@description` | Yes | Brief description of what it does |
| `@author` | No | Original author's name |
| `@authorUrl` | No | Link to author or source |
| `@tags` | No | Comma-separated list of tags |
| `@auditing` | No | Set to `true` for auditing favorites |
| `@pageTest` | No | `true`, `false`, or `self` for test page behavior |

## Related web tools

Expand Down
7 changes: 0 additions & 7 deletions bookmarklets/are-ya-hidden.html
Original file line number Diff line number Diff line change
@@ -1,10 +1,3 @@
---
permalink: "are-ya-hidden/"
file: "are-ya-hidden.js"
layout: test
title: are ya hidden
---

<style>
.visually-hidden {
clip-path: inset(50%);
Expand Down
20 changes: 14 additions & 6 deletions bookmarklets/are-ya-hidden.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
/**
* @bookmarklet Are ya hidden?
* @description Display hidden content
* @author Ian Lloyd
* @authorUrl https://a11y-tools.com/bookmarklets/
* @tags accessibility
* @pageTest true
*/
(function () {
var allElements = document.querySelectorAll("*");
function findAllVisuallyHiddenElements() {
Expand All @@ -16,7 +24,7 @@
o < cs.length;
o++
)
((cssProperty = cs[o]),
(cssProperty = cs[o]),
(cssValue = cs.getPropertyValue(cssProperty)),
"clip" === cssProperty &&
"rect(1px, 1px, 1px, 1px)" === cssValue &&
Expand All @@ -27,7 +35,7 @@
"overflow-y" === cssProperty && "hidden" === cssValue && (l = !0),
"position" === cssProperty && "absolute" === cssValue && (s = !0),
"white-space" === cssProperty && "nowrap" === cssValue && (r = !0),
"width" === cssProperty && "1px" === cssValue && (d = !0));
"width" === cssProperty && "1px" === cssValue && (d = !0);
!0 === a &&
!0 === t &&
!0 === e &&
Expand All @@ -38,22 +46,22 @@
!0 === d &&
i.classList.add("was-visually-hidden");
let c = i.classList;
(c.forEach((a) => {
c.forEach((a) => {
-1 !== a.indexOf("-offscreen") &&
i.classList.add("was-visually-hidden");
}),
(i.classList.contains("sr-only") ||
i.classList.contains("screenreader-only") ||
i.classList.contains("visually-hidden") ||
i.classList.contains("visuallyhidden")) &&
i.classList.add("was-visually-hidden"));
i.classList.add("was-visually-hidden");
});
}
function indicateAriaHiddenElements(i) {
findAllVisuallyHiddenElements();
var a,
t = i.createElement("style");
(i.head.appendChild(t),
i.head.appendChild(t),
(a = t.sheet).insertRule(
"[aria-hidden=true] {background:black;color:black;}",
0
Expand All @@ -62,7 +70,7 @@
a.insertRule(
".was-visually-hidden {clip-path: initial!important;clip: initial!important;height: auto!important;overflow: initial!important;position: initial!important;white-space: initial!important;width: auto!important;opacity:initial!important;z-index:initial!important;background:black!important;color:lime!important;}",
0
));
);
}
indicateAriaHiddenElements(document);
var iframes = document.querySelectorAll("iframe");
Expand Down
6 changes: 0 additions & 6 deletions bookmarklets/auto-complete.html
Original file line number Diff line number Diff line change
@@ -1,9 +1,3 @@
---
permalink: "auto-complete/"
file: "auto-complete.js"
layout: test
title: autocomplete
---

<p>See <a href="https://www.w3.org/TR/WCAG21/#input-purposes">the list of names in WCAG</a></p>

Expand Down
9 changes: 9 additions & 0 deletions bookmarklets/auto-complete.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
/**
* @bookmarklet Autocomplete
* @description Display all fields with autocomplete
* @author Rachele DiTullio
* @authorUrl https://racheleditullio.com/blog/2023/11/autocomplete-accessibility-bookmarklet/
* @tags accessibility, wcag:1.3.5
* @auditing true
* @pageTest true
*/
(function () {
let divs = document.querySelectorAll(".autocomplete-info");
if (divs.length > 0) {
Expand Down
6 changes: 0 additions & 6 deletions bookmarklets/background-images.html
Original file line number Diff line number Diff line change
@@ -1,9 +1,3 @@
---
permalink: "background-images/"
file: "background-images.js"
layout: test
title: background images
---
<style>
#one, #two {
background-image: url("https://picsum.photos/300/200");
Expand Down
8 changes: 8 additions & 0 deletions bookmarklets/background-images.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
/**
* @bookmarklet Background images
* @description Highlight all CSS background images
* @author Zoe Mickley Gillenwater
* @authorUrl https://zomigi.com/blog/bookmarklets-for-accessibility-testing/
* @tags utility
* @pageTest true
*/
(function () {
var tags = document.getElementsByTagName("*");
var element;
Expand Down
8 changes: 8 additions & 0 deletions bookmarklets/blur-page.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
/**
* @bookmarklet Blur page
* @description Blur entire page
* @author Thomas Park
* @authorUrl https://thomaspark.co/2013/11/3-simple-design-bookmarklets-to-improve-your-aesthetics/
* @tags diagnostic
* @pageTest false
*/
(function () {
document.body.setAttribute(
"style",
Expand Down
20 changes: 20 additions & 0 deletions bookmarklets/bookmarklets.11tydata.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import path from "path";

export default {
layout: "test",
eleventyComputed: {
file: (data) => {
const basename = path.basename(data.page.inputPath, ".html");
return `${basename}.js`;
},
permalink: (data) => {
const basename = path.basename(data.page.inputPath, ".html");
return `/${basename}/`;
},
title: (data) => {
const file = `${path.basename(data.page.inputPath, ".html")}.js`;
const bookmarklet = data.bookmarklets?.find((b) => b.file === file);
return bookmarklet?.bookmarklet || "";
},
},
};
9 changes: 9 additions & 0 deletions bookmarklets/buttons.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
/**
* @bookmarklet Buttons
* @description Display all buttons
* @author Ian Lloyd
* @authorUrl https://a11y-tools.com/bookmarklets/
* @tags accessibility
* @auditing true
* @pageTest false
*/
(function () {
"use strict";
function listButtons() {
Expand Down
6 changes: 0 additions & 6 deletions bookmarklets/character-keys.html
Original file line number Diff line number Diff line change
@@ -1,9 +1,3 @@
---
permalink: "character-keys/"
file: "character-keys.js"
layout: test
title: character keys
---

<p>This bookmarklet triggers a <code>keypress</code> event for every printable character (and then some) on a US standard 101 keyboard. The keypress details are logged to the console.</p>

Expand Down
Loading