• Stars
    star
    131
  • Rank 267,100 (Top 6 %)
  • Language
    TypeScript
  • License
    MIT License
  • Created over 7 years ago
  • Updated about 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Helps you manage and autosave your extension's options. Chrome and Firefox.

webext-options-sync

Helps you manage and autosave your extension's options.

Main features:

  • Define your default options
  • Add autoload and autosave to your options <form>
  • Run migrations on update

This also lets you very easily have separate options for each domain with the help of webext-options-sync-per-domain.

Install

You can download the standalone bundle and include it in your manifest.json.

Or use npm:

npm install webext-options-sync
import OptionsSync from 'webext-options-sync';

The browser-extension-template repo includes a complete setup with ES Modules, based on the advanced usage below.

Usage

This module requires the storage permission in manifest.json:

{
	"name": "My Cool Extension",
	"permissions": [
		"storage"
	]
}

Simple usage

You can set and get your options from any context (background, content script, etc):

/* global OptionsSync */
const optionsStorage = new OptionsSync();

await optionsStorage.set({showStars: 10});

const options = await optionsStorage.getAll();
// {showStars: 10}

Note: OptionsSync relies on chrome.storage.sync, so its limitations apply, both the size limit and the type of data stored (which must be compatible with JSON).

Advanced usage

It's suggested to create an options-storage.js file with your defaults and possible migrations, and import it where needed:

/* global OptionsSync */
window.optionsStorage = new OptionsSync({
	defaults: {
		colorString: 'green',
		anyBooleans: true,
		numbersAreFine: 9001
	},

	// List of functions that are called when the extension is updated
	migrations: [
		(savedOptions, currentDefaults) => {
			// Perhaps it was renamed
			if (savedOptions.colour) {
				savedOptions.color = savedOptions.colour;
				delete savedOptions.colour;
			}
		},

		// Integrated utility that drops any properties that don't appear in the defaults
		OptionsSync.migrations.removeUnused
	]
});

Include this file as a background script: it's where the defaults are set for the first time and where the migrations are run. This example also includes it in the content script, if you need it there:

{
	"background": {
		"scripts": [
			"webext-options-sync.js",
			"options-storage.js",
			"background.js"
		]
	},
	"content_scripts": [
		{
			"matches": [
				"https://www.google.com/*",
			],
			"js": [
				"webext-options-sync.js",
				"options-storage.js",
				"content.js"
			]
		}
	]
}

Then you can use it this way from the background or content.js:

/* global optionsStorage */
async function init () {
	const {colorString} = await optionsStorage.getAll();
	document.body.style.background = colorString;
}

init();

And also enable autosaving in your options page:

<!-- Your options.html -->
<form>
	<label>Color: <input name="colorString"/></label><br>
	<label>Show: <input type="checkbox" name="anyBooleans"/></label><br>
	<label>Stars: <input name="numbersAreFine"/></label><br>
</form>

<script src="webext-options-sync.js"></script>
<script src="options-storage.js"></script>
<script src="options.js"></script>
// Your options.js file
/* global optionsStorage */

optionsStorage.syncForm(document.querySelector('form'));

Form autosave and autoload

When using the syncForm method, OptionsSync will serialize the form using dom-form-serializer, which uses the name attribute as key for your options. Refer to its readme for more info on the structure of the data.

Any user changes to the form are automatically saved into chrome.storage.sync after 300ms (debounced). It listens to input events.

Input validation

If your form fields have any validation attributes they will not be saved until they become valid.

Since autosave and validation is silent, you should inform the user of invalid fields, possibly via CSS by using the :invalid selector:

/* Style the element */
input:invalid {
	color: red;
	border: 1px solid red;
}

/* Or display a custom error message */
input:invalid ~ .error-message {
	display: block;
}

API

const optionsStorage = new OptionsSync(setup?)

Returns an instance linked to the chosen storage. It will also run any migrations if it's called in the background.

setup

Type: object

Optional. It should follow this format:

{
	defaults: { // recommended
		color: 'blue'
	},
	migrations: [ // optional
		savedOptions => {
			if(savedOptions.oldStuff) {
				delete savedOptions.oldStuff
			}
		}
	],
}
defaults

Type: object

A map of default options as strings or booleans. The keys will have to match the options form fields' name attributes.

migrations

Type: array

A list of functions to run in the background when the extension is updated. Example:

{
	migrations: [
		(savedOptions, defaults) => {
			// Change the `savedOptions`
			if(savedOptions.oldStuff) {
				delete savedOptions.oldStuff
			}

			// No return needed
		},

		// Integrated utility that drops any properties that don't appear in the defaults
		OptionsSync.migrations.removeUnused
	],
}
storageName

Type: string Default: 'options'

The key used to store data in chrome.storage.sync

logging

Type: boolean Default: true

Whether info and warnings (on sync, updating form, etc.) should be logged to the console or not.

storageType

Type: 'local' | 'sync' Default: sync

What storage area type to use (sync storage vs local storage). Sync storage is used by default.

Considerations for selecting which option to use:

  • Sync is default as it's likely more convenient for users.
  • Firefox requires browser_specific_settings.gecko.id for the sync storage to work locally.
  • Sync storage is subject to much tighter quota limitations, and may cause privacy concerns if the data being stored is confidential.

optionsStorage.set(options)

This will merge the existing options with the object provided.

Note: Any values specified in default are not saved into the storage, to save space, but they will still appear when using getAll. You just have to make sure to always specify the same defaults object in every context (this happens automatically in the Advanced usage above.)

options

Type: object Default: {} Example: {color: red}

A map of default options as strings, booleans, numbers and anything accepted by dom-form-serializer’s deserialize function.

optionsStorage.setAll(options)

This will override all the options stored with your options.

optionsStorage.getAll()

This returns a Promise that will resolve with all the options.

optionsStorage.syncForm(form)

Any defaults or saved options will be loaded into the <form> and any change will automatically be saved via chrome.storage.sync. It also looks for any buttons with js-import or js-export classes that when clicked will allow the user to export and import the options to a JSON file.

form

Type: HTMLFormElement, string

It's the <form> that needs to be synchronized or a CSS selector (one element). The form fields' name attributes will have to match the option names.

optionsStorage.stopSyncForm()

Removes any listeners added by syncForm.

optionsStorage.exportFromFile()

Opens the browser’s "save file" dialog to export options to a JSON file. If your form has a .js-export element, this listener will be attached automatically.

optionsStorage.importFromFile()

Opens the browser’s file picker to import options from a previously-saved JSON file. If your form has a .js-import element, this listener will be attached automatically.

Related

License

MIT © Federico Brigante

More Repositories

1

GhostText

👻 Use your text editor to write in your browser. Everything you type in the editor will be instantly updated in the browser (and vice versa).
JavaScript
3,069
star
2

object-fit-images

🗻 Polyfill object-fit/object-position on <img>: IE9, IE10, IE11, Edge, Safari, ...
JavaScript
2,045
star
3

Awesome-WebExtensions

A curated list of awesome resources for WebExtensions development.
1,145
star
4

browser-extension-template

📕 Barebones boilerplate with Parcel 2, options handler and auto-publishing
JavaScript
751
star
5

chrome-webstore-upload-cli

CLI tool to upload Chrome Extensions to the Chrome Web Store
JavaScript
366
star
6

chrome-webstore-upload

Upload Chrome Extensions to the Chrome Web Store
JavaScript
337
star
7

github-issue-link-status

Colorize issue and PR links to see their status (open, closed, merged)
JavaScript
294
star
8

ghat

🛕 Reuse GitHub Actions workflows across repositories
TypeScript
262
star
9

delegate-it

DOM event delegation, in <1KB
TypeScript
185
star
10

indent-textarea

Add editor-like tab-to-indent functionality to <textarea>, in a few bytes
TypeScript
154
star
11

image-promise

🎑🤞 Load one or more images, return a promise. Tiny, browser-only, no dependencies.
TypeScript
144
star
12

select-dom

Lightweight querySelector/All wrapper that outputs an Array
TypeScript
123
star
13

supports-webp

Detect support for WEBP images in the browser in 0.3KB
JavaScript
109
star
14

many-keys-map

A Map subclass with support for multiple keys for one entry.
JavaScript
101
star
15

doma

Parse an HTML string into `DocumentFragment` or one `Element`, in a few bytes (in browser)
TypeScript
94
star
16

code-tag

noop functions to help formatters and syntax highlighters recognize embedded code
JavaScript
89
star
17

webext-fun

WebExtension packages for every need
80
star
18

webext-base-css

Extremely minimal stylesheet/setup for Web Extensions’ options pages (also dark mode)
CSS
80
star
19

webext-storage-cache

Cache values in your Web Extension and clear them on expiration. Also includes a memoize-like API to cache any function results automatically
JavaScript
79
star
20

