Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove @financial-times/polyfill-useragent-normaliser dependency #92

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
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
52 changes: 50 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,9 @@ npm install @mrhenry/polyfill-library --save

```javascript
const polyfillLibrary = require('@mrhenry/polyfill-library');
const UA = require('@financial-times/polyfill-useragent-normaliser');

const polyfillBundle = polyfillLibrary.getPolyfillString({
ua: new UA('Mozilla/5.0 (Windows; U; MSIE 7.0; Windows NT 6.0; en-US)'),
ua: yourUserAgentParser('Mozilla/5.0 (Windows; U; MSIE 7.0; Windows NT 6.0; en-US)')
minify: true,
features: {
'es6': { flags: ['gated'] }
Expand Down Expand Up @@ -82,6 +81,55 @@ Create a polyfill bundle.

Returns a polyfill bundle as either a utf-8 ReadStream or as a Promise of a utf-8 String.

## User Agent normalizing

Support data only exists for the most common browsers (e.g. Chrome, Firefox, Safari, ...). To map any user agent to a list of needed polyfills you need to normalize the user agent to one of the known browser families and their corresponding version.

Since the `@financial-times/polyfill-useragent-normaliser` package was deprecated you might need to provide your own solution.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wish we could provide a solution here. I think it will be difficult for another organization to provide this library, given that the list of normalized families and versions is so tightly coupled to polyfill-library.

What if we publish our own normalizer? At first, it could just be a wrapper around @financial-times/polyfill-useragent-normaliser (thus avoiding users of polyfill-library depending directly on it), and then we can decide whether we want to fork it or transition to another normalizer.


A minimal UA normalizer needs to be able to parse a user agent string and return an object with these functions:

```js
const semver = require('semver');

