diff --git a/babel.config.js b/babel.config.js index 89452807..ca7fdee2 100644 --- a/babel.config.js +++ b/babel.config.js @@ -3,13 +3,16 @@ module.exports = api => { const presets = [ ["@babel/env", { - targets: { - esmodules: isESMBuild, - }, + debug: true, loose: true, }], "@babel/flow", ]; + if (isESMBuild) { + presets[0][1].targets = { + esmodules: true, + }; + } const plugins = [ "@babel/transform-runtime", ["@babel/proposal-class-properties", { diff --git a/docs/font.md b/docs/font.md index 31088a01..bfaa05c9 100644 --- a/docs/font.md +++ b/docs/font.md @@ -25,19 +25,17 @@ will appear larger than 1cm in browser units. ## Kinds of fonts used -The default build of KaTeX includes each of the needed fonts in three different formats: `ttf`, `woff`, and `woff2`. +KaTeX provides fonts in three different formats: `ttf`, `woff`, and `woff2`. -- `ttf`s are included to support old versions of Chrome, Safari, Firefox, etc. (Here "old" means Firefox 3.5, Chrome < 5, and Safari <= 5.1, all of which are no longer supported: see [woff](https://caniuse.com/#search=woff) vs. [ttf](https://caniuse.com/#search=ttf)). -- `woff` is the format that is most widely supported (all modern browsers support it), so it probably provides the most benefit to being included. -- `woff2`s are included for very new versions of Chrome, because they are much smaller and faster to load. +- `ttf`s are included to support very old browsers and local installation. [Browser support](https://caniuse.com/#feat=ttf) +- `woff` is the format that is most widely supported (all modern browsers support it), so it probably provides the most benefit to being included. [Browser support](https://caniuse.com/#feat=woff) +- `woff2`s are included for modern browsers, because they are much smaller and faster to load. [Browser support](https://caniuse.com/#feat=woff2) -Based on this information and what you want to support with your website, you might decide to include different versions of the fonts besides what comes with the standard installation. +KaTeX will automatically include only necessary fonts for target environments +specified by [Browserslist config](https://github.com/browserslist/browserslist#queries). -For example, if you wanted to create a trimmed down version of KaTeX, you could only include the `woff` files and gain the most support with the least number of files. To do this: - -1. Set `@use-ttf`, and `@use-woff2` to `false` at the top of [fonts.less](https://github.com/KaTeX/katex-fonts/blob/master/fonts.less). -2. Rebuild KaTeX by running `yarn build` from the top-level directory. -3. Include only the `build/fonts/*.woff` files in your distribution. +To force a font type to be included or excluded, set `USE_(FONT NAME)` environment +variable to `"true"` or `"false"`, respectively.` ## Location of font files diff --git a/docs/node.md b/docs/node.md index 36d007c3..776feee3 100644 --- a/docs/node.md +++ b/docs/node.md @@ -36,6 +36,16 @@ yarn yarn build ``` +It will automatically transpile code and include only necessary fonts for +target environments specified by [Browserslist config](https://github.com/browserslist/browserslist#environment-variables). +For example, if you are making a web app for a kiosk with Chrome 68, run +`BROWSERSLIST="Chrome 68" yarn build` and it will produce build with no +transpilation, as it fully supports ES6, and only include WOFF2 fonts. + +You can override included fonts using environment variables. Set `USE_(FONT NAME)` +environment variable to `"true"` or `"false"`, to force a font type to be included +or excluded, respectively.` + If you'd like to use the built KaTeX in other projects, install the package by specifying the path: ```bash diff --git a/package.json b/package.json index 7187e729..1b6a1b40 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,8 @@ "babel-plugin-istanbul": "^5.0.1", "babel-plugin-version-inline": "^1.0.0", "benchmark": "^2.1.4", + "browserslist": "^4.3.4", + "caniuse-lite": "^1.0.30000900", "codecov": "^3.0.4", "css-loader": "^1.0.0", "cssnano": "^4.0.1", @@ -65,7 +67,7 @@ "style-loader": "^0.23.0", "stylelint": "9.6.0", "stylelint-config-standard": "^18.0.0", - "uglifyjs-webpack-plugin": "^2.0.0", + "terser-webpack-plugin": "^1.1.0", "webpack": "^4.9.1", "webpack-bundle-analyzer": "^3.0.0", "webpack-cli": "^3.0.1", diff --git a/webpack.common.js b/webpack.common.js index b06555c9..b2630d65 100644 --- a/webpack.common.js +++ b/webpack.common.js @@ -1,8 +1,14 @@ // @flow const path = require('path'); -const UglifyJsPlugin = require('uglifyjs-webpack-plugin'); +const TerserPlugin = require('terser-webpack-plugin'); const MiniCssExtractPlugin = require('mini-css-extract-plugin'); +const browserslist = require('browserslist')(); +const caniuse = require('caniuse-lite'); + +// from the least supported to the most supported +const fonts = ['woff2', 'woff', 'ttf']; + /*:: type Target = {| name: string, // the name of output JS/CSS @@ -53,11 +59,19 @@ function createConfig(target /*: Target */, dev /*: boolean */, }); } - const lessOptions = {}; - if (process.env.USE_TTF === "false") { - lessOptions.modifyVars = { - 'use-ttf': false, - }; + // use only necessary fonts, overridable by environment variables + const lessOptions = {modifyVars: {}}; + let isCovered = false; + for (const font of fonts) { + const override = process.env[`USE_${font.toUpperCase()}`]; + const useFont = override === "true" || override !== "false" && !isCovered; + lessOptions.modifyVars[`use-${font}`] = useFont; + + const support = caniuse.feature(caniuse.features[font]).stats; + isCovered = isCovered || useFont && browserslist.every(browser => { + const [name, version] = browser.split(' '); + return !support[name] || support[name][version] === 'y'; + }); } return { @@ -123,8 +137,8 @@ function createConfig(target /*: Target */, dev /*: boolean */, optimization: { minimize, minimizer: [ - new UglifyJsPlugin({ - uglifyOptions: { + new TerserPlugin({ + terserOptions: { output: { ascii_only: true, }, diff --git a/yarn.lock b/yarn.lock index 74763f79..deb1ede1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1715,23 +1715,14 @@ browserify-zlib@^0.2.0: dependencies: pako "~1.0.5" -browserslist@^4.0.0, browserslist@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.0.1.tgz#61c05ce2a5843c7d96166408bc23d58b5416e818" - integrity sha512-QqiiIWchEIkney3wY53/huI7ZErouNAdvOkjorUALAwRcu3tEwOV3Sh6He0DnP38mz1JjBpCBb50jQBmaYuHPw== +browserslist@^4.0.0, browserslist@^4.0.1, browserslist@^4.1.0, browserslist@^4.3.4: + version "4.3.4" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.3.4.tgz#4477b737db6a1b07077275b24791e680d4300425" + integrity sha512-u5iz+ijIMUlmV8blX82VGFrB9ecnUg5qEt55CMZ/YJEhha+d8qpBfOFuutJ6F/VKRXjZoD33b6uvarpPxcl3RA== dependencies: - caniuse-lite "^1.0.30000865" - electron-to-chromium "^1.3.52" - node-releases "^1.0.0-alpha.10" - -browserslist@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.1.0.tgz#81cbb8e52dfa09918f93c6e051d779cb7360785d" - integrity sha512-kQBKB8hnq1SRfSpwHDpM1JNHAyk9fydW8hIDvndR2ijTFKIlBPEvkJkCt8JznOugdm12/YCaRgyq/sqDGz9PwA== - dependencies: - caniuse-lite "^1.0.30000878" - electron-to-chromium "^1.3.61" - node-releases "^1.0.0-alpha.11" + caniuse-lite "^1.0.30000899" + electron-to-chromium "^1.3.82" + node-releases "^1.0.1" bser@^2.0.0: version "2.0.0" @@ -1803,10 +1794,10 @@ cacache@^10.0.4: unique-filename "^1.1.0" y18n "^4.0.0" -cacache@^11.2.0: - version "11.2.0" - resolved "https://registry.yarnpkg.com/cacache/-/cacache-11.2.0.tgz#617bdc0b02844af56310e411c0878941d5739965" - integrity sha512-IFWl6lfK6wSeYCHUXh+N1lY72UDrpyrYQJNIVQf48paDuWbv5RbAtJYf/4gUQFObTCHZwdZ5sI8Iw7nqwP6nlQ== +cacache@^11.0.2: + version "11.3.1" + resolved "https://registry.yarnpkg.com/cacache/-/cacache-11.3.1.tgz#d09d25f6c4aca7a6d305d141ae332613aa1d515f" + integrity sha512-2PEw4cRRDu+iQvBTTuttQifacYjLPhET+SYO/gEFMy8uhi+jlJREDAjSF5FWSdV/Aw5h18caHA7vMTw2c+wDzA== dependencies: bluebird "^3.5.1" chownr "^1.0.1" @@ -1902,15 +1893,10 @@ caniuse-api@^3.0.0: lodash.memoize "^4.1.2" lodash.uniq "^4.5.0" -caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000865: - version "1.0.30000865" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000865.tgz#70026616e8afe6e1442f8bb4e1092987d81a2f25" - integrity sha512-vs79o1mOSKRGv/1pSkp4EXgl4ZviWeYReXw60XfacPU64uQWZwJT6vZNmxRF9O+6zu71sJwMxLK5JXxbzuVrLw== - -caniuse-lite@^1.0.30000878: - version "1.0.30000878" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000878.tgz#c644c39588dd42d3498e952234c372e5a40a4123" - integrity sha512-/dCGTdLCnjVJno1mFRn7Y6eit3AYaeFzSrMQHCoK0LEQaWl5snuLex1Ky4b8/Qu2ig5NgTX4cJx65hH9546puA== +caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000865, caniuse-lite@^1.0.30000899, caniuse-lite@^1.0.30000900: + version "1.0.30000900" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000900.tgz#015cfe37897a3386a3075a914498800c29afe77e" + integrity sha512-xDVs8pBFr6bzq9pXUkLKpGQQnzsF/l6/yX38UnCkTcUcwC0rDl1NGZGildcJVTU+uGBxfsyniK/ZWagPNn1Oqw== capture-exit@^1.2.0: version "1.2.0" @@ -2953,15 +2939,10 @@ ejs@^2.6.1: resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.6.1.tgz#498ec0d495655abc6f23cd61868d926464071aa0" integrity sha512-0xy4A/twfrRCnkhfk8ErDi5DqdAsAqeGxht4xkCUrsvhhbQNs7E+4jV0CN7+NKIY0aHE72+XvqtBIXzD31ZbXQ== -electron-to-chromium@^1.3.52: - version "1.3.52" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.52.tgz#d2d9f1270ba4a3b967b831c40ef71fb4d9ab5ce0" - integrity sha1-0tnxJwuko7lnuDHEDvcftNmrXOA= - -electron-to-chromium@^1.3.61: - version "1.3.61" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.61.tgz#a8ac295b28d0f03d85e37326fd16b6b6b17a1795" - integrity sha512-XjTdsm6x71Y48lF9EEvGciwXD70b20g0t+3YbrE+0fPFutqV08DSNrZXkoXAp3QuzX7TpL/OW+/VsNoR9GkuNg== +electron-to-chromium@^1.3.82: + version "1.3.82" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.82.tgz#7d13ae4437d2a783de3f4efba96b186c540b67b1" + integrity sha512-NI4nB2IWGcU4JVT1AE8kBb/dFor4zjLHMLsOROPahppeHrR0FG5uslxMmkp/thO1MvPjM2xhlKoY29/I60s0ew== elliptic@^6.0.0: version "6.4.0" @@ -6237,17 +6218,10 @@ node-pre-gyp@^0.10.0: semver "^5.3.0" tar "^4" -node-releases@^1.0.0-alpha.10: - version "1.0.0-alpha.10" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.0.0-alpha.10.tgz#61c8d5f9b5b2e05d84eba941d05b6f5202f68a2a" - integrity sha512-BSQrRgOfN6L/MoKIa7pRUc7dHvflCXMcqyTBvphixcSsgJTuUd24vAFONuNfVsuwTyz28S1HEc9XN6ZKylk4Hg== - dependencies: - semver "^5.3.0" - -node-releases@^1.0.0-alpha.11: - version "1.0.0-alpha.11" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.0.0-alpha.11.tgz#73c810acc2e5b741a17ddfbb39dfca9ab9359d8a" - integrity sha512-CaViu+2FqTNYOYNihXa5uPS/zry92I3vPU4nCB6JB3OeZ2UGtOpF5gRwuN4+m3hbEcL47bOXyun1jX2iC+3uEQ== +node-releases@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.0.1.tgz#957a2735d2ca737d7005588f8e85e6c27032555b" + integrity sha512-/kOv7jA26OBwkBPx6B9xR/FzJzs2OkMtcWjS8uPQRMHE7IELdSfN0QKZvmiWnf5P1QJ8oYq/e9qe0aCZISB1pQ== dependencies: semver "^5.3.0" @@ -8302,7 +8276,7 @@ source-map-support@^0.4.15: dependencies: source-map "^0.5.6" -source-map-support@^0.5.6, source-map-support@^0.5.9: +source-map-support@^0.5.6, source-map-support@^0.5.9, source-map-support@~0.5.6: version "0.5.9" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.9.tgz#41bc953b2534267ea2d605bccfa7bfa3111ced5f" integrity sha512-gR6Rw4MvUlYy83vP0vxoVNzM6t8MUXqNuRsuBmBHQDu1Fh6X015FrLdgoDKcNdkwGubozq0P4N0Q37UyFVr1EA== @@ -8791,6 +8765,29 @@ tar@^4: safe-buffer "^5.1.2" yallist "^3.0.2" +terser-webpack-plugin@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-1.1.0.tgz#cf7c25a1eee25bf121f4a587bb9e004e3f80e528" + integrity sha512-61lV0DSxMAZ8AyZG7/A4a3UPlrbOBo8NIQ4tJzLPAdGOQ+yoNC7l5ijEow27lBAL2humer01KLS6bGIMYQxKoA== + dependencies: + cacache "^11.0.2" + find-cache-dir "^2.0.0" + schema-utils "^1.0.0" + serialize-javascript "^1.4.0" + source-map "^0.6.1" + terser "^3.8.1" + webpack-sources "^1.1.0" + worker-farm "^1.5.2" + +terser@^3.8.1: + version "3.10.11" + resolved "https://registry.yarnpkg.com/terser/-/terser-3.10.11.tgz#e063da74b194dde9faf0a561f3a438c549d2da3f" + integrity sha512-iruZ7j14oBbRYJC5cP0/vTU7YOWjN+J1ZskEGoF78tFzXdkK2hbCL/3TRZN8XB+MuvFhvOHMp7WkOCBO4VEL5g== + dependencies: + commander "~2.17.1" + source-map "~0.6.1" + source-map-support "~0.5.6" + test-exclude@^4.2.1: version "4.2.1" resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-4.2.1.tgz#dfa222f03480bca69207ca728b37d74b45f724fa" @@ -9028,14 +9025,6 @@ uglify-js@^2.6: optionalDependencies: uglify-to-browserify "~1.0.0" -uglify-js@^3.4.9: - version "3.4.9" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.4.9.tgz#af02f180c1207d76432e473ed24a28f4a782bae3" - integrity sha512-8CJsbKOtEbnJsTyv6LE6m6ZKniqMiFWmm9sRbopbkGs3gMPPfd3Fh8iIA4Ykv5MgaTbqHr4BaoGLJLZNhsrW1Q== - dependencies: - commander "~2.17.1" - source-map "~0.6.1" - uglify-to-browserify@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7" @@ -9055,20 +9044,6 @@ uglifyjs-webpack-plugin@^1.2.4: webpack-sources "^1.1.0" worker-farm "^1.5.2" -uglifyjs-webpack-plugin@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-2.0.0.tgz#5ca8a9816bb2f826d558fada74b4880e26532ee3" - integrity sha512-553rPZK5sQe9irhMbKv2SAb2wWeoAj+7/IYpuRz+VECEUKZAcIyR2ZwFeaY+umBEtQe4i65iSjhN/aa7KsKIGg== - dependencies: - cacache "^11.2.0" - find-cache-dir "^2.0.0" - schema-utils "^1.0.0" - serialize-javascript "^1.4.0" - source-map "^0.6.1" - uglify-js "^3.4.9" - webpack-sources "^1.1.0" - worker-farm "^1.5.2" - unherit@^1.0.4: version "1.1.1" resolved "https://registry.yarnpkg.com/unherit/-/unherit-1.1.1.tgz#132748da3e88eab767e08fabfbb89c5e9d28628c"