webext-dynamic-content-scripts

WebExtension module: Automatically registers your content_scripts on domains added via permission.request
TypeScript
74
star
21

fit-textarea

Automatically expand a <textarea> to fit its content, in a few bytes
TypeScript
74
star
22

intrinsic-scale

Replicate `background-size: cover/contain` for canvas/CSS/Node/… on any type of media.
JavaScript
71
star
23

scroll-restoration-polyfill

Polyfill for the "History API: Scroll Restoration"
HTML
71
star
24

text-field-edit

Insert text in a <textarea> and <input> (supports Firefox and Undo)
TypeScript
68
star
25

release-with-changelog

Creates GitHub releases for pushed tags, with the commit log as release body
JavaScript
62
star
26

setup-git-user

GitHub Action that sets the git user and email to enable commiting
61
star
27

webext-domain-permission-toggle

Browser-action context menu to request permission for the current tab.
TypeScript
61
star
28

video-canvas

Paint video on canvas. Extra light.
JavaScript
47
star
29

webext-storage

A more usable typed storage API for Web Extensions
TypeScript
47
star
30

list-github-dir-content

List all the files in a GitHub repo’s directory
JavaScript
41
star
31

webext-detect-page

Detects where the current browser extension code is being run. Chrome and Firefox.
TypeScript
39
star
32

web-ext-submit

Wrapper around Mozilla’s web-ext to submit extensions to AMO.
Shell
33
star
33

fregante

32
star
34

zip-text-nodes

Merge the DOM of 2 elements with the same textContent.
TypeScript
32
star
35

gsap-then

🙏 Make every GSAP Tween a promise. tl.then(doSomething) (GSAP 1 and 2)
JavaScript
29
star
36

GhostText-for-VSCode

Use VS Code to write in your browser. Everything you type in the editor will be instantly updated in the browser (and vice versa).
TypeScript
22
star
37

content-scripts-register-polyfill

WebExtensions: Polyfill for browser.contentScripts.register() for Chrome.
JavaScript
22
star
38

filter-altered-clicks

Filter alt-click, ctrl-click, shift-click, middle click, ...
JavaScript
21
star
39

tiny-version-compare

Compare two software versions, with any number of points (<1KB)
JavaScript
20
star
40

webext-patterns

Convert the patterns of your WebExtension manifest to regex
JavaScript
18
star
41

ghatemplates

GitHub Actions workflow templates for `$ ghat`
17
star
42

eslint-formatters

ESLint formatters published as standalone modules 🎉
JavaScript
17
star
43

webext-content-scripts

Utility functions to inject content scripts from a WebExtension
TypeScript
17
star
44

push-form

Zero-effort nanomodule to submit a `<form>` element via `fetch` and receive the response
TypeScript
17
star
45

daily-version-action

Creates a new tag using the format Y.M.D, but only if HEAD isn’t already tagged
JavaScript
16
star
46

daily-version

Get the current date formatted as a version. Automatically add the time if you already released a version today.
JavaScript
16
star
47

github-clean-feed

Group GitHub's news feed events by repo (Chrome, Firefox, Opera)
JavaScript
16
star
48

tumblr-upload

🚡 Upload your Tumblr theme via node or CLI
JavaScript
15
star
49

setup-git-token

GitHub Action that sets the GITHUB_TOKEN as credentials for git (enables `git push`)
JavaScript
15
star
50

many-keys-weakmap

A `WeakMap` subclass with support for multiple keys for one entry
JavaScript
13
star
51

title-to-labels-action

Cleans up the titles of issues and PRs from common opening keywords
JavaScript
13
star
52

webext-inject-on-install

Automatically add content scripts to existing tabs when your extension is installed. Chrome
JavaScript
13
star
53

webext-options-sync-per-domain

Helps you manage and autosave your extension's options, separately for each additional permission
TypeScript
13
star
54

regex-join

Merge multiple regexes and strings into one, preserving all the flags, automatically escaping the strings
JavaScript
12
star
55

webext-tools

Utility functions for WebExtensions
TypeScript
12
star
56

get-media-size

Get the real size of an <img>, <video>, or <canvas> in the browser.
JavaScript
12
star
57

webext-polyfill-kinda

Super-lightweight Promised wrapper around `chrome.*` API to be used in modules. Prefer `webextension-polyfill` if you’re using it directly in an extension.
JavaScript
11
star
58

webext-additional-permissions