function parse(uaString) {
const parsed = yourParser(uaString);

// Depending on your implementation this will differ:
const version = parsed.version;
const browser = parsed.browser;

return {
isUnknown: () => {
// When the browser and/or version are unrecognized
return this.getFamily() === 'other';
},
getFamily: () => {
// Must be one of:
// - android
// - bb
// - chrome
// - edge
// - edge_mob
// - firefox
// - firefox_mob
// - ie
// - ie_mob
// - opera
// - op_mob
// - op_mini
// - safari
// - ios_saf
// - samsung_mob
return browser;
},
satisfies: (range) => {
return semver.satisfies(this.getVersion(), range);
}
}
}
```

## Contributing

Development of @mrhenry/polyfill-library happens on GitHub. Read below to learn how you can take part in contributing.
Expand Down
41 changes: 11 additions & 30 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@
"/types"
],
"devDependencies": {
"@financial-times/polyfill-useragent-normaliser": "^2.0.1",
"@iarna/toml": "^2.2.5",
"apicache": "^1.6.3",
"browserstack": "1.6.1",
Expand Down
8 changes: 3 additions & 5 deletions tasks/buildsources/polyfill.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,14 @@
const fs = require('node:fs');
const path = require('node:path');
const uglify = require('uglify-js');
const UA = require('@financial-times/polyfill-useragent-normaliser');
const TOML = require('@iarna/toml');

const validateSource = require('./validate-source');
const semver = require('semver');
const osiApproved = require('./osi-approved');

const uaBaselines = UA.getBaselines();
delete uaBaselines.ios_chr; // https://github.com/Financial-Times/polyfill-library/issues/1202#issuecomment-1193403165
const supportedBrowsers = Object.keys(uaBaselines).sort((a, b) => a.localeCompare(b));
const configTemplate = fs.readFileSync(path.join(__dirname, '..', 'polyfill-templates', 'config.toml'), { encoding: 'utf-8' });
const supportedBrowsers = Object.keys(TOML.parse(configTemplate).browsers).sort((a, b) => a.localeCompare(b));

/**
* Polyfill represents a single polyfill directory.
Expand Down Expand Up @@ -147,7 +145,7 @@ module.exports = class Polyfill {
.then(data => {
this.config = TOML.parse(data);

// Each internal polyfill needs to target all supported browsers at all versions.
// Each internal polyfill needs to target all default browsers at all versions.
if (this.path.relative.startsWith('_') && !supportedBrowsers.every(browser => this.config.browsers[browser] === "*")) {
const browserSupport = {};
for (const browser of supportedBrowsers) browserSupport[browser] = "*";
Expand Down
8 changes: 4 additions & 4 deletions test/end-to-end/generating-bundles.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ const test = require('node:test');
const { describe, it } = test;

const assert = require('node:assert');
const UA = require("@financial-times/polyfill-useragent-normaliser");
const ua_parser = require('../polyfills/ua-parser');
const polyfillLibrary = require('../..');

describe("polyfill-library", function () {
Expand All @@ -13,15 +13,15 @@ describe("polyfill-library", function () {
features: {
all: {}
},
ua: new UA('other/0.0.0'),
ua: ua_parser('other/0.0.0'),
unknown: 'polyfill'
});

const bundle2 = await polyfillLibrary.getPolyfillString({
features: {
all: {}
},
ua: new UA('other/0.0.0'),
ua: ua_parser('other/0.0.0'),
unknown: 'polyfill'
});

Expand All @@ -44,7 +44,7 @@ describe("polyfill-library", function () {
'__proto__': {},
'toLocaleString': {},
},
ua: new UA('other/0.0.0'),
ua: ua_parser('other/0.0.0'),
unknown: 'polyfill'
});
});
Expand Down
32 changes: 16 additions & 16 deletions test/node/lib/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ const test = require('node:test');
const { describe, it } = test;

const assert = require('node:assert');
const UA = require("@financial-times/polyfill-useragent-normaliser");
const ua_parser = require('../../polyfills/ua-parser');

const appVersion = require("../../../package.json").version;

Expand All @@ -16,7 +16,7 @@ describe(".getPolyfills(features)", async () => {
features: {
'Promise': {}
},
ua: new UA('chrome/45')
ua: ua_parser('chrome/45')
};
return polyfillio.getPolyfills(input).then(result => assert.deepEqual(result, {}));
});
Expand All @@ -29,7 +29,7 @@ describe(".getPolyfills(features)", async () => {
'es7': {},
},
excludes: ['Array.prototype.values'],
ua: new UA('chrome/61')
ua: ua_parser('chrome/61')
};
return polyfillio.getPolyfills(input).then(result => assert.deepEqual(result, {
"Array.prototype.sort": {
Expand Down Expand Up @@ -65,7 +65,7 @@ describe(".getPolyfills(features)", async () => {
features: {
'Math.sign': {}
},
ua: new UA('')
ua: ua_parser('')
}).then(result => assert.deepEqual(result, {
'Math.sign': {
"flags": new Set(["gated"]),
Expand All @@ -87,7 +87,7 @@ describe(".getPolyfills(features)", async () => {
features: {
'Math.sign': {}
},
ua: new UA(''),
ua: ua_parser(''),
unknown: 'ignore',
}).then(result => assert.deepEqual(result, {}));
});
Expand All @@ -98,7 +98,7 @@ describe(".getPolyfills(features)", async () => {
'Math.sign': {}
},
unknown: 'polyfill',
ua: new UA('')
ua: ua_parser('')
}).then(result => assert.deepEqual(result, {
'Math.sign': {
"flags": new Set(["gated"]),
Expand Down Expand Up @@ -145,7 +145,7 @@ describe(".getPolyfills(features)", async () => {
flags: []
}
},
ua: new UA('ie/8')
ua: ua_parser('ie/8')
}).then(result => assert(Object.keys(result).length > 0));
});

Expand All @@ -154,7 +154,7 @@ describe(".getPolyfills(features)", async () => {
features: {
"Math.fround": {}
},
ua: new UA("ie/9")
ua: ua_parser("ie/9")
});

assert.deepEqual(noExcludes, {
Expand All @@ -180,7 +180,7 @@ describe(".getPolyfills(features)", async () => {
"Math.fround": {}
},
excludes: ["ArrayBuffer", "non-existent-feature"],
ua: new UA("ie/9")
ua: ua_parser("ie/9")
});

assert.deepEqual(excludes, {
Expand All @@ -206,15 +206,15 @@ describe('.getPolyfillString', async () => {
features: {
default: {}
},
ua: new UA('chrome/30')
ua: ua_parser('chrome/30')
}),
polyfillio.getPolyfillString({
features: {
default: {
flags: new Set(['gated'])
}
},
ua: new UA('chrome/30')
ua: ua_parser('chrome/30')
})
]).then(results => {
assert.notEqual(results[0], results[1]);
Expand All @@ -231,14 +231,14 @@ describe('.getPolyfillString', async () => {
features: {
default: {}
},
ua: new UA('chrome/30'),
ua: ua_parser('chrome/30'),
minify: false
}),
polyfillio.getPolyfillString({
features: {
default: {}
},
ua: new UA('chrome/30'),
ua: ua_parser('chrome/30'),
minify: true
})
]).then(results => {
Expand All @@ -260,7 +260,7 @@ describe('.getPolyfillString', async () => {
features: {
default: {}
},
ua: new UA('chrome/30'),
ua: ua_parser('chrome/30'),
stream: true,
minify: false
});
Expand Down Expand Up @@ -330,7 +330,7 @@ describe('.getPolyfillString', async () => {
features: {
default: {}
},
ua: new UA('ie/9'),
ua: ua_parser('ie/9'),
stream: true,
minify: false
});
Expand All @@ -345,7 +345,7 @@ describe('.getPolyfillString', async () => {
features: {
default: {}
},
ua: new UA('ie/9'),
ua: ua_parser('ie/9'),
stream: true,
minify: false
});
Expand Down
Loading
Loading