diff --git a/package-lock.json b/package-lock.json index 786ccacb9..012b1e71b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -994,6 +994,474 @@ "to-fast-properties": "^2.0.0" } }, + "@jimp/bmp": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@jimp/bmp/-/bmp-0.8.5.tgz", + "integrity": "sha512-o/23j1RODQGGjvb2xg+9ZQCHc9uXa5XIoJuXHN8kh8AJBGD7JZYiHMwNHaxJRJvadimCKUeA5udZUJAoaPwrYg==", + "requires": { + "@jimp/utils": "^0.8.5", + "bmp-js": "^0.1.0", + "core-js": "^2.5.7" + }, + "dependencies": { + "core-js": { + "version": "2.6.10", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.10.tgz", + "integrity": "sha512-I39t74+4t+zau64EN1fE5v2W31Adtc/REhzWN+gWRRXg6WH5qAsZm62DHpQ1+Yhe4047T55jvzz7MUqF/dBBlA==" + } + } + }, + "@jimp/core": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@jimp/core/-/core-0.8.5.tgz", + "integrity": "sha512-Jto1IdL5HYg7uE15rpQjK6dfZJ6d6gRjUsVCPW50nIfXgWizaTibFEov90W9Bj+irwKrX2ntG3e3pZUyOC0COg==", + "requires": { + "@jimp/utils": "^0.8.5", + "any-base": "^1.1.0", + "buffer": "^5.2.0", + "core-js": "^2.5.7", + "exif-parser": "^0.1.12", + "file-type": "^9.0.0", + "load-bmfont": "^1.3.1", + "mkdirp": "0.5.1", + "phin": "^2.9.1", + "pixelmatch": "^4.0.2", + "tinycolor2": "^1.4.1" + }, + "dependencies": { + "core-js": { + "version": "2.6.10", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.10.tgz", + "integrity": "sha512-I39t74+4t+zau64EN1fE5v2W31Adtc/REhzWN+gWRRXg6WH5qAsZm62DHpQ1+Yhe4047T55jvzz7MUqF/dBBlA==" + } + } + }, + "@jimp/custom": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@jimp/custom/-/custom-0.8.5.tgz", + "integrity": "sha512-hS4qHOcOIL+N93IprsIhFgr8F4XnC2oYd+lRaOKEOg3ptS2vQnceSTtcXsC0//mhq8AV6lNjpbfs1iseEZuTqg==", + "requires": { + "@jimp/core": "^0.8.5", + "core-js": "^2.5.7" + }, + "dependencies": { + "core-js": { + "version": "2.6.10", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.10.tgz", + "integrity": "sha512-I39t74+4t+zau64EN1fE5v2W31Adtc/REhzWN+gWRRXg6WH5qAsZm62DHpQ1+Yhe4047T55jvzz7MUqF/dBBlA==" + } + } + }, + "@jimp/gif": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@jimp/gif/-/gif-0.8.5.tgz", + "integrity": "sha512-Mj8jmv4AS76OY+Hx/Xoyihj02SUZ2ELk+O5x89pODz1+NeGtSWHHjZjnSam9HYAjycvVI/lGJdk/7w0nWIV/yQ==", + "requires": { + "@jimp/utils": "^0.8.5", + "core-js": "^2.5.7", + "omggif": "^1.0.9" + }, + "dependencies": { + "core-js": { + "version": "2.6.10", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.10.tgz", + "integrity": "sha512-I39t74+4t+zau64EN1fE5v2W31Adtc/REhzWN+gWRRXg6WH5qAsZm62DHpQ1+Yhe4047T55jvzz7MUqF/dBBlA==" + } + } + }, + "@jimp/jpeg": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@jimp/jpeg/-/jpeg-0.8.5.tgz", + "integrity": "sha512-7kjTY0BiCpwRywk+oPfpLto7cLI+9G0mf4N1bv1Hn+VLQwcXFy2fHyl4qjqLbbY6u4cyZgqN+R8Pg6GRRzv0kw==", + "requires": { + "@jimp/utils": "^0.8.5", + "core-js": "^2.5.7", + "jpeg-js": "^0.3.4" + }, + "dependencies": { + "core-js": { + "version": "2.6.10", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.10.tgz", + "integrity": "sha512-I39t74+4t+zau64EN1fE5v2W31Adtc/REhzWN+gWRRXg6WH5qAsZm62DHpQ1+Yhe4047T55jvzz7MUqF/dBBlA==" + } + } + }, + "@jimp/plugin-blit": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@jimp/plugin-blit/-/plugin-blit-0.8.5.tgz", + "integrity": "sha512-r8Z1CwazaJwZCRbucQgrfprlGyH91tX7GubUsbWr+zy5/dRJAAgaPj/hcoHDwbh3zyiXp5BECKKzKW0x4reL4w==", + "requires": { + "@jimp/utils": "^0.8.5", + "core-js": "^2.5.7" + }, + "dependencies": { + "core-js": { + "version": "2.6.10", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.10.tgz", + "integrity": "sha512-I39t74+4t+zau64EN1fE5v2W31Adtc/REhzWN+gWRRXg6WH5qAsZm62DHpQ1+Yhe4047T55jvzz7MUqF/dBBlA==" + } + } + }, + "@jimp/plugin-blur": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@jimp/plugin-blur/-/plugin-blur-0.8.5.tgz", + "integrity": "sha512-UH5ywpV4YooUh9HXEsrNKDtojLCvIAAV0gywqn8EQeFyzwBJyXAvRNARJp7zr5OPLr9uGXkRLDCO9YyzdlXZng==", + "requires": { + "@jimp/utils": "^0.8.5", + "core-js": "^2.5.7" + }, + "dependencies": { + "core-js": { + "version": "2.6.10", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.10.tgz", + "integrity": "sha512-I39t74+4t+zau64EN1fE5v2W31Adtc/REhzWN+gWRRXg6WH5qAsZm62DHpQ1+Yhe4047T55jvzz7MUqF/dBBlA==" + } + } + }, + "@jimp/plugin-color": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@jimp/plugin-color/-/plugin-color-0.8.5.tgz", + "integrity": "sha512-7XHqcTQ8Y1zto1b9P1y8m1dzSjnOpBsD9OZG0beTpeJ5bgPX+hF5ZLmvcM6c5ljkINw5EUF1it07BYbkCxiGQA==", + "requires": { + "@jimp/utils": "^0.8.5", + "core-js": "^2.5.7", + "tinycolor2": "^1.4.1" + }, + "dependencies": { + "core-js": { + "version": "2.6.10", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.10.tgz", + "integrity": "sha512-I39t74+4t+zau64EN1fE5v2W31Adtc/REhzWN+gWRRXg6WH5qAsZm62DHpQ1+Yhe4047T55jvzz7MUqF/dBBlA==" + } + } + }, + "@jimp/plugin-contain": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@jimp/plugin-contain/-/plugin-contain-0.8.5.tgz", + "integrity": "sha512-ZkiPFx9L0yITiKtYTYLWyBsSIdxo/NARhNPRZXyVF9HmTWSLDUw1c2c1uvETKxDZTAVK+souYT14DwFWWdhsYA==", + "requires": { + "@jimp/utils": "^0.8.5", + "core-js": "^2.5.7" + }, + "dependencies": { + "core-js": { + "version": "2.6.10", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.10.tgz", + "integrity": "sha512-I39t74+4t+zau64EN1fE5v2W31Adtc/REhzWN+gWRRXg6WH5qAsZm62DHpQ1+Yhe4047T55jvzz7MUqF/dBBlA==" + } + } + }, + "@jimp/plugin-cover": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@jimp/plugin-cover/-/plugin-cover-0.8.5.tgz", + "integrity": "sha512-OdT4YAopLOhbhTUQV3R1v5ZZqIaUt3n3vJi/OfTbsak1t9UkPBVdmYPyhoont8zJdtdkF5dW16Ro1FTshytcww==", + "requires": { + "@jimp/utils": "^0.8.5", + "core-js": "^2.5.7" + }, + "dependencies": { + "core-js": { + "version": "2.6.10", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.10.tgz", + "integrity": "sha512-I39t74+4t+zau64EN1fE5v2W31Adtc/REhzWN+gWRRXg6WH5qAsZm62DHpQ1+Yhe4047T55jvzz7MUqF/dBBlA==" + } + } + }, + "@jimp/plugin-crop": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@jimp/plugin-crop/-/plugin-crop-0.8.5.tgz", + "integrity": "sha512-E1Hb+gfu2k74Gkqh96apAyVljsP5MjCH4TY6lECAAEcYKGH/XRhz6lY2dSEjCYE7KtiqjTZzWwYkgAvkwojj9Q==", + "requires": { + "@jimp/utils": "^0.8.5", + "core-js": "^2.5.7" + }, + "dependencies": { + "core-js": { + "version": "2.6.10", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.10.tgz", + "integrity": "sha512-I39t74+4t+zau64EN1fE5v2W31Adtc/REhzWN+gWRRXg6WH5qAsZm62DHpQ1+Yhe4047T55jvzz7MUqF/dBBlA==" + } + } + }, + "@jimp/plugin-displace": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@jimp/plugin-displace/-/plugin-displace-0.8.5.tgz", + "integrity": "sha512-fVgVYTS1HZzAXkg8Lg06PuirSUG5oXYaYYGL+3ZU4tmZn1pyZ+mZyfejpwtymETEYZnmymHoCT4xto19E/IRvA==", + "requires": { + "@jimp/utils": "^0.8.5", + "core-js": "^2.5.7" + }, + "dependencies": { + "core-js": { + "version": "2.6.10", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.10.tgz", + "integrity": "sha512-I39t74+4t+zau64EN1fE5v2W31Adtc/REhzWN+gWRRXg6WH5qAsZm62DHpQ1+Yhe4047T55jvzz7MUqF/dBBlA==" + } + } + }, + "@jimp/plugin-dither": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@jimp/plugin-dither/-/plugin-dither-0.8.5.tgz", + "integrity": "sha512-KSj2y8E3yK7tldjT/8ejqAWw5HFBjtWW6QkcxfW7FdV4c/nsXZXDkMbhqMZ7FkDuSYoAPeWUFeddrH4yipC5iA==", + "requires": { + "@jimp/utils": "^0.8.5", + "core-js": "^2.5.7" + }, + "dependencies": { + "core-js": { + "version": "2.6.10", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.10.tgz", + "integrity": "sha512-I39t74+4t+zau64EN1fE5v2W31Adtc/REhzWN+gWRRXg6WH5qAsZm62DHpQ1+Yhe4047T55jvzz7MUqF/dBBlA==" + } + } + }, + "@jimp/plugin-flip": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@jimp/plugin-flip/-/plugin-flip-0.8.5.tgz", + "integrity": "sha512-2QbGDkurPNAXZUeHLo/UA3tjh+AbAXWZKSdtoa1ArlASovRz8rqtA45YIRIkKrMH82TA3PZk8bgP2jaLKLrzww==", + "requires": { + "@jimp/utils": "^0.8.5", + "core-js": "^2.5.7" + }, + "dependencies": { + "core-js": { + "version": "2.6.10", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.10.tgz", + "integrity": "sha512-I39t74+4t+zau64EN1fE5v2W31Adtc/REhzWN+gWRRXg6WH5qAsZm62DHpQ1+Yhe4047T55jvzz7MUqF/dBBlA==" + } + } + }, + "@jimp/plugin-gaussian": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@jimp/plugin-gaussian/-/plugin-gaussian-0.8.5.tgz", + "integrity": "sha512-2zReC5GJcVAXtf3UgzFcHSYN277i02K9Yrhc1xJf3mti00s43uD++B5Ho7/mIo+HrntVvWhxqar7PARdq0lVIg==", + "requires": { + "@jimp/utils": "^0.8.5", + "core-js": "^2.5.7" + }, + "dependencies": { + "core-js": { + "version": "2.6.10", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.10.tgz", + "integrity": "sha512-I39t74+4t+zau64EN1fE5v2W31Adtc/REhzWN+gWRRXg6WH5qAsZm62DHpQ1+Yhe4047T55jvzz7MUqF/dBBlA==" + } + } + }, + "@jimp/plugin-invert": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@jimp/plugin-invert/-/plugin-invert-0.8.5.tgz", + "integrity": "sha512-GyMXPGheHdS14xfDceuZ9hrGm6gE9UG3PfTEjQbJmHMWippLC6yf8kombSudJlUf8q72YYSSXsSFKGgkHa67vA==", + "requires": { + "@jimp/utils": "^0.8.5", + "core-js": "^2.5.7" + }, + "dependencies": { + "core-js": { + "version": "2.6.10", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.10.tgz", + "integrity": "sha512-I39t74+4t+zau64EN1fE5v2W31Adtc/REhzWN+gWRRXg6WH5qAsZm62DHpQ1+Yhe4047T55jvzz7MUqF/dBBlA==" + } + } + }, + "@jimp/plugin-mask": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@jimp/plugin-mask/-/plugin-mask-0.8.5.tgz", + "integrity": "sha512-inD/++XO+MkmwXl9JGYQ8X2deyOZuq9i+dmugH/557p16B9Q6tvUQt5X1Yg5w7hhkLZ00BKOAJI9XoyCC1NFvQ==", + "requires": { + "@jimp/utils": "^0.8.5", + "core-js": "^2.5.7" + }, + "dependencies": { + "core-js": { + "version": "2.6.10", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.10.tgz", + "integrity": "sha512-I39t74+4t+zau64EN1fE5v2W31Adtc/REhzWN+gWRRXg6WH5qAsZm62DHpQ1+Yhe4047T55jvzz7MUqF/dBBlA==" + } + } + }, + "@jimp/plugin-normalize": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@jimp/plugin-normalize/-/plugin-normalize-0.8.5.tgz", + "integrity": "sha512-8YRWJWBT4NoSAbPhnjQJXGeaeWVrJAlGDv39A54oNH8Ry47fHcE0EN6zogQNpBuM34M6hRnZl4rOv1FIisaWdg==", + "requires": { + "@jimp/utils": "^0.8.5", + "core-js": "^2.5.7" + }, + "dependencies": { + "core-js": { + "version": "2.6.10", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.10.tgz", + "integrity": "sha512-I39t74+4t+zau64EN1fE5v2W31Adtc/REhzWN+gWRRXg6WH5qAsZm62DHpQ1+Yhe4047T55jvzz7MUqF/dBBlA==" + } + } + }, + "@jimp/plugin-print": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@jimp/plugin-print/-/plugin-print-0.8.5.tgz", + "integrity": "sha512-BviNpCiA/fEieOqsrWr1FkqyFuiG2izdyyg7zUqyeUTHPwqrTLvXO9cfP/ThG4hZpu5wMQ5QClWSqhZu1fAwxA==", + "requires": { + "@jimp/utils": "^0.8.5", + "core-js": "^2.5.7", + "load-bmfont": "^1.4.0" + }, + "dependencies": { + "core-js": { + "version": "2.6.10", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.10.tgz", + "integrity": "sha512-I39t74+4t+zau64EN1fE5v2W31Adtc/REhzWN+gWRRXg6WH5qAsZm62DHpQ1+Yhe4047T55jvzz7MUqF/dBBlA==" + } + } + }, + "@jimp/plugin-resize": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@jimp/plugin-resize/-/plugin-resize-0.8.5.tgz", + "integrity": "sha512-gIdmISuNmZQ1QwprnRC5VXVWQfKIiWineVQGebpMAG/aoFOLDXrVl939Irg7Fb/uOlSFTzpAbt1zpJ8YG/Mi2w==", + "requires": { + "@jimp/utils": "^0.8.5", + "core-js": "^2.5.7" + }, + "dependencies": { + "core-js": { + "version": "2.6.10", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.10.tgz", + "integrity": "sha512-I39t74+4t+zau64EN1fE5v2W31Adtc/REhzWN+gWRRXg6WH5qAsZm62DHpQ1+Yhe4047T55jvzz7MUqF/dBBlA==" + } + } + }, + "@jimp/plugin-rotate": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@jimp/plugin-rotate/-/plugin-rotate-0.8.5.tgz", + "integrity": "sha512-8T9wnL3gb+Z0ogMZmtyI6h3y7TuqW2a5SpFbzFUVF+lTZoAabXjEfX3CAozizCLaT+Duc5H2FJVemAHiyr+Dbw==", + "requires": { + "@jimp/utils": "^0.8.5", + "core-js": "^2.5.7" + }, + "dependencies": { + "core-js": { + "version": "2.6.10", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.10.tgz", + "integrity": "sha512-I39t74+4t+zau64EN1fE5v2W31Adtc/REhzWN+gWRRXg6WH5qAsZm62DHpQ1+Yhe4047T55jvzz7MUqF/dBBlA==" + } + } + }, + "@jimp/plugin-scale": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@jimp/plugin-scale/-/plugin-scale-0.8.5.tgz", + "integrity": "sha512-G+CDH9s7BsxJ4b+mKZ5SsiXwTAynBJ+7/9SwZFnICZJJvLd79Tws6VPXfSaKJZuWnGIX++L8jTGmFORCfLNkdg==", + "requires": { + "@jimp/utils": "^0.8.5", + "core-js": "^2.5.7" + }, + "dependencies": { + "core-js": { + "version": "2.6.10", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.10.tgz", + "integrity": "sha512-I39t74+4t+zau64EN1fE5v2W31Adtc/REhzWN+gWRRXg6WH5qAsZm62DHpQ1+Yhe4047T55jvzz7MUqF/dBBlA==" + } + } + }, + "@jimp/plugins": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@jimp/plugins/-/plugins-0.8.5.tgz", + "integrity": "sha512-52na0wqfQ3uItIA+C9cJ1EXffhSmABgK7ETClDseUh9oGtynHzxZ97smnFf1ydLjXLrF89Gt+YBxWLyiBGgiZQ==", + "requires": { + "@jimp/plugin-blit": "^0.8.5", + "@jimp/plugin-blur": "^0.8.5", + "@jimp/plugin-color": "^0.8.5", + "@jimp/plugin-contain": "^0.8.5", + "@jimp/plugin-cover": "^0.8.5", + "@jimp/plugin-crop": "^0.8.5", + "@jimp/plugin-displace": "^0.8.5", + "@jimp/plugin-dither": "^0.8.5", + "@jimp/plugin-flip": "^0.8.5", + "@jimp/plugin-gaussian": "^0.8.5", + "@jimp/plugin-invert": "^0.8.5", + "@jimp/plugin-mask": "^0.8.5", + "@jimp/plugin-normalize": "^0.8.5", + "@jimp/plugin-print": "^0.8.5", + "@jimp/plugin-resize": "^0.8.5", + "@jimp/plugin-rotate": "^0.8.5", + "@jimp/plugin-scale": "^0.8.5", + "core-js": "^2.5.7", + "timm": "^1.6.1" + }, + "dependencies": { + "core-js": { + "version": "2.6.10", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.10.tgz", + "integrity": "sha512-I39t74+4t+zau64EN1fE5v2W31Adtc/REhzWN+gWRRXg6WH5qAsZm62DHpQ1+Yhe4047T55jvzz7MUqF/dBBlA==" + } + } + }, + "@jimp/png": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@jimp/png/-/png-0.8.5.tgz", + "integrity": "sha512-zT89ucu8I2rsD3FIMIPLgr1OyKn4neD+5umwD3MY8AOB8+6tX5bFtnmTm3FzGJaJuibkK0wFl87eiaxnb+Megw==", + "requires": { + "@jimp/utils": "^0.8.5", + "core-js": "^2.5.7", + "pngjs": "^3.3.3" + }, + "dependencies": { + "core-js": { + "version": "2.6.10", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.10.tgz", + "integrity": "sha512-I39t74+4t+zau64EN1fE5v2W31Adtc/REhzWN+gWRRXg6WH5qAsZm62DHpQ1+Yhe4047T55jvzz7MUqF/dBBlA==" + } + } + }, + "@jimp/tiff": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@jimp/tiff/-/tiff-0.8.5.tgz", + "integrity": "sha512-Z7uzDcbHuwDg+hy2+UJQ2s5O6sqYXmv6H1fmSf/2dxBrlGMzl8yTc2/BxLrGREeoidDDMcKmXYGAOp4uCsdJjw==", + "requires": { + "core-js": "^2.5.7", + "utif": "^2.0.1" + }, + "dependencies": { + "core-js": { + "version": "2.6.10", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.10.tgz", + "integrity": "sha512-I39t74+4t+zau64EN1fE5v2W31Adtc/REhzWN+gWRRXg6WH5qAsZm62DHpQ1+Yhe4047T55jvzz7MUqF/dBBlA==" + } + } + }, + "@jimp/types": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@jimp/types/-/types-0.8.5.tgz", + "integrity": "sha512-XUvpyebZGd1vyFiJyxUT4H9A3mKD7MV2MxjXnay3fNTrcow0UJJspmFw/w+G3TP/1dgrVC4K++gntjR6QWTzvg==", + "requires": { + "@jimp/bmp": "^0.8.5", + "@jimp/gif": "^0.8.5", + "@jimp/jpeg": "^0.8.5", + "@jimp/png": "^0.8.5", + "@jimp/tiff": "^0.8.5", + "core-js": "^2.5.7", + "timm": "^1.6.1" + }, + "dependencies": { + "core-js": { + "version": "2.6.10", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.10.tgz", + "integrity": "sha512-I39t74+4t+zau64EN1fE5v2W31Adtc/REhzWN+gWRRXg6WH5qAsZm62DHpQ1+Yhe4047T55jvzz7MUqF/dBBlA==" + } + } + }, + "@jimp/utils": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@jimp/utils/-/utils-0.8.5.tgz", + "integrity": "sha512-D3+H4BiopDkhUKvKkZTPPJ53voqOkfMuk3r7YZNcLtXGLkchjjukC4056lNo7B0DzjBgowTYsQM3JjKnYNIYeg==", + "requires": { + "core-js": "^2.5.7" + }, + "dependencies": { + "core-js": { + "version": "2.6.10", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.10.tgz", + "integrity": "sha512-I39t74+4t+zau64EN1fE5v2W31Adtc/REhzWN+gWRRXg6WH5qAsZm62DHpQ1+Yhe4047T55jvzz7MUqF/dBBlA==" + } + } + }, "@nodelib/fs.scandir": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.2.tgz", @@ -1104,6 +1572,15 @@ "@types/node": "*" } }, + "@types/jimp": { + "version": "0.2.28", + "resolved": "https://registry.npmjs.org/@types/jimp/-/jimp-0.2.28.tgz", + "integrity": "sha512-nLIVbImtcaEf90y2XQsMzfgWK5EZxfDg6EVWobrkFTFJiLqmx/yU5Jh+LYUN94ztzXX1GwQLFYHaEi8tfMeZzw==", + "dev": true, + "requires": { + "jimp": "*" + } + }, "@types/json-schema": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.3.tgz", @@ -1292,6 +1769,11 @@ "color-convert": "^1.9.0" } }, + "any-base": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/any-base/-/any-base-1.1.0.tgz", + "integrity": "sha512-uMgjozySS8adZZYePpaWs8cxB9/kdzmpX6SgJZ+wbz1K5eYk5QMYDVJaZKhxyIHUdnnJkfR7SVgStgH7LkGUyg==" + }, "any-observable": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/any-observable/-/any-observable-0.3.0.tgz", @@ -1408,6 +1890,16 @@ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" }, + "base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, + "bmp-js": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/bmp-js/-/bmp-js-0.1.0.tgz", + "integrity": "sha1-4Fpj95amwf8l9Hcex62twUjAcjM=" + }, "boolbase": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", @@ -1447,6 +1939,20 @@ "node-releases": "^1.1.25" } }, + "buffer": { + "version": "5.4.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.4.3.tgz", + "integrity": "sha512-zvj65TkFeIt3i6aj5bIvJDzjjQQGs4o/sNoezg1F1kYap9Nu2jcUdpwzRSJTHMMzG0H7bZkn4rNQpImhuxWX2A==", + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "buffer-equal": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-0.0.1.tgz", + "integrity": "sha1-kbx0sR6kBbyRa8aqkI+q+ltKrEs=" + }, "buffer-from": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", @@ -1907,7 +2413,6 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "dev": true, "requires": { "object-keys": "^1.0.12" } @@ -1975,6 +2480,11 @@ "entities": "^1.1.1" } }, + "dom-walk": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.1.tgz", + "integrity": "sha1-ZyIm3HTI95mtNTB9+TaroRrNYBg=" + }, "domelementtype": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", @@ -2054,7 +2564,6 @@ "version": "1.13.0", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz", "integrity": "sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==", - "dev": true, "requires": { "es-to-primitive": "^1.2.0", "function-bind": "^1.1.1", @@ -2068,7 +2577,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", - "dev": true, "requires": { "is-callable": "^1.1.4", "is-date-object": "^1.0.1", @@ -2257,6 +2765,11 @@ "strip-eof": "^1.0.0" } }, + "exif-parser": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/exif-parser/-/exif-parser-0.1.12.tgz", + "integrity": "sha1-WKnS1ywCwfbwKg70qRZicrd2CSI=" + }, "external-editor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", @@ -2376,6 +2889,11 @@ "flat-cache": "^2.0.1" } }, + "file-type": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-9.0.0.tgz", + "integrity": "sha512-Qe/5NJrgIOlwijpq3B7BEpzPFcgzggOTagZmkXQY4LA6bsXKTUstK7Wp12lEJ/mLKTpvIZxmIuRcLYWT6ov9lw==" + }, "file-url": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/file-url/-/file-url-3.0.0.tgz", @@ -2486,6 +3004,14 @@ "integrity": "sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg==", "dev": true }, + "for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "requires": { + "is-callable": "^1.1.3" + } + }, "fs-extra": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", @@ -2505,8 +3031,7 @@ "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, "functional-red-black-tree": { "version": "1.0.1", @@ -2728,6 +3253,15 @@ "is-glob": "^4.0.1" } }, + "global": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/global/-/global-4.3.2.tgz", + "integrity": "sha1-52mJJopsdMOJCLEwWxD8DjlOnQ8=", + "requires": { + "min-document": "^2.19.0", + "process": "~0.5.1" + } + }, "globals": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", @@ -2796,7 +3330,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, "requires": { "function-bind": "^1.1.1" } @@ -2826,8 +3359,7 @@ "has-symbols": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", - "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", - "dev": true + "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=" }, "he": { "version": "1.2.0", @@ -2984,6 +3516,11 @@ "safer-buffer": ">= 2.1.2 < 3" } }, + "ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, "ignore": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", @@ -3080,8 +3617,7 @@ "is-callable": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", - "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", - "dev": true + "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==" }, "is-ci": { "version": "2.0.0", @@ -3095,8 +3631,7 @@ "is-date-object": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", - "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", - "dev": true + "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=" }, "is-directory": { "version": "0.3.1", @@ -3122,6 +3657,11 @@ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" }, + "is-function": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.1.tgz", + "integrity": "sha1-Es+5i2W1fdPRk6MSH19uL0N2ArU=" + }, "is-glob": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", @@ -3197,7 +3737,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", - "dev": true, "requires": { "has": "^1.0.1" } @@ -3222,7 +3761,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", - "dev": true, "requires": { "has-symbols": "^1.0.0" } @@ -3243,6 +3781,30 @@ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", "dev": true }, + "jimp": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/jimp/-/jimp-0.8.5.tgz", + "integrity": "sha512-BW7t/+TCgKpqZw/wHFwqF/A/Tyk43RmzRHyMBdqfOepqunUrajt0RTqowdWyFo4CS2FmD8pFiYfefWjpXFWrCA==", + "requires": { + "@jimp/custom": "^0.8.5", + "@jimp/plugins": "^0.8.5", + "@jimp/types": "^0.8.5", + "core-js": "^2.5.7", + "regenerator-runtime": "^0.13.3" + }, + "dependencies": { + "core-js": { + "version": "2.6.10", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.10.tgz", + "integrity": "sha512-I39t74+4t+zau64EN1fE5v2W31Adtc/REhzWN+gWRRXg6WH5qAsZm62DHpQ1+Yhe4047T55jvzz7MUqF/dBBlA==" + } + } + }, + "jpeg-js": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.3.6.tgz", + "integrity": "sha512-MUj2XlMB8kpe+8DJUGH/3UJm4XpI8XEgZQ+CiHDeyrGoKPdW/8FJv6ku+3UiYm5Fz3CWaL+iXmD8Q4Ap6aC1Jw==" + }, "js-levenshtein": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.6.tgz", @@ -3558,6 +4120,28 @@ } } }, + "load-bmfont": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/load-bmfont/-/load-bmfont-1.4.0.tgz", + "integrity": "sha512-kT63aTAlNhZARowaNYcY29Fn/QYkc52M3l6V1ifRcPewg2lvUZDAj7R6dXjOL9D0sict76op3T5+odumDSF81g==", + "requires": { + "buffer-equal": "0.0.1", + "mime": "^1.3.4", + "parse-bmfont-ascii": "^1.0.3", + "parse-bmfont-binary": "^1.0.5", + "parse-bmfont-xml": "^1.1.4", + "phin": "^2.9.1", + "xhr": "^2.0.1", + "xtend": "^4.0.0" + }, + "dependencies": { + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" + } + } + }, "locate-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", @@ -3745,6 +4329,14 @@ "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", "dev": true }, + "min-document": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz", + "integrity": "sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU=", + "requires": { + "dom-walk": "^0.1.0" + } + }, "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", @@ -4013,8 +4605,7 @@ "object-keys": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" }, "object.assign": { "version": "4.1.0", @@ -4032,12 +4623,16 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz", "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=", - "dev": true, "requires": { "define-properties": "^1.1.2", "es-abstract": "^1.5.1" } }, + "omggif": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/omggif/-/omggif-1.0.10.tgz", + "integrity": "sha512-LMJTtvgc/nugXj0Vcrrs68Mn2D1r0zf630VNtqtpI1FEO7e+O9FP4gqs9AcnBaSEeoHIPm28u6qgPR0oyEpGSw==" + }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -4313,6 +4908,11 @@ } } }, + "pako": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.10.tgz", + "integrity": "sha512-0DTvPVU3ed8+HNXOu5Bs+o//Mbdj9VNQMUOe9oKCwh8l0GNwpTDMKCWbRjgtD291AWnkAgkqA/LOnQS8AmS1tw==" + }, "parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -4322,6 +4922,34 @@ "callsites": "^3.0.0" } }, + "parse-bmfont-ascii": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/parse-bmfont-ascii/-/parse-bmfont-ascii-1.0.6.tgz", + "integrity": "sha1-Eaw8P/WPfCAgqyJ2kHkQjU36AoU=" + }, + "parse-bmfont-binary": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/parse-bmfont-binary/-/parse-bmfont-binary-1.0.6.tgz", + "integrity": "sha1-0Di0dtPp3Z2x4RoLDlOiJ5K2kAY=" + }, + "parse-bmfont-xml": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/parse-bmfont-xml/-/parse-bmfont-xml-1.1.4.tgz", + "integrity": "sha512-bjnliEOmGv3y1aMEfREMBJ9tfL3WR0i0CKPj61DnSLaoxWR3nLrsQrEbCId/8rF4NyRF0cCqisSVXyQYWM+mCQ==", + "requires": { + "xml-parse-from-string": "^1.0.0", + "xml2js": "^0.4.5" + } + }, + "parse-headers": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.2.tgz", + "integrity": "sha512-/LypJhzFmyBIDYP9aDVgeyEb5sQfbfY5mnDq4hVhlQ69js87wXfmEI5V3xI6vvXasqebp0oCytYFLxsBVfCzSg==", + "requires": { + "for-each": "^0.3.3", + "string.prototype.trim": "^1.1.2" + } + }, "parse-json": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", @@ -4381,6 +5009,11 @@ "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=" }, + "phin": { + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/phin/-/phin-2.9.3.tgz", + "integrity": "sha512-CzFr90qM24ju5f88quFC/6qohjC144rehe5n6DH900lgXmUe86+xCKc10ev56gRKC4/BkHUoG4uSiQgBiIXwDA==" + }, "picomatch": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.0.7.tgz", @@ -4414,6 +5047,14 @@ "node-modules-regexp": "^1.0.0" } }, + "pixelmatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/pixelmatch/-/pixelmatch-4.0.2.tgz", + "integrity": "sha1-j0fc7FARtHe2fbA8JDvB8wheiFQ=", + "requires": { + "pngjs": "^3.0.0" + } + }, "pkg-dir": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", @@ -4440,6 +5081,11 @@ "irregular-plurals": "^2.0.0" } }, + "pngjs": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-3.4.0.tgz", + "integrity": "sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==" + }, "prelude-ls": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", @@ -4471,6 +5117,11 @@ "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", "dev": true }, + "process": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/process/-/process-0.5.2.tgz", + "integrity": "sha1-FjjYqONML0QKkduVq5rrZ3/Bhc8=" + }, "process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", @@ -4573,6 +5224,11 @@ "regenerate": "^1.4.0" } }, + "regenerator-runtime": { + "version": "0.13.3", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz", + "integrity": "sha512-naKIZz2GQ8JWh///G7L3X6LaQUAMp2lvb1rvwwsURe/VXwD6VMfr+/1NuNw3ag8v2kY1aQ/go5SNn79O9JU7yw==" + }, "regenerator-transform": { "version": "0.14.1", "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.1.tgz", @@ -4893,6 +5549,11 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + }, "semver": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", @@ -5064,6 +5725,16 @@ } } }, + "string.prototype.trim": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.0.tgz", + "integrity": "sha512-9EIjYD/WdlvLpn987+ctkLf0FfvBefOCuiEr2henD8X+7jfwPnyvTdmW8OJhj5p+M0/96mBdynLWkxUr+rHlpg==", + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.13.0", + "function-bind": "^1.1.1" + } + }, "string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -5192,6 +5863,16 @@ "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=" }, + "timm": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/timm/-/timm-1.6.2.tgz", + "integrity": "sha512-IH3DYDL1wMUwmIlVmMrmesw5lZD6N+ZOAFWEyLrtpoL9Bcrs9u7M/vyOnHzDD2SMs4irLkVjqxZbHrXStS/Nmw==" + }, + "tinycolor2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.4.1.tgz", + "integrity": "sha1-9PrTM0R7wLB9TcjpIJ2POaisd+g=" + }, "tmp": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.1.0.tgz", @@ -5378,11 +6059,28 @@ "prepend-http": "^1.0.1" } }, + "utif": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/utif/-/utif-2.0.1.tgz", + "integrity": "sha512-Z/S1fNKCicQTf375lIP9G8Sa1H/phcysstNrrSdZKj1f9g58J4NMgb5IgiEZN9/nLMPDwF0W7hdOe9Qq2IYoLg==", + "requires": { + "pako": "^1.0.5" + } + }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, + "util.promisify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.0.tgz", + "integrity": "sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==", + "requires": { + "define-properties": "^1.1.2", + "object.getownpropertydescriptors": "^2.0.3" + } + }, "v8-compile-cache": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz", @@ -5730,6 +6428,42 @@ "mkdirp": "^0.5.1" } }, + "xhr": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/xhr/-/xhr-2.5.0.tgz", + "integrity": "sha512-4nlO/14t3BNUZRXIXfXe+3N6w3s1KoxcJUUURctd64BLRe67E4gRwp4PjywtDY72fXpZ1y6Ch0VZQRY/gMPzzQ==", + "requires": { + "global": "~4.3.0", + "is-function": "^1.0.1", + "parse-headers": "^2.0.0", + "xtend": "^4.0.0" + } + }, + "xml-parse-from-string": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/xml-parse-from-string/-/xml-parse-from-string-1.0.1.tgz", + "integrity": "sha1-qQKekp09vN7RafPG4oI42VpdWig=" + }, + "xml2js": { + "version": "0.4.22", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.22.tgz", + "integrity": "sha512-MWTbxAQqclRSTnehWWe5nMKzI3VmJ8ltiJEco8akcC6j3miOhjjfzKum5sId+CWhfxdOs/1xauYr8/ZDBtQiRw==", + "requires": { + "sax": ">=0.6.0", + "util.promisify": "~1.0.0", + "xmlbuilder": "~11.0.0" + } + }, + "xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==" + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + }, "y18n": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", diff --git a/package.json b/package.json index f5750bbea..0addd6bca 100644 --- a/package.json +++ b/package.json @@ -43,6 +43,7 @@ "dependencies": { "cheerio": "^1.0.0-rc.3", "globby": "^10.0.1", + "jimp": "^0.8.5", "pageres": "^5.2.0", "prettier": "^1.18.2", "yargs": "^14.0.0" @@ -55,6 +56,7 @@ "@babel/register": "^7.6.2", "@types/chai": "^4.2.3", "@types/cheerio": "^0.22.13", + "@types/jimp": "^0.2.28", "@types/mocha": "^5.2.7", "@types/prettier": "^1.18.3", "@types/sinon": "^7.5.0", diff --git a/src/generate-examples-index/index.ts b/src/generate-examples-index/index.ts index 1fddedb9b..de1dcf0ee 100644 --- a/src/generate-examples-index/index.ts +++ b/src/generate-examples-index/index.ts @@ -1,4 +1,5 @@ import $ from "cheerio"; +import Jimp from "jimp"; import Pageres from "pageres"; import childProcess from "child_process"; import commonScreenshotScript from "./screenshot-script.js.txt"; @@ -79,6 +80,13 @@ yargs "Generate full page (…), if false generates only a list of examples (
) that can be inserted into different page with custom CSS.", type: "boolean" }) + .option("verify", { + alias: "v", + default: 100, + describe: + "Attempt to verify that the examples were generated correctly. The value is a percentage of checks that have to pass for the run to be considered success.", + type: "number" + }) .option("parallel", { alias: "p", default: 6, @@ -118,6 +126,14 @@ type Example = { selector: string; titles: string[]; }; +interface Checks { + fail: number; + failPaths: string[]; + okay: number; + okayPaths: string[]; + percentage: number; + total: number; +} function isExample(value: any): value is Example { return ( @@ -161,6 +177,9 @@ class ContentBuilder { private readonly _root: Cheerio; private readonly _screenshotTodo: Example[] = []; + private readonly _fail: string[] = []; + private readonly _okay: string[] = []; + private readonly _examples: ExamplesRoot; private readonly _fullPage: boolean; private readonly _indexPath: string; @@ -201,6 +220,7 @@ class ContentBuilder { generateIndex, renderScreenshots }: { generateIndex?: boolean; renderScreenshots?: boolean } = {}): { + checks: Promise; index: Promise; screenshots: Promise; } { @@ -256,7 +276,22 @@ class ContentBuilder { })() : Promise.resolve(); - return { index, screenshots }; + const checks = (async (): Promise => { + await screenshots; + await index; + + const total = this._okay.length + this._fail.length; + return { + fail: this._fail.length, + failPaths: this._fail, + okay: this._okay.length, + okayPaths: this._okay, + percentage: total === 0 ? 100 : (100 * this._okay.length) / total, + total + }; + })(); + + return { checks, index, screenshots }; } private async _processGroup( @@ -541,7 +576,7 @@ class ContentBuilder { await writeFile(tmpPath, formatHTML(screenshotPage.html())); // Render the page and take the screenshot. - await new Pageres({ + const screenshots = await new Pageres({ delay: example.delay, selector: example.selector, css: [ @@ -571,6 +606,20 @@ class ContentBuilder { // Remove the temporary file. await unlink(tmpPath); + + (await Promise.all( + screenshots.map( + (screenshot): Promise => { + return this._isScreenshotValid(screenshot); + } + ) + )).forEach((valid): void => { + if (valid) { + this._okay.push(example.path); + } else { + this._fail.push(example.path); + } + }); } private _pageToScreenshotPath( pagePath: string, @@ -585,6 +634,30 @@ class ContentBuilder { .digest("hex")}.png` ); } + + /** + * Check if the screenshot is valid. At the moment this simply considers + * everything except for solid color images as valid. This works pretty well + * though may yield some false positives. + * + * @param screenshot - The binary data of the screenshot. + * + * @returns True for valid and false for invalid. + */ + private async _isScreenshotValid(screenshot: Buffer): Promise { + const image = await Jimp.read(screenshot); + const firstPixel = image.getPixelColor(0, 0); + + for (let x = 0; x < image.getWidth(); ++x) { + for (let y = 0; y < image.getHeight(); ++y) { + if (firstPixel !== image.getPixelColor(x, y)) { + return true; + } + } + } + + return false; + } } const exampleLinter = { @@ -630,6 +703,8 @@ const exampleLinter = { }; (async (): Promise => { + let code = 0; + if (!yargs.argv.index && !yargs.argv.screenshots && !yargs.argv.lint) { yargs.parse("--help"); return; @@ -770,5 +845,39 @@ const exampleLinter = { await builtData.screenshots; console.info("All screenshot files were written."); } + + // Verify the result. + const checks = await builtData.checks; + process.stdout.write("\n"); + if (checks.fail === 0) { + console.info( + `Verification: ${checks.okay} passed (${Math.round( + checks.percentage + )} %) passed.` + ); + } else { + if (checks.percentage >= (yargs.argv.verify as number)) { + console.info( + `Verification: ${checks.okay} passed (${Math.round( + checks.percentage + )} %), ${checks.fail} failed.\n` + + "This is within the threshold set by --verify." + ); + } else { + console.error( + `Verification: Only ${checks.okay} passed (${Math.round( + checks.percentage + )} %), ${checks.fail} failed.\n` + + "This is not within the threshold set by --verify. Exiting with an error." + ); + code = 3; + } + + checks.failPaths.forEach((path): void => { + console.error(path); + }); + } } + + process.exit(code); })(); diff --git a/test/generate-examples-index/basic.test.ts b/test/generate-examples-index/basic.test.ts index 6b9eb6b73..4263010b4 100644 --- a/test/generate-examples-index/basic.test.ts +++ b/test/generate-examples-index/basic.test.ts @@ -10,18 +10,28 @@ const exec = util.promisify(childProcess.exec); const executable = path.resolve( `${exec("npm root")}/../bin/generate-examples-index.js` ); -const examplesPath = path.resolve(`${__dirname}/examples`); const baseURL = "https://visjs.github.io/vis-test"; const nmExamples = 6; const title = "Test Examples"; -describe("generate-examples-index", function(): void { +function prepareWorkplace(): { + outputDir: string; + outputIndex: string; + outputScreenshots: string; +} { const { name: outputDir } = tmp.dirSync({ mode: 0o700 }); const outputIndex = path.join(outputDir, "index.html"); const outputScreenshots = path.join(outputDir, "thumbnails"); - let $index: CheerioStatic; + return { + outputDir, + outputIndex, + outputScreenshots + }; +} + +describe("generate-examples-index", function(): void { it("is executable built", function(): void { expect( fs.existsSync(executable), @@ -29,76 +39,133 @@ describe("generate-examples-index", function(): void { ).to.be.true; }); - it("generate index", async function(): Promise { - this.timeout(10 * 60 * 1000); - - await exec( - [ - "node", - executable, - "--container-id test-element", - "--index", - "--screenshots", - `--examples-directory "${examplesPath}"`, - `--output "${outputIndex}"`, - `--title "${title}"`, - `--web-url "${baseURL}"` - ].join(" ") - ); - }); + describe("working examples", function(): void { + const { outputIndex, outputScreenshots } = prepareWorkplace(); + let $index: CheerioStatic; - describe("verify index", function(): void { - it("valid HTML", function(): void { - $index = $.load(fs.readFileSync(outputIndex, "utf-8")); - }); + it("generate index", async function(): Promise { + this.timeout(30 * 60 * 1000); - it("title", function(): void { - expect($index("title").text()).to.equal(title); + await exec( + [ + "node", + executable, + "--container-id test-element", + "--index", + "--screenshots", + `--examples-directory "${path.resolve(`${__dirname}/examples`)}"`, + `--output "${outputIndex}"`, + `--title "${title}"`, + `--web-url "${baseURL}"` + ].join(" ") + ); }); - it("links", function(): void { - expect( - $index(".example-link").length, - `There should be ${nmExamples} links to examples.` - ).to.equal(nmExamples); - }); + describe("verify index", function(): void { + it("valid HTML", function(): void { + $index = $.load(fs.readFileSync(outputIndex, "utf-8")); + }); - it("screenshots", function(): void { - expect( - fs.readdirSync(outputScreenshots), - `There should be ${nmExamples} screenshots.` - ).have.lengthOf(nmExamples); - }); + it("title", function(): void { + expect($index("title").text()).to.equal(title); + }); - for (const i of new Array(nmExamples) - .fill(null) - .map((_value, i): number => i)) { - describe(`example ${i + 1}`, function(): void { - function getNthExample(n: number): Cheerio { - return $index(".example-link").eq(n); - } + it("links", function(): void { + expect( + $index(".example-link").length, + `There should be ${nmExamples} links to examples.` + ).to.equal(nmExamples); + }); - it("thumbnail", function(): void { - expect( - getNthExample(i).find(".example-image img").length, - "There should be a screenshot of this example." - ).to.equal(1); - }); + it("screenshots", function(): void { + expect( + fs.readdirSync(outputScreenshots), + `There should be ${nmExamples} screenshots.` + ).have.lengthOf(nmExamples); + }); - it("JSFiddle", function(): void { - expect( - getNthExample(i).find("form button.icon.jsfiddle").length, - "There should be exactly 1 JSFiddle icon." - ).to.equal(1); - }); + for (const i of new Array(nmExamples) + .fill(null) + .map((_value, i): number => i)) { + describe(`example ${i + 1}`, function(): void { + function getNthExample(n: number): Cheerio { + return $index(".example-link").eq(n); + } + + it("thumbnail", function(): void { + expect( + getNthExample(i).find(".example-image img").length, + "There should be a screenshot of this example." + ).to.equal(1); + }); + + it("JSFiddle", function(): void { + expect( + getNthExample(i).find("form button.icon.jsfiddle").length, + "There should be exactly 1 JSFiddle icon." + ).to.equal(1); + }); - it("CodePen", function(): void { - expect( - getNthExample(i).find("form button.icon.codepen").length, - "There should be exactly 1 CodePen icon." - ).to.equal(1); + it("CodePen", function(): void { + expect( + getNthExample(i).find("form button.icon.codepen").length, + "There should be exactly 1 CodePen icon." + ).to.equal(1); + }); }); - }); - } + } + }); + }); + + describe("broken examples", function(): void { + const { outputIndex } = prepareWorkplace(); + + [ + { threshold: undefined, code: 3 }, + { threshold: 100, code: 3 }, + { threshold: 90, code: 3 }, + { threshold: 80, code: 0 }, + { threshold: 0, code: 0 } + ].forEach(({ threshold, code }): void => { + it( + (threshold == null ? "default" : threshold + " %") + + " threshold, 1 broken, 6 okay", + async function(): Promise { + this.timeout(90 * 60 * 1000); + + try { + await exec( + [ + "node", + executable, + "--container-id test-element", + "--index", + "--screenshots", + `--examples-directory "${path.resolve( + `${__dirname}/broken-examples` + )}"`, + `--output "${outputIndex}"`, + `--title "${title}"`, + `--web-url "${baseURL}"`, + `--verify "${threshold}"` + ].join(" ") + ); + + if (code !== 0) { + expect.fail( + "Some of the examples should fail the verification and this should end with nonzero exit code." + ); + } + } catch (error) { + expect( + error, + `Exit code ${code} should be returned when verification fails.` + ) + .to.haveOwnProperty("code") + .that.equals(code); + } + } + ); + }); }); }); diff --git a/test/generate-examples-index/broken-examples/example-1.html b/test/generate-examples-index/broken-examples/example-1.html new file mode 100644 index 000000000..3f56e7e58 --- /dev/null +++ b/test/generate-examples-index/broken-examples/example-1.html @@ -0,0 +1,10 @@ + + + + Test | Number 1 + + + +
+ + diff --git a/test/generate-examples-index/broken-examples/examples b/test/generate-examples-index/broken-examples/examples new file mode 120000 index 000000000..a6573af9c --- /dev/null +++ b/test/generate-examples-index/broken-examples/examples @@ -0,0 +1 @@ +../examples \ No newline at end of file diff --git a/test/generate-examples-index/examples/example-1.html b/test/generate-examples-index/examples/example-1.html index d92be888a..419ef135a 100644 --- a/test/generate-examples-index/examples/example-1.html +++ b/test/generate-examples-index/examples/example-1.html @@ -11,6 +11,6 @@ -
+
Number 1
diff --git a/test/generate-examples-index/examples/example-2.html b/test/generate-examples-index/examples/example-2.html index b42fd9e4b..e7f7f4708 100644 --- a/test/generate-examples-index/examples/example-2.html +++ b/test/generate-examples-index/examples/example-2.html @@ -11,6 +11,6 @@ -
+
Number 2
diff --git a/test/generate-examples-index/examples/example-alert.html b/test/generate-examples-index/examples/example-alert.html index 91b310e66..6b44b2ed1 100644 --- a/test/generate-examples-index/examples/example-alert.html +++ b/test/generate-examples-index/examples/example-alert.html @@ -11,6 +11,6 @@ -
+
Alert
diff --git a/test/generate-examples-index/examples/example-confirm.html b/test/generate-examples-index/examples/example-confirm.html index e4639974b..5e55fb5f1 100644 --- a/test/generate-examples-index/examples/example-confirm.html +++ b/test/generate-examples-index/examples/example-confirm.html @@ -11,6 +11,6 @@ -
+
Confirm
diff --git a/test/generate-examples-index/examples/subdir/example-3.html b/test/generate-examples-index/examples/subdir/example-3.html index f6bbc9cb3..7d4ea8600 100644 --- a/test/generate-examples-index/examples/subdir/example-3.html +++ b/test/generate-examples-index/examples/subdir/example-3.html @@ -11,6 +11,6 @@ -
+
Number 3
diff --git a/test/generate-examples-index/examples/subdir/example-4.html b/test/generate-examples-index/examples/subdir/example-4.html index 0c4a66001..98cb38921 100644 --- a/test/generate-examples-index/examples/subdir/example-4.html +++ b/test/generate-examples-index/examples/subdir/example-4.html @@ -11,6 +11,6 @@ -
+
Number 4