From e0687dc110c7d64faaa1d7420cd105c036d397ed Mon Sep 17 00:00:00 2001 From: Christopher Deutsch Date: Thu, 20 Dec 2018 12:42:06 -0600 Subject: [PATCH] Use Babel to compile to ES5. Update tests to point to `dist` file. --- .babelrc | 3 + dist/index.js | 277 +++++++++++++++++++++++++++++++++++++++++++++ package.json | 7 +- test/extract.js | 2 +- test/parse-url.js | 2 +- test/parse.js | 2 +- test/properties.js | 2 +- test/stringify.js | 2 +- 8 files changed, 291 insertions(+), 6 deletions(-) create mode 100644 .babelrc create mode 100644 dist/index.js diff --git a/.babelrc b/.babelrc new file mode 100644 index 00000000..8aa924d7 --- /dev/null +++ b/.babelrc @@ -0,0 +1,3 @@ +{ + "presets": ["@babel/preset-env"] +} \ No newline at end of file diff --git a/dist/index.js b/dist/index.js new file mode 100644 index 00000000..054a2467 --- /dev/null +++ b/dist/index.js @@ -0,0 +1,277 @@ +'use strict'; + +function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); } + +function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } + +function _iterableToArrayLimit(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } + +function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } + +function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } + +var strictUriEncode = require('strict-uri-encode'); + +var decodeComponent = require('decode-uri-component'); + +function encoderForArrayFormat(options) { + switch (options.arrayFormat) { + case 'index': + return function (key, value, index) { + return value === null ? [encode(key, options), '[', index, ']'].join('') : [encode(key, options), '[', encode(index, options), ']=', encode(value, options)].join(''); + }; + + case 'bracket': + return function (key, value) { + return value === null ? [encode(key, options), '[]'].join('') : [encode(key, options), '[]=', encode(value, options)].join(''); + }; + + default: + return function (key, value) { + return value === null ? encode(key, options) : [encode(key, options), '=', encode(value, options)].join(''); + }; + } +} + +function parserForArrayFormat(options) { + var result; + + switch (options.arrayFormat) { + case 'index': + return function (key, value, accumulator) { + result = /\[(\d*)\]$/.exec(key); + key = key.replace(/\[\d*\]$/, ''); + + if (!result) { + accumulator[key] = value; + return; + } + + if (accumulator[key] === undefined) { + accumulator[key] = {}; + } + + accumulator[key][result[1]] = value; + }; + + case 'bracket': + return function (key, value, accumulator) { + result = /(\[\])$/.exec(key); + key = key.replace(/\[\]$/, ''); + + if (!result) { + accumulator[key] = value; + return; + } + + if (accumulator[key] === undefined) { + accumulator[key] = [value]; + return; + } + + accumulator[key] = [].concat(accumulator[key], value); + }; + + default: + return function (key, value, accumulator) { + if (accumulator[key] === undefined) { + accumulator[key] = value; + return; + } + + accumulator[key] = [].concat(accumulator[key], value); + }; + } +} + +function encode(value, options) { + if (options.encode) { + return options.strict ? strictUriEncode(value) : encodeURIComponent(value); + } + + return value; +} + +function decode(value, options) { + if (options.decode) { + return decodeComponent(value); + } + + return value; +} + +function keysSorter(input) { + if (Array.isArray(input)) { + return input.sort(); + } + + if (_typeof(input) === 'object') { + return keysSorter(Object.keys(input)).sort(function (a, b) { + return Number(a) - Number(b); + }).map(function (key) { + return input[key]; + }); + } + + return input; +} + +function extract(input) { + var queryStart = input.indexOf('?'); + + if (queryStart === -1) { + return ''; + } + + return input.slice(queryStart + 1); +} + +function parse(input, options) { + options = Object.assign({ + decode: true, + arrayFormat: 'none' + }, options); + var formatter = parserForArrayFormat(options); // Create an object with no prototype + + var ret = Object.create(null); + + if (typeof input !== 'string') { + return ret; + } + + input = input.trim().replace(/^[?#&]/, ''); + + if (!input) { + return ret; + } + + var _iteratorNormalCompletion = true; + var _didIteratorError = false; + var _iteratorError = undefined; + + try { + for (var _iterator = input.split('&')[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { + var param = _step.value; + + var _param$replace$split = param.replace(/\+/g, ' ').split('='), + _param$replace$split2 = _slicedToArray(_param$replace$split, 2), + key = _param$replace$split2[0], + value = _param$replace$split2[1]; // Missing `=` should be `null`: + // http://w3.org/TR/2012/WD-url-20120524/#collect-url-parameters + + + value = value === undefined ? null : decode(value, options); + formatter(decode(key, options), value, ret); + } + } catch (err) { + _didIteratorError = true; + _iteratorError = err; + } finally { + try { + if (!_iteratorNormalCompletion && _iterator.return != null) { + _iterator.return(); + } + } finally { + if (_didIteratorError) { + throw _iteratorError; + } + } + } + + return Object.keys(ret).sort().reduce(function (result, key) { + var value = ret[key]; + + if (Boolean(value) && _typeof(value) === 'object' && !Array.isArray(value)) { + // Sort object keys, not values + result[key] = keysSorter(value); + } else { + result[key] = value; + } + + return result; + }, Object.create(null)); +} + +exports.extract = extract; +exports.parse = parse; + +exports.stringify = function (obj, options) { + if (!obj) { + return ''; + } + + options = Object.assign({ + encode: true, + strict: true, + arrayFormat: 'none' + }, options); + var formatter = encoderForArrayFormat(options); + var keys = Object.keys(obj); + + if (options.sort !== false) { + keys.sort(options.sort); + } + + return keys.map(function (key) { + var value = obj[key]; + + if (value === undefined) { + return ''; + } + + if (value === null) { + return encode(key, options); + } + + if (Array.isArray(value)) { + var result = []; + var _iteratorNormalCompletion2 = true; + var _didIteratorError2 = false; + var _iteratorError2 = undefined; + + try { + for (var _iterator2 = value.slice()[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { + var value2 = _step2.value; + + if (value2 === undefined) { + continue; + } + + result.push(formatter(key, value2, result.length)); + } + } catch (err) { + _didIteratorError2 = true; + _iteratorError2 = err; + } finally { + try { + if (!_iteratorNormalCompletion2 && _iterator2.return != null) { + _iterator2.return(); + } + } finally { + if (_didIteratorError2) { + throw _iteratorError2; + } + } + } + + return result.join('&'); + } + + return encode(key, options) + '=' + encode(value, options); + }).filter(function (x) { + return x.length > 0; + }).join('&'); +}; + +exports.parseUrl = function (input, options) { + var hashStart = input.indexOf('#'); + + if (hashStart !== -1) { + input = input.slice(0, hashStart); + } + + return { + url: input.split('?')[0] || '', + query: parse(extract(input), options) + }; +}; \ No newline at end of file diff --git a/package.json b/package.json index c93d5b91..c64cfdda 100644 --- a/package.json +++ b/package.json @@ -12,8 +12,10 @@ "engines": { "node": ">=6" }, + "main": "dist/index.js", "scripts": { - "test": "xo && ava" + "build": "babel ./index.js -d dist", + "test": "npm run build && xo && ava" }, "files": [ "index.js" @@ -38,6 +40,9 @@ "strict-uri-encode": "^2.0.0" }, "devDependencies": { + "@babel/cli": "^7.2.3", + "@babel/core": "^7.2.2", + "@babel/preset-env": "^7.2.3", "ava": "^0.25.0", "deep-equal": "^1.0.1", "fast-check": "^1.5.0", diff --git a/test/extract.js b/test/extract.js index 76726b77..0bf8c7ed 100644 --- a/test/extract.js +++ b/test/extract.js @@ -1,5 +1,5 @@ import test from 'ava'; -import m from '..'; +import m from '../dist'; test('extracts query string from url', t => { t.is(m.extract('https://foo.bar/?abc=def&hij=klm'), 'abc=def&hij=klm'); diff --git a/test/parse-url.js b/test/parse-url.js index 239427e8..835094ad 100644 --- a/test/parse-url.js +++ b/test/parse-url.js @@ -1,5 +1,5 @@ import test from 'ava'; -import m from '..'; +import m from '../dist'; test('handles strings with query string', t => { t.deepEqual(m.parseUrl('https://foo.bar#top?foo=bar'), {url: 'https://foo.bar', query: {}}); diff --git a/test/parse.js b/test/parse.js index 999cff83..b9054c11 100644 --- a/test/parse.js +++ b/test/parse.js @@ -1,5 +1,5 @@ import test from 'ava'; -import m from '..'; +import m from '../dist'; test('query strings starting with a `?`', t => { t.deepEqual(m.parse('?foo=bar'), {foo: 'bar'}); diff --git a/test/properties.js b/test/properties.js index a2e840c1..bd71d3cb 100644 --- a/test/properties.js +++ b/test/properties.js @@ -1,7 +1,7 @@ import deepEqual from 'deep-equal'; import * as fc from 'fast-check'; import test from 'ava'; -import m from '..'; +import m from '../dist'; // Valid query parameters must follow: // - key can be any unicode string (not empty) diff --git a/test/stringify.js b/test/stringify.js index 0302b507..72711465 100644 --- a/test/stringify.js +++ b/test/stringify.js @@ -1,5 +1,5 @@ import test from 'ava'; -import m from '..'; +import m from '../dist'; test('stringify', t => { t.is(m.stringify({foo: 'bar'}), 'foo=bar');