WebExtensions module: Get any optional permissions that users have granted you.
TypeScript
10
star
59

one-mutation

Observe one mutation via `MutationObserver`, then resolve a Promise.
JavaScript
10
star
60

webext-events

High-level events and utilities for events in Web Extensions
TypeScript
10
star
61

get-canvas-pixel-color

Micro module to get the color of a single pixel on a HTML canvas
JavaScript
10
star
62

flat-zip

Merges arrays like a zipper. Like `lodash.zip().flat().take(limit)` but a tenth of the size!
TypeScript
9
star
63

animate-prop

Single, dependency-free function to tween a property. Use that on canvas or anywhere else.
JavaScript
9
star
64

browser-player

🔈 Chrome extension: pause other tabs when you play something
JavaScript
9
star
65

bundle

Bundles my modules so you don't have to!
JavaScript
8
star
66

intervalometer

Call a function at every frame or every X ms. With start/stop
JavaScript
8
star
67

webext-content-script-ping

One-file interface to detect whether your content script have loaded.
JavaScript
8
star
68

one-event

Micro module to add an event listener to be executed only once
TypeScript
6
star
69

tiny-load-script

Load a javascript file and forget about it
JavaScript
5
star
70

on-off

Add/remove DOM events
JavaScript
5
star
71

webext-sandbox

WIP
TypeScript
4
star
72

console-class

Get yourself a light, togglable, namespaced and colored console.log in the browser
JavaScript
4
star
73

prevent-popstate-scroll

(Deprecated) Prevent the scroll restoration caused by the popstate event or back/forward buttons.
JavaScript
4
star
74

gulp-setup

Personal project. NOT RECOMMENDED. Gulp setup for a static website. Includes asset optimization. Loosely based on gulp-starter
JavaScript
4
star
75

visibility-change-ponyfill

A more reliable visibilitychange event that works in more mobile WebViews
JavaScript
4
star
76

get-scroll

Micro module to get the scroll position (top or left) in the browser
4
star
77

random-encoder

Lightweight way to generate multiple, random, reversible "hashes" or encoding
JavaScript
3
star
78

eslint-formatter-table

ESLint’s official `table` formatter, extracted from ESLint 7
JavaScript
3
star
79

RedditGallery.ga

Paste a Reddit post URL, get a gallery of each comment's image. Perfect for /r/photoshopbattles
JavaScript
3
star
80

webext-permissions-events-polyfill

WebExtensions: Polyfill for `onAdded` and `onRemoved` permission events for Firefox.
TypeScript
3
star
81

sticky-pinned-tabs

Chrome Extension: When in a pinned tab, external links open in a new tab
JavaScript
3
star
82

eslint-formatter-codeframe

ESLint’s official `codeframe` formatter, extracted from ESLint 7
JavaScript
3
star
83

facebook-sdk-promise

Load Facebook's API and return a Promise. If it's already loading it won't try to load it again.
JavaScript
3
star
84

npm-helpful-typosquatting

Redirect wrong `npm install`s to the right package
2
star
85

get-elements-array

Array of elements from selector, Array-like objects and single elements
JavaScript
2
star
86

ephiframe

ephimeral iframe page builder
HTML
2
star
87

Redd.cf

An improved fork of Redditate
JavaScript
2
star
88

abort-utils

Utility functions to use and combine `AbortSignal` and `AbortController` with Promises
TypeScript
2
star
89

npm-bundler

Opinionated ES6 library bundler based on rollup-babel-lib-bundler. For my own modules, but maybe you can find it useful too.
JavaScript
2
star
90

github-desktop-open-in-sublime-text

In GitHub Desktop on Mac, replace "Open in Atom" with Sublime Text
2
star
91

time

What time is it?
HTML
1
star
92

webextension-polyfill-global

Wrapper around Mozilla’s webextension-polyfill to make it available as a global even with a bundler
Shell
1
star
93

bin-dir

Find the folder of a global command (installed via npm or not)
JavaScript
1
star
94

guides

1
star
95

meta

Meta discussions (inspired by sindresorhus/meta)
1
star
96

ghosttext.fregante.com

Minisite for GhostText
HTML
1
star
97

webpack-sandbox

Just some personal webpack tests and their output
JavaScript
1
star
98

index-github-bot

Bot that reminds me to add my new repos to my index.
JavaScript
1
star
99

blur-accessibly

Use `element.blur()` without losing the `tab` position
TypeScript
1
star
100

sandbox

wo`w`
JavaScript
1
star