feat: library wrapped as an UMD module
This addresses [issue 7] by making it possible for users to run: ```sh npm install webextension-polyfill ``` and download a module that they can use with a bundler as follows: ```js import browser from 'webextension-polyfill'; ``` Also, add a [prepublish script] so that users who clone the repo don't need to run `grunt` manually. In addition, specify [files] in package.json so that this module can be published to npm without including miscellanea. This can be verified by running: ```sh npm pack && tar -tvf webextension-polyfill-0.1.0.tgz ``` [issue 7]: https://github.com/mozilla/webextension-polyfill/issues/7 [files]: https://docs.npmjs.com/files/package.json#files [prepublish script]: https://docs.npmjs.com/misc/scripts
This commit is contained in:
parent
52791c8633
commit
f9248e62e7
14
Gruntfile.js
14
Gruntfile.js
|
@ -28,7 +28,7 @@ module.exports = function(grunt) {
|
|||
options: {
|
||||
patterns: [
|
||||
{
|
||||
match: /\{\/\* include\("(.*?)"\) \*\/\}/,
|
||||
match: /require\("..\/(.*?)"\)/,
|
||||
replacement: (match, filename) => {
|
||||
return grunt.file.read(filename)
|
||||
.replace(/\n$/, "")
|
||||
|
@ -55,6 +55,15 @@ module.exports = function(grunt) {
|
|||
},
|
||||
},
|
||||
|
||||
umd: {
|
||||
all: {
|
||||
src: "dist/browser-polyfill.js",
|
||||
template: "unit",
|
||||
globalAlias: "browser",
|
||||
amdModuleId: "webextension-polyfill",
|
||||
},
|
||||
},
|
||||
|
||||
"closure-compiler": {
|
||||
dist: {
|
||||
files: {
|
||||
|
@ -88,8 +97,9 @@ module.exports = function(grunt) {
|
|||
|
||||
grunt.loadNpmTasks("gruntify-eslint");
|
||||
grunt.loadNpmTasks("grunt-replace");
|
||||
grunt.loadNpmTasks("grunt-umd");
|
||||
grunt.loadNpmTasks("grunt-coveralls");
|
||||
require("google-closure-compiler").grunt(grunt);
|
||||
|
||||
grunt.registerTask("default", ["eslint", "replace", "closure-compiler"]);
|
||||
grunt.registerTask("default", ["eslint", "replace", "umd", "closure-compiler"]);
|
||||
};
|
||||
|
|
|
@ -14,7 +14,6 @@ simply run:
|
|||
|
||||
```sh
|
||||
npm install
|
||||
grunt
|
||||
```
|
||||
|
||||
This will build both non-minified and minified versions of the final library,
|
||||
|
|
10
package.json
10
package.json
|
@ -2,6 +2,12 @@
|
|||
"name": "webextension-polyfill",
|
||||
"version": "0.1.0",
|
||||
"description": "A lightweight polyfill library for Promise-based WebExtension APIs in Chrome.",
|
||||
"main": "src/browser-polyfill.js",
|
||||
"files": [
|
||||
"api-metadata.json",
|
||||
"src",
|
||||
"dist"
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/mozilla/webextension-polyfill.git"
|
||||
|
@ -19,6 +25,7 @@
|
|||
"grunt": "^1.0.1",
|
||||
"grunt-coveralls": "^1.0.1",
|
||||
"grunt-replace": "*",
|
||||
"grunt-umd": "^2.4.0",
|
||||
"gruntify-eslint": "*",
|
||||
"istanbul-lib-instrument": "^1.1.3",
|
||||
"jsdom": "^9.6.0",
|
||||
|
@ -38,6 +45,7 @@
|
|||
"build": "grunt",
|
||||
"test": "mocha",
|
||||
"test-coverage": "COVERAGE=y nyc mocha",
|
||||
"publish-coverage": "grunt coveralls"
|
||||
"publish-coverage": "grunt coveralls",
|
||||
"prepublish": "npm run build"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,9 @@ if (typeof browser === "undefined") {
|
|||
// never actually need to be called, this allows the polyfill to be included
|
||||
// in Firefox nearly for free.
|
||||
const wrapAPIs = () => {
|
||||
const apiMetadata = {/* include("api-metadata.json") */};
|
||||
// Note that `require` does NOT work in general. See discussion here:
|
||||
// https://github.com/mozilla/webextension-polyfill/pull/17#discussion_r99170958
|
||||
const apiMetadata = require("../api-metadata.json"); // eslint-disable-line no-undef
|
||||
|
||||
/**
|
||||
* A WeakMap subclass which creates and stores a value for any key which does
|
||||
|
@ -336,5 +338,9 @@ if (typeof browser === "undefined") {
|
|||
return wrapObject(chrome, staticWrappers, apiMetadata);
|
||||
};
|
||||
|
||||
this.browser = wrapAPIs();
|
||||
// The build process adds a UMD wrapper around this file, which makes the
|
||||
// `module` variable available.
|
||||
module.exports = wrapAPIs(); // eslint-disable-line no-undef
|
||||
} else {
|
||||
module.exports = browser; // eslint-disable-line no-undef
|
||||
}
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
"use strict";
|
||||
|
||||
const {deepEqual, equal, ok} = require("chai").assert;
|
||||
|
||||
module.exports.testCustomProperties = window => {
|
||||
Object.defineProperty(window.browser, "myns", {
|
||||
enumerable: true,
|
||||
configurable: true,
|
||||
value: {mykey: true},
|
||||
});
|
||||
|
||||
ok("myns" in window.browser, "The custom property exists");
|
||||
ok("mykey" in window.browser.myns,
|
||||
"The content of the custom property exists");
|
||||
|
||||
deepEqual(window.browser.myns, {mykey: true},
|
||||
"The custom property has the expected content");
|
||||
|
||||
delete window.browser.myns;
|
||||
|
||||
ok(!("myns" in window.browser),
|
||||
"The deleted custom defined property has been removed");
|
||||
};
|
||||
|
||||
module.exports.testUndefinedProperties = window => {
|
||||
equal(window.browser.myns.mykey, true,
|
||||
"Got the expected result from a wrapped property");
|
||||
equal(window.browser.myns.nonexistent, undefined,
|
||||
"Got undefined for non existent property");
|
||||
equal(window.browser.nonexistent, undefined,
|
||||
"Got undefined for non existent namespaces");
|
||||
};
|
|
@ -1,9 +1,11 @@
|
|||
"use strict";
|
||||
|
||||
const {deepEqual, equal, ok} = require("chai").assert;
|
||||
const {deepEqual, equal} = require("chai").assert;
|
||||
|
||||
const {setupTestDOMWindow} = require("./setup");
|
||||
|
||||
const {testCustomProperties, testUndefinedProperties} = require("./helpers");
|
||||
|
||||
describe("browser-polyfill", () => {
|
||||
it("wraps the global chrome namespace with a global browser namespace", () => {
|
||||
const fakeChrome = {};
|
||||
|
@ -29,37 +31,12 @@ describe("browser-polyfill", () => {
|
|||
describe("browser wrapper", () => {
|
||||
it("supports custom properties defined using Object.defineProperty", () => {
|
||||
const fakeChrome = {};
|
||||
return setupTestDOMWindow(fakeChrome).then(window => {
|
||||
Object.defineProperty(window.browser, "myns", {
|
||||
enumerable: true,
|
||||
configurable: true,
|
||||
value: {mykey: true},
|
||||
});
|
||||
|
||||
ok("myns" in window.browser, "The custom property exists");
|
||||
ok("mykey" in window.browser.myns,
|
||||
"The content of the custom property exists");
|
||||
|
||||
deepEqual(window.browser.myns, {mykey: true},
|
||||
"The custom property has the expected content");
|
||||
|
||||
delete window.browser.myns;
|
||||
|
||||
ok(!("myns" in window.browser),
|
||||
"The deleted custom defined property has been removed");
|
||||
});
|
||||
return setupTestDOMWindow(fakeChrome).then(testCustomProperties);
|
||||
});
|
||||
|
||||
it("returns undefined for property undefined in the target", () => {
|
||||
const fakeChrome = {myns: {mykey: true}};
|
||||
return setupTestDOMWindow(fakeChrome).then(window => {
|
||||
equal(window.browser.myns.mykey, true,
|
||||
"Got the expected result from a wrapped property");
|
||||
equal(window.browser.myns.nonexistent, undefined,
|
||||
"Got undefined for non existent property");
|
||||
equal(window.browser.nonexistent, undefined,
|
||||
"Got undefined for non existent namespaces");
|
||||
});
|
||||
return setupTestDOMWindow(fakeChrome).then(testUndefinedProperties);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
"use strict";
|
||||
|
||||
const {deepEqual, strictEqual, notStrictEqual, throws} = require("chai").assert;
|
||||
const {testCustomProperties, testUndefinedProperties} = require("./helpers");
|
||||
|
||||
describe("node-export", () => {
|
||||
beforeEach(() => {
|
||||
delete global.browser;
|
||||
delete global.chrome;
|
||||
delete require.cache[require.resolve("../")];
|
||||
});
|
||||
|
||||
it("exports the global browser namespace if it already exists", () => {
|
||||
global.browser = {key: "value"};
|
||||
|
||||
const exported = require("../");
|
||||
|
||||
strictEqual(exported, browser);
|
||||
});
|
||||
|
||||
it("exports a wrapper around the global chrome namespace", () => {
|
||||
global.chrome = {key: "value"};
|
||||
|
||||
const exported = require("../");
|
||||
|
||||
deepEqual(exported, chrome);
|
||||
notStrictEqual(exported, chrome);
|
||||
});
|
||||
|
||||
it("throws an error if the global chrome namespace is missing", () => {
|
||||
throws(() => require("../"), ReferenceError, /chrome is not defined/);
|
||||
});
|
||||
|
||||
describe("browser wrapper", () => {
|
||||
it("supports custom properties defined using Object.defineProperty", () => {
|
||||
global.chrome = {};
|
||||
global.browser = require("../");
|
||||
testCustomProperties(global);
|
||||
});
|
||||
|
||||
it("returns undefined for property undefined in the target", () => {
|
||||
global.chrome = {myns: {mykey: true}};
|
||||
global.browser = require("../");
|
||||
testUndefinedProperties(global);
|
||||
});
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue