From e818e69463cb6e0fd1dcef803a8260914c8ad355 Mon Sep 17 00:00:00 2001 From: Satyajit Sahoo Date: Thu, 18 Oct 2018 00:33:35 +0200 Subject: [PATCH] feat: add typescript definitions fixes #197 --- .circleci/config.yml | 5 +- .gitignore | 3 - package.json | 5 ++ src/react/styled.js | 5 +- types/index.d.ts | 51 +++++++++++++++ types/tests/index.tsx | 46 ++++++++++++++ types/tests/react.tsx | 58 +++++++++++++++++ types/tests/server.tsx | 7 +++ types/tsconfig.json | 13 ++++ yarn.lock | 140 ++++++++++++++++++++++++++++++++++++++++- 10 files changed, 323 insertions(+), 10 deletions(-) create mode 100644 types/index.d.ts create mode 100644 types/tests/index.tsx create mode 100644 types/tests/react.tsx create mode 100644 types/tests/server.tsx create mode 100644 types/tsconfig.json diff --git a/.circleci/config.yml b/.circleci/config.yml index 8df782152..617db9c2e 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -30,7 +30,7 @@ jobs: - persist_to_workspace: root: . paths: . - lint-and-flow: + lint-and-typecheck: <<: *defaults steps: - attach_workspace: @@ -38,6 +38,7 @@ jobs: - run: | yarn lint yarn flow + yarn typescript unit-tests: <<: *defaults steps: @@ -74,7 +75,7 @@ workflows: build-and-test: jobs: - install-dependencies - - lint-and-flow: + - lint-and-typecheck: requires: - install-dependencies - unit-tests: diff --git a/.gitignore b/.gitignore index dd26ab471..59878bc80 100644 --- a/.gitignore +++ b/.gitignore @@ -41,9 +41,6 @@ build/Release node_modules/ jspm_packages/ -# Typescript v1 declaration files -typings/ - # Optional npm cache directory .npm diff --git a/package.json b/package.json index 407b2c31c..b971cd700 100644 --- a/package.json +++ b/package.json @@ -3,8 +3,10 @@ "version": "1.0.0-alpha.13", "description": "Blazing fast zero-runtime CSS in JS library", "main": "lib/index.js", + "types": "types/index.d.ts", "files": [ "lib/", + "types/", "react.js", "server.js", "babel.js", @@ -29,6 +31,7 @@ "scripts": { "lint": "eslint .", "flow": "flow", + "typescript": "dtslint types", "test": "jest", "test:unit": "jest __tests__", "test:integration": "jest __integration-tests__", @@ -50,12 +53,14 @@ "@babel/preset-flow": "^7.0.0", "@babel/preset-react": "^7.0.0", "@callstack/eslint-config": "^2.0.0", + "@types/react": "^16.4.18", "all-contributors-cli": "^5.4.0", "babel-core": "^7.0.0-bridge.0", "codecov": "^3.1.0", "conventional-changelog-cli": "^2.0.5", "dedent": "^0.7.0", "del-cli": "^1.1.0", + "dtslint": "^0.3.0", "eslint": "^5.4.0", "flow-bin": "^0.79.1", "flow-copy-source": "^2.0.2", diff --git a/src/react/styled.js b/src/react/styled.js index cbf5c0c40..c50e3fc14 100644 --- a/src/react/styled.js +++ b/src/react/styled.js @@ -82,8 +82,9 @@ type StyledComponent = React.ComponentType; type StyledTag = (strings: string[], ...exprs: Array string | number)>) => StyledComponent; -declare module.exports: {| +type StyledJSXIntrinsics = $ObjMap<$JSXIntrinsics, ({ props: T }) => StyledTag>; + +declare module.exports: StyledJSXIntrinsics & {| (T): StyledTag>, - [string]: StyledTag<{ children?: React.Node, [key: string]: any }>, |}; */ diff --git a/types/index.d.ts b/types/index.d.ts new file mode 100644 index 000000000..45bed4860 --- /dev/null +++ b/types/index.d.ts @@ -0,0 +1,51 @@ +// TypeScript Version: 2.8 + +declare module 'linaria' { + type Falsy = false | undefined | null | 0; + + function css( + strings: TemplateStringsArray, + ...exprs: Array + ): string; + + function cx(...classNames: Array): string; +} + +declare module 'linaria/react' { + import * as React from 'react'; + + type Overwrite = { [P in Exclude]: T1[P] } & T2; + + type InterpolationFunction = (props: T) => string | number; + + type StyledComponent = React.StatelessComponent< + T & { as?: React.ReactType } + >; + + type StyledTag = ( + strings: TemplateStringsArray, + ...exprs: Array> + ) => StyledComponent; + + type StyledJSXIntrinsics = { + [P in keyof JSX.IntrinsicElements]: StyledTag< + JSX.IntrinsicElements[P] & { [key: string]: any } + > + }; + + const styled: StyledJSXIntrinsics & { + (component: React.ReactType): StyledTag; + + [key: string]: StyledTag<{ + children?: React.ReactNode; + [key: string]: any; + }>; + }; +} + +declare module 'linaria/server' { + function collect( + html: string, + css: string + ): { critical: string; other: string }; +} diff --git a/types/tests/index.tsx b/types/tests/index.tsx new file mode 100644 index 000000000..8d0470f9f --- /dev/null +++ b/types/tests/index.tsx @@ -0,0 +1,46 @@ +import { css, cx } from 'linaria'; + +const tomato = 'tomato'; +const border = 1; + +const absoluteFill = { + position: 'absolute', + top: 0, + left: 0, + bottom: 0, + right: 0, +}; + +// $ExpectType string +css` + color: ${tomato}; + border-width: ${border}px; + + &.abs { + ${absoluteFill}; + } +`; + +// $ExpectType string +css`font-family: sans-serif`; + +// $ExpectError +css`color: ${true}`; + +// $ExpectError +css`color: ${undefined}`; + +// $ExpectError +css`color: ${null}`; + +// $ExpectType string +cx('test', false, undefined, null, 0); + +// $ExpectError +cx('test', 42); + +// $ExpectError +cx('test', true); + +// $ExpectError +cx('test', {}); diff --git a/types/tests/react.tsx b/types/tests/react.tsx new file mode 100644 index 000000000..8bd824380 --- /dev/null +++ b/types/tests/react.tsx @@ -0,0 +1,58 @@ +import * as React from 'react'; +import { styled } from 'linaria/react'; + +const white = 'white'; +const tomato = 'tomato'; +const border = 1; + +const absoluteFill = { + position: 'absolute', + top: 0, + left: 0, + bottom: 0, + right: 0, +}; + +const Button = styled.button` + color: ${white}; + background-color: ${props => props.background}; + border-width: ${border}px; + + &.abs { + ${absoluteFill}; + } +`; + +const CustomButton = styled(Button)` + &:hover { + background-color: ${tomato}; + } +`; + +class Title extends React.Component<{ label: string; className?: string }> { + render() { + return

{this.props.label}

; + } +} + +const CustomTitle = styled(Title)` + font-family: sans-serif; +`; + +// $Expect Element +; + +// $ExpectError +; + +// $Expect Element + alert('Clicked')}>Hello world; + +// $Expect Element +; + +// $Expect Element +; + +// $ExpectError +; diff --git a/types/tests/server.tsx b/types/tests/server.tsx new file mode 100644 index 000000000..c61f3953e --- /dev/null +++ b/types/tests/server.tsx @@ -0,0 +1,7 @@ +import { collect } from 'linaria/server'; + +// $ExpectType { critical: string; other: string; } +collect( + '
Hello
', + '.foo { color: blue; }' +); diff --git a/types/tsconfig.json b/types/tsconfig.json new file mode 100644 index 000000000..698de8c1e --- /dev/null +++ b/types/tsconfig.json @@ -0,0 +1,13 @@ +{ + "compilerOptions": { + "module": "commonjs", + "lib": ["es6", "dom"], + "noImplicitAny": true, + "noImplicitThis": true, + "strictNullChecks": true, + "strictFunctionTypes": true, + "noEmit": true, + "forceConsistentCasingInFileNames": true, + "jsx": "react" + } +} diff --git a/yarn.lock b/yarn.lock index 851f7f6fa..e1376c510 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1000,6 +1000,24 @@ resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.7.0.tgz#9a06f4f137ee84d7df0460c1fdb1135ffa6c50fd" integrity sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow== +"@types/parsimmon@^1.3.0": + version "1.10.0" + resolved "https://registry.yarnpkg.com/@types/parsimmon/-/parsimmon-1.10.0.tgz#ffb81cb023ff435a41d4710a29ab23c561dc9fdf" + integrity sha512-bsTIJFVQv7jnvNiC42ld2pQW2KRI+pAG243L+iATvqzy3X6+NH1obz2itRKDZZ8VVhN3wjwYax/VBGCcXzgTqQ== + +"@types/prop-types@*": + version "15.5.6" + resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.5.6.tgz#9c03d3fed70a8d517c191b7734da2879b50ca26c" + integrity sha512-ZBFR7TROLVzCkswA3Fmqq+IIJt62/T7aY/Dmz+QkU7CaW2QFqAitCE8Ups7IzmGhcN1YWMBT4Qcoc07jU9hOJQ== + +"@types/react@^16.4.18": + version "16.4.18" + resolved "https://registry.yarnpkg.com/@types/react/-/react-16.4.18.tgz#2e28a2e7f92d3fa7d6a65f2b73275c3e3138a13d" + integrity sha512-eFzJKEg6pdeaukVLVZ8Xb79CTl/ysX+ExmOfAAqcFlCCK5TgFDD9kWR0S18sglQ3EmM8U+80enjUqbfnUyqpdA== + dependencies: + "@types/prop-types" "*" + csstype "^2.2.0" + JSONStream@^1.0.4: version "1.3.4" resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.4.tgz#615bb2adb0cd34c8f4c447b5f6512fa1d8f16a2e" @@ -1150,6 +1168,11 @@ ansi-styles@^3.2.1: dependencies: color-convert "^1.9.0" +any-promise@^1.0.0, any-promise@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" + integrity sha1-q8av7tzqUugJzcA3au0845Y10X8= + anymatch@^1.3.0: version "1.3.2" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-1.3.2.tgz#553dcb8f91e3c889845dfdba34c77721b90b9d7a" @@ -1381,7 +1404,7 @@ axobject-query@^2.0.1: dependencies: ast-types-flow "0.0.7" -babel-code-frame@^6.26.0: +babel-code-frame@^6.22.0, babel-code-frame@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" integrity sha1-Y/1D99weO7fONZR9uP42mj9Yx0s= @@ -2068,7 +2091,7 @@ buffer-from@^1.0.0: resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== -builtin-modules@^1.0.0: +builtin-modules@^1.0.0, builtin-modules@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" integrity sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8= @@ -2392,6 +2415,11 @@ commander@^2.11.0, commander@^2.8.1: resolved "https://registry.yarnpkg.com/commander/-/commander-2.18.0.tgz#2bf063ddee7c7891176981a2cc798e5754bc6970" integrity sha512-6CYPa+JP2ftfRU2qkDK+UTVeQYosOg/2GbcjIcKPHfinyOLPVGXu/ovN86RP49Re5ndJK1N0kuiidFFuepc4ZQ== +commander@^2.12.1: + version "2.19.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a" + integrity sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg== + commander@~2.17.1: version "2.17.1" resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf" @@ -2727,6 +2755,11 @@ cssstyle@^1.0.0: dependencies: cssom "0.3.x" +csstype@^2.2.0: + version "2.5.7" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.5.7.tgz#bf9235d5872141eccfb2d16d82993c6b149179ff" + integrity sha512-Nt5VDyOTIIV4/nRFswoCKps1R5CD1hkiyjBE9/thNaNZILLEviVw9yWQw15+O+CpNjQKB/uvdcxFFOrSflY3Yw== + currently-unhandled@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea" @@ -2884,6 +2917,13 @@ define-property@^2.0.2: is-descriptor "^1.0.2" isobject "^3.0.1" +"definitelytyped-header-parser@github:Microsoft/definitelytyped-header-parser#production": + version "0.0.0" + resolved "https://codeload.github.com/Microsoft/definitelytyped-header-parser/tar.gz/c79916047989994b21f3332771c6b97191c03d38" + dependencies: + "@types/parsimmon" "^1.3.0" + parsimmon "^1.2.0" + del-cli@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/del-cli/-/del-cli-1.1.0.tgz#27557d69a0b7df99dcbaa1e34a09e6ac6591d2c4" @@ -2999,6 +3039,17 @@ dot-prop@^4.1.0: dependencies: is-obj "^1.0.0" +dtslint@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/dtslint/-/dtslint-0.3.0.tgz#918e664a6f7e1f54ba22088daa2bc6e64a6001c1" + integrity sha512-3oWL8MD+2nKaxmNzrt8EAissP63hNSJ4OLr/itvNnPdAAl+7vxnjQ8p2Zdk0MNgdenqwk7GcaUDz7fQHaPgCyA== + dependencies: + definitelytyped-header-parser Microsoft/definitelytyped-header-parser#production + fs-promise "^2.0.0" + strip-json-comments "^2.0.1" + tslint "^5.9.1" + typescript next + duplexer3@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" @@ -3698,6 +3749,14 @@ from2@^2.1.1: inherits "^2.0.1" readable-stream "^2.0.0" +fs-extra@^2.0.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-2.1.2.tgz#046c70163cef9aad46b0e4a7fa467fb22d71de35" + integrity sha1-BGxwFjzvmq1GsOSn+kZ/si1x3jU= + dependencies: + graceful-fs "^4.1.2" + jsonfile "^2.1.0" + fs-extra@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.0.tgz#8cc3f47ce07ef7b3593a11b9fb245f7e34c041d6" @@ -3714,6 +3773,16 @@ fs-minipass@^1.2.5: dependencies: minipass "^2.2.1" +fs-promise@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/fs-promise/-/fs-promise-2.0.3.tgz#f64e4f854bcf689aa8bddcba268916db3db46854" + integrity sha1-9k5PhUvPaJqovdy6JokW2z20aFQ= + dependencies: + any-promise "^1.3.0" + fs-extra "^2.0.0" + mz "^2.6.0" + thenify-all "^1.6.0" + fs-readdir-recursive@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz#e32fc030a2ccee44a6b5371308da54be0b397d27" @@ -5317,6 +5386,13 @@ json5@^0.5.0: resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" integrity sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE= +jsonfile@^2.1.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-2.4.0.tgz#3736a2b428b87bbda0cc83b53fa3d633a35c2ae8" + integrity sha1-NzaitCi4e72gzIO1P6PWM6NcKug= + optionalDependencies: + graceful-fs "^4.1.6" + jsonfile@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" @@ -5850,6 +5926,15 @@ mute-stream@0.0.7: resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s= +mz@^2.6.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32" + integrity sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q== + dependencies: + any-promise "^1.0.0" + object-assign "^4.0.1" + thenify-all "^1.0.0" + nan@^2.3.0: version "2.7.0" resolved "https://registry.yarnpkg.com/nan/-/nan-2.7.0.tgz#d95bf721ec877e08db276ed3fc6eb78f9083ad46" @@ -6334,6 +6419,11 @@ parse5@4.0.0: resolved "https://registry.yarnpkg.com/parse5/-/parse5-4.0.0.tgz#6d78656e3da8d78b4ec0b906f7c08ef1dfe3f608" integrity sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA== +parsimmon@^1.2.0: + version "1.12.0" + resolved "https://registry.yarnpkg.com/parsimmon/-/parsimmon-1.12.0.tgz#886a442fb30b5fc3c8e7c4994050f5cdcfe0ea90" + integrity sha512-uC/BjuSfb4jfaWajKCp1mVncXXq+V1twbcYChbTxN3GM7fn+8XoHwUdvUz+PTaFtDSCRQxU8+Rnh+iMhAkVwdw== + pascalcase@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" @@ -7750,6 +7840,20 @@ text-table@^0.2.0: resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= +thenify-all@^1.0.0, thenify-all@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/thenify-all/-/thenify-all-1.6.0.tgz#1a1918d402d8fc3f98fbf234db0bcc8cc10e9726" + integrity sha1-GhkY1ALY/D+Y+/I02wvMjMEOlyY= + dependencies: + thenify ">= 3.1.0 < 4" + +"thenify@>= 3.1.0 < 4": + version "3.3.0" + resolved "https://registry.yarnpkg.com/thenify/-/thenify-3.3.0.tgz#e69e38a1babe969b0108207978b9f62b88604839" + integrity sha1-5p44obq+lpsBCCB5eLn2K4hgSDk= + dependencies: + any-promise "^1.0.0" + throat@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/throat/-/throat-4.1.0.tgz#89037cbc92c56ab18926e6ba4cbb200e15672a6a" @@ -7870,11 +7974,36 @@ trim-right@^1.0.1: resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" integrity sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM= -tslib@^1.9.0: +tslib@^1.8.0, tslib@^1.8.1, tslib@^1.9.0: version "1.9.3" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286" integrity sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ== +tslint@^5.9.1: + version "5.11.0" + resolved "https://registry.yarnpkg.com/tslint/-/tslint-5.11.0.tgz#98f30c02eae3cde7006201e4c33cb08b48581eed" + integrity sha1-mPMMAurjzecAYgHkwzywi0hYHu0= + dependencies: + babel-code-frame "^6.22.0" + builtin-modules "^1.1.1" + chalk "^2.3.0" + commander "^2.12.1" + diff "^3.2.0" + glob "^7.1.1" + js-yaml "^3.7.0" + minimatch "^3.0.4" + resolve "^1.3.2" + semver "^5.3.0" + tslib "^1.8.0" + tsutils "^2.27.2" + +tsutils@^2.27.2: + version "2.29.0" + resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-2.29.0.tgz#32b488501467acbedd4b85498673a0812aca0b99" + integrity sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA== + dependencies: + tslib "^1.8.1" + tunnel-agent@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" @@ -7899,6 +8028,11 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= +typescript@next: + version "3.2.0-dev.20181018" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.2.0-dev.20181018.tgz#2f05d613e86d06d814214a1101b3b8bf58d52950" + integrity sha512-BML75AnK2PZu54xULlF3zQaJh1flrtt66NEYc4NBHZwCh1jFbVP2E8nNpoRcZyMh4EiSCvX3r6zUpPYcY10vzQ== + uglify-js@^2.6: version "2.8.29" resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.29.tgz#29c5733148057bb4e1f75df35b7a9cb72e6a59dd"