diff --git a/i18n/template-ssr.pot b/i18n/template-ssr.pot index 903d06fa..0523a4c3 100644 --- a/i18n/template-ssr.pot +++ b/i18n/template-ssr.pot @@ -290,10 +290,6 @@ msgstr "" msgid "Server error occured" msgstr "" -#: src/routes/api/auth/logout.js:13 -msgid "You are not even logged in." -msgstr "" - #: src/routes/api/auth/register.js:31 msgid "E-Mail already in use." msgstr "" @@ -310,6 +306,22 @@ msgstr "" msgid "Failed to establish session after register :(" msgstr "" +#: src/routes/api/auth/logout.js:13 +msgid "You are not even logged in." +msgstr "" + +#: src/routes/api/auth/change_mail.js:41 +#: src/routes/api/auth/change_passwd.js:37 +#: src/routes/api/auth/delete_account.js:38 +msgid "You are not authenticated." +msgstr "" + +#: src/routes/api/auth/change_mail.js:50 +#: src/routes/api/auth/change_passwd.js:46 +#: src/routes/api/auth/delete_account.js:48 +msgid "Incorrect password!" +msgstr "" + #: src/routes/api/auth/verify.js:25 #: src/routes/api/auth/verify.js:32 msgid "Mail verification" @@ -325,18 +337,6 @@ msgid "" "request a new one." msgstr "" -#: src/routes/api/auth/change_mail.js:41 -#: src/routes/api/auth/change_passwd.js:37 -#: src/routes/api/auth/delete_account.js:38 -msgid "You are not authenticated." -msgstr "" - -#: src/routes/api/auth/change_mail.js:50 -#: src/routes/api/auth/change_passwd.js:46 -#: src/routes/api/auth/delete_account.js:48 -msgid "Incorrect password!" -msgstr "" - #: src/ssr-components/RedirectionPage.jsx:20 msgid "You will be automatically redirected after 15s" msgstr "" diff --git a/i18n/template.pot b/i18n/template.pot index 9318b239..5d8c8f07 100644 --- a/i18n/template.pot +++ b/i18n/template.pot @@ -106,11 +106,6 @@ msgstr "" msgid "Copy to Clipboard" msgstr "" -#: src/components/CanvasSelectModal.jsx:67 -#: src/components/CanvasSwitchButton.jsx:20 -msgid "Canvas Selection" -msgstr "" - #: src/components/OnlineBox.jsx:22 msgid "User online" msgstr "" @@ -119,6 +114,11 @@ msgstr "" msgid "Pixels placed" msgstr "" +#: src/components/CanvasSelectModal.jsx:67 +#: src/components/CanvasSwitchButton.jsx:20 +msgid "Canvas Selection" +msgstr "" + #: src/components/ChatButton.jsx:61 msgid "Close Chat" msgstr "" @@ -170,6 +170,10 @@ msgstr "" msgid "Server answered with gibberish :(" msgstr "" +#: src/components/HelpButton.jsx:20 +msgid "Help" +msgstr "" + #: src/components/Chat.jsx:143 msgid "Channel settings" msgstr "" @@ -190,12 +194,9 @@ msgstr "" msgid "You must be logged in to chat" msgstr "" -#: src/components/DownloadButton.jsx:37 -msgid "Make Screenshot" -msgstr "" - -#: src/components/HelpButton.jsx:20 -msgid "Help" +#: src/components/SettingsButton.jsx:20 +#: src/components/SettingsModal.jsx:278 +msgid "Settings" msgstr "" #: src/components/LogInButton.jsx:20 @@ -203,9 +204,8 @@ msgstr "" msgid "User Area" msgstr "" -#: src/components/SettingsButton.jsx:20 -#: src/components/SettingsModal.jsx:278 -msgid "Settings" +#: src/components/DownloadButton.jsx:37 +msgid "Make Screenshot" msgstr "" #: src/components/GlobeButton.jsx:31 @@ -236,93 +236,6 @@ msgstr "" msgid "Mute" msgstr "" -#: src/components/SettingsModal.jsx:125 -msgid "Show Grid" -msgstr "" - -#: src/components/SettingsModal.jsx:126 -msgid "Turn on grid to highlight pixel borders." -msgstr "" - -#: src/components/SettingsModal.jsx:132 -msgid "Show Pixel Activity" -msgstr "" - -#: src/components/SettingsModal.jsx:133 -msgid "Show circles where pixels are placed." -msgstr "" - -#: src/components/SettingsModal.jsx:139 -msgid "Disable Game Sounds" -msgstr "" - -#: src/components/SettingsModal.jsx:141 -msgid "All sound effects will be disabled." -msgstr "" - -#: src/components/SettingsModal.jsx:147 -msgid "Enable chat notifications" -msgstr "" - -#: src/components/SettingsModal.jsx:148 -msgid "Play a sound when new chat messages arrive" -msgstr "" - -#: src/components/SettingsModal.jsx:153 -msgid "Auto Zoom In" -msgstr "" - -#: src/components/SettingsModal.jsx:155 -msgid "" -"Zoom in instead of placing a pixel when you tap the canvas and your zoom is " -"small." -msgstr "" - -#: src/components/SettingsModal.jsx:160 -msgid "Compact Palette" -msgstr "" - -#: src/components/SettingsModal.jsx:162 -msgid "Display Palette in a compact form that takes less screen space." -msgstr "" - -#: src/components/SettingsModal.jsx:167 -msgid "Potato Mode" -msgstr "" - -#: src/components/SettingsModal.jsx:168 -msgid "For when you are playing on a potato." -msgstr "" - -#: src/components/Converter.jsx:423 -#: src/components/SettingsModal.jsx:173 -msgid "Light Grid" -msgstr "" - -#: src/components/SettingsModal.jsx:174 -msgid "Show Grid in white instead of black." -msgstr "" - -#: src/components/SettingsModal.jsx:180 -msgid "Historical View" -msgstr "" - -#: src/components/SettingsModal.jsx:181 -msgid "Check out past versions of the canvas." -msgstr "" - -#: src/components/SettingsModal.jsx:189 -msgid "Themes" -msgstr "" - -#: src/components/SettingsModal.jsx:190 -msgid "How pixelplanet should look like." -msgstr "" - -#: src/components/SettingsModal.jsx:200 -msgid "Select Language" -msgstr "" - #: src/components/HelpModal.jsx:35 msgid "your IP" msgstr "" @@ -493,6 +406,93 @@ msgstr "" msgid "Welcome to PixelPlanet.fun" msgstr "" +#: src/components/SettingsModal.jsx:125 +msgid "Show Grid" +msgstr "" + +#: src/components/SettingsModal.jsx:126 +msgid "Turn on grid to highlight pixel borders." +msgstr "" + +#: src/components/SettingsModal.jsx:132 +msgid "Show Pixel Activity" +msgstr "" + +#: src/components/SettingsModal.jsx:133 +msgid "Show circles where pixels are placed." +msgstr "" + +#: src/components/SettingsModal.jsx:139 +msgid "Disable Game Sounds" +msgstr "" + +#: src/components/SettingsModal.jsx:141 +msgid "All sound effects will be disabled." +msgstr "" + +#: src/components/SettingsModal.jsx:147 +msgid "Enable chat notifications" +msgstr "" + +#: src/components/SettingsModal.jsx:148 +msgid "Play a sound when new chat messages arrive" +msgstr "" + +#: src/components/SettingsModal.jsx:153 +msgid "Auto Zoom In" +msgstr "" + +#: src/components/SettingsModal.jsx:155 +msgid "" +"Zoom in instead of placing a pixel when you tap the canvas and your zoom is " +"small." +msgstr "" + +#: src/components/SettingsModal.jsx:160 +msgid "Compact Palette" +msgstr "" + +#: src/components/SettingsModal.jsx:162 +msgid "Display Palette in a compact form that takes less screen space." +msgstr "" + +#: src/components/SettingsModal.jsx:167 +msgid "Potato Mode" +msgstr "" + +#: src/components/SettingsModal.jsx:168 +msgid "For when you are playing on a potato." +msgstr "" + +#: src/components/Converter.jsx:423 +#: src/components/SettingsModal.jsx:173 +msgid "Light Grid" +msgstr "" + +#: src/components/SettingsModal.jsx:174 +msgid "Show Grid in white instead of black." +msgstr "" + +#: src/components/SettingsModal.jsx:180 +msgid "Historical View" +msgstr "" + +#: src/components/SettingsModal.jsx:181 +msgid "Check out past versions of the canvas." +msgstr "" + +#: src/components/SettingsModal.jsx:189 +msgid "Themes" +msgstr "" + +#: src/components/SettingsModal.jsx:190 +msgid "How pixelplanet should look like." +msgstr "" + +#: src/components/SettingsModal.jsx:200 +msgid "Select Language" +msgstr "" + #: src/components/UserAreaModal.jsx:33 msgid "Login to access more features and stats." msgstr "" @@ -547,6 +547,14 @@ msgstr "" msgid "Consider joining us on Guilded:" msgstr "" +#: src/components/RegisterModal.jsx:18 +msgid "Register new account here" +msgstr "" + +#: src/components/RegisterModal.jsx:38 +msgid "Register New Account" +msgstr "" + #: src/components/CanvasSelectModal.jsx:29 msgid "" "Select the canvas you want to use. Every canvas is unique and has different " @@ -558,14 +566,6 @@ msgstr "" msgid "Archive" msgstr "" -#: src/components/RegisterModal.jsx:18 -msgid "Register new account here" -msgstr "" - -#: src/components/RegisterModal.jsx:38 -msgid "Register New Account" -msgstr "" - #: src/components/ArchiveModal.jsx:20 msgid "" "While we tend to not delete canvases, some canvases are started for fun or " @@ -615,7 +615,7 @@ msgstr "" msgid "Restore my Password" msgstr "" -#: src/components/Captcha.jsx:29 +#: src/components/Captcha.jsx:41 #: src/components/ChangeMail.jsx:88 #: src/components/ChangeName.jsx:67 #: src/components/ChangePassword.jsx:73 @@ -626,31 +626,31 @@ msgstr "" msgid "Error" msgstr "" -#: src/components/Captcha.jsx:33 +#: src/components/Captcha.jsx:45 msgid "Type the characters from the following image:" msgstr "" -#: src/components/Captcha.jsx:36 +#: src/components/Captcha.jsx:48 msgid "Tip: Not case-sensitive; I and l are the same" msgstr "" -#: src/components/Captcha.jsx:60 +#: src/components/Captcha.jsx:72 msgid "Could not load captcha" msgstr "" -#: src/components/Captcha.jsx:64 +#: src/components/Captcha.jsx:76 msgid "Can't read? Reload:" msgstr "" -#: src/components/Captcha.jsx:68 +#: src/components/Captcha.jsx:80 msgid "Reload" msgstr "" -#: src/components/Captcha.jsx:80 +#: src/components/Captcha.jsx:92 msgid "Enter Characters" msgstr "" -#: src/components/Captcha.jsx:102 +#: src/components/Captcha.jsx:117 #: src/components/ChangeMail.jsx:109 #: src/components/ChangeName.jsx:79 #: src/components/ChangePassword.jsx:109 @@ -660,7 +660,7 @@ msgstr "" msgid "Cancel" msgstr "" -#: src/components/Captcha.jsx:119 +#: src/components/Captcha.jsx:124 msgid "Send" msgstr "" @@ -743,33 +743,27 @@ msgstr "" msgid "Ranking updates every 5 min. Daily rankings get reset at midnight UTC." msgstr "" -#: src/components/CanvasItem.jsx:46 -msgid "Cooldown" +#: src/components/SignUpForm.jsx:109 +msgid "Name" msgstr "" -#: src/components/CanvasItem.jsx:52 -msgid "Stacking till" +#: src/components/NewPasswordForm.jsx:86 +#: src/components/SignUpForm.jsx:117 +msgid "Email" msgstr "" -#: src/components/CanvasItem.jsx:54 -msgid "Ranked" +#: src/components/SignUpForm.jsx:135 +msgid "Confirm Password" msgstr "" -#: src/components/CanvasItem.jsx:56 -msgid "Requirements" -msgstr "" - -#: src/components/CanvasItem.jsx:58 -msgid "User Account" -msgstr "" - -#: src/components/CanvasItem.jsx:60 -#, javascript-format -msgid "and ${ canvas.req } Pixels set" -msgstr "" - -#: src/components/CanvasItem.jsx:64 -msgid "Dimensions" +#: src/components/Admintools.jsx:306 +#: src/components/Admintools.jsx:387 +#: src/components/Admintools.jsx:461 +#: src/components/Admintools.jsx:505 +#: src/components/Admintools.jsx:589 +#: src/components/NewPasswordForm.jsx:90 +#: src/components/SignUpForm.jsx:138 +msgid "Submit" msgstr "" #: src/components/Admintools.jsx:179 @@ -800,16 +794,6 @@ msgstr "" msgid "Coordinates in X_Y format:" msgstr "" -#: src/components/Admintools.jsx:306 -#: src/components/Admintools.jsx:387 -#: src/components/Admintools.jsx:461 -#: src/components/Admintools.jsx:505 -#: src/components/Admintools.jsx:589 -#: src/components/NewPasswordForm.jsx:90 -#: src/components/SignUpForm.jsx:138 -msgid "Submit" -msgstr "" - #: src/components/Admintools.jsx:311 msgid "Pixel Protection" msgstr "" @@ -860,23 +844,39 @@ msgstr "" msgid "User Name" msgstr "" +#: src/components/CanvasItem.jsx:46 +msgid "Cooldown" +msgstr "" + +#: src/components/CanvasItem.jsx:52 +msgid "Stacking till" +msgstr "" + +#: src/components/CanvasItem.jsx:54 +msgid "Ranked" +msgstr "" + +#: src/components/CanvasItem.jsx:56 +msgid "Requirements" +msgstr "" + +#: src/components/CanvasItem.jsx:58 +msgid "User Account" +msgstr "" + +#: src/components/CanvasItem.jsx:60 +#, javascript-format +msgid "and ${ canvas.req } Pixels set" +msgstr "" + +#: src/components/CanvasItem.jsx:64 +msgid "Dimensions" +msgstr "" + #: src/components/NewPasswordForm.jsx:69 msgid "Sent you a mail with instructions to reset your password." msgstr "" -#: src/components/NewPasswordForm.jsx:86 -#: src/components/SignUpForm.jsx:117 -msgid "Email" -msgstr "" - -#: src/components/SignUpForm.jsx:109 -msgid "Name" -msgstr "" - -#: src/components/SignUpForm.jsx:135 -msgid "Confirm Password" -msgstr "" - #: src/components/Converter.jsx:274 msgid "Choose Canvas" msgstr "" @@ -996,26 +996,6 @@ msgstr "" msgid "Password must be shorter than 60 characters." msgstr "" -#: src/components/ChangePassword.jsx:19 -msgid "Passwords do not match." -msgstr "" - -#: src/components/ChangePassword.jsx:39 -msgid "Changed Password successfully." -msgstr "" - -#: src/components/ChangePassword.jsx:82 -msgid "Old Password" -msgstr "" - -#: src/components/ChangePassword.jsx:90 -msgid "New Password" -msgstr "" - -#: src/components/ChangePassword.jsx:97 -msgid "Confirm New Password" -msgstr "" - #: src/components/UserMessages.jsx:38 msgid "A new verification mail is getting sent to you." msgstr "" @@ -1055,8 +1035,24 @@ msgstr "" msgid "New Username" msgstr "" -#: src/components/DeleteAccount.jsx:78 -msgid "Yes, Delete My Account!" +#: src/components/ChangePassword.jsx:19 +msgid "Passwords do not match." +msgstr "" + +#: src/components/ChangePassword.jsx:39 +msgid "Changed Password successfully." +msgstr "" + +#: src/components/ChangePassword.jsx:82 +msgid "Old Password" +msgstr "" + +#: src/components/ChangePassword.jsx:90 +msgid "New Password" +msgstr "" + +#: src/components/ChangePassword.jsx:97 +msgid "Confirm New Password" msgstr "" #: src/components/ChangeMail.jsx:73 @@ -1069,6 +1065,10 @@ msgstr "" msgid "New Mail" msgstr "" +#: src/components/DeleteAccount.jsx:78 +msgid "Yes, Delete My Account!" +msgstr "" + #: src/components/SocialSettings.jsx:39 msgid "Block all Private Messages" msgstr "" @@ -1093,11 +1093,6 @@ msgctxt "keybinds" msgid "X" msgstr "" -#: src/components/SettingsModal.jsx:142 -msgctxt "keybinds" -msgid "M" -msgstr "" - #: src/components/HelpModal.jsx:17 #: src/components/SettingsModal.jsx:183 msgctxt "keybinds" @@ -1147,4 +1142,9 @@ msgstr "" #: src/components/HelpModal.jsx:32 msgctxt "keybinds" msgid "C" +msgstr "" + +#: src/components/SettingsModal.jsx:142 +msgctxt "keybinds" +msgid "M" msgstr "" \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index c959a105..0f1ae20f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4072,6 +4072,32 @@ } } }, + "@nodelib/fs.scandir": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz", + "integrity": "sha512-33g3pMJk3bg5nXbL/+CY6I2eJDzZAni49PfJnL5fghPTggPvBd/pFNSgJsdAgWptuFu7qq/ERvOYFlhvsLTCKA==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "2.0.4", + "run-parallel": "^1.1.9" + } + }, + "@nodelib/fs.stat": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.4.tgz", + "integrity": "sha512-IYlHJA0clt2+Vg7bccq+TzRdJvv19c2INqBSsoOLp1je7xjtr7J26+WXR72MCdvU9q1qTzIWDfhMf+DRvQJK4Q==", + "dev": true + }, + "@nodelib/fs.walk": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.6.tgz", + "integrity": "sha512-8Broas6vTtW4GIXTAHDoE32hnN2M5ykgCpWGbuXHQ15vEMqr23pB76e/GZcYsZCHALv50ktd24qhEyKr6wBtow==", + "dev": true, + "requires": { + "@nodelib/fs.scandir": "2.1.4", + "fastq": "^1.6.0" + } + }, "@polka/url": { "version": "1.0.0-next.11", "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.11.tgz", @@ -5139,6 +5165,15 @@ "concat-map": "0.0.1" } }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, "browserslist": { "version": "4.16.3", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.3.tgz", @@ -5705,6 +5740,69 @@ } } }, + "copy-webpack-plugin": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-8.0.0.tgz", + "integrity": "sha512-sqGe2FsB67wV/De+sz5azQklADe4thN016od6m7iK9KbjrSc1SEgg5QZ0LN+jGx5aZR52CbuXbqOhoIbqzzXlA==", + "dev": true, + "requires": { + "fast-glob": "^3.2.5", + "glob-parent": "^5.1.1", + "globby": "^11.0.2", + "normalize-path": "^3.0.0", + "p-limit": "^3.1.0", + "schema-utils": "^3.0.0", + "serialize-javascript": "^5.0.1" + }, + "dependencies": { + "array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true + }, + "globby": { + "version": "11.0.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.2.tgz", + "integrity": "sha512-2ZThXDvvV8fYFRVIxnrMQBipZQDr7MxKAmQK1vujaj9/7eF0efG7BPUKJ7jP7G5SLF37xKDXvO4S/KKLj/Z0og==", + "dev": true, + "requires": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.1.1", + "ignore": "^5.1.4", + "merge2": "^1.3.0", + "slash": "^3.0.0" + } + }, + "ignore": { + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", + "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", + "dev": true + }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "requires": { + "yocto-queue": "^0.1.0" + } + }, + "schema-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz", + "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.6", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + } + } + }, "core-js": { "version": "3.9.1", "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.9.1.tgz", @@ -6176,6 +6274,23 @@ } } }, + "dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "requires": { + "path-type": "^4.0.0" + }, + "dependencies": { + "path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true + } + } + }, "doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -7201,6 +7316,20 @@ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, + "fast-glob": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.5.tgz", + "integrity": "sha512-2DtFcgT68wiTTiwZ2hNdJfcHNke9XOfnwmBRWXhmeKM8rF0TGwmC/Qto3S7RoZKp5cilZbxzO5iTNTQsJ+EeDg==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.0", + "merge2": "^1.3.0", + "micromatch": "^4.0.2", + "picomatch": "^2.2.1" + } + }, "fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", @@ -7223,6 +7352,15 @@ "integrity": "sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow==", "dev": true }, + "fastq": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.11.0.tgz", + "integrity": "sha512-7Eczs8gIPDrVzT+EksYBcupqMyxSHXXrHOLRRxU2/DicV8789MRBRR8+Hc2uWzUupOs4YS4JzBmBxjjCVBxD/g==", + "dev": true, + "requires": { + "reusify": "^1.0.4" + } + }, "fecha": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.0.tgz", @@ -7251,6 +7389,15 @@ "integrity": "sha512-7KjR1vv6qnicaPMi1iiTcI85CyYwRO/PSFCu6SvqL8jN2Wjt/NIYQTFtFs7fSDCYOstUkEWIQGFUg5YZQfjlcg==", "dev": true }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, "finalhandler": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", @@ -8098,6 +8245,12 @@ "integrity": "sha1-8vtjpl5JBbQGyGBydloaTceTufQ=", "dev": true }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, "is-obj": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", @@ -8854,11 +9007,27 @@ "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", "dev": true }, + "merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true + }, "methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" }, + "micromatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", + "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", + "dev": true, + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.0.5" + } + }, "mime": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", @@ -9191,6 +9360,12 @@ "validate-npm-package-license": "^3.0.1" } }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, "npm-check": { "version": "5.9.2", "resolved": "https://registry.npmjs.org/npm-check/-/npm-check-5.9.2.tgz", @@ -9942,6 +10117,12 @@ "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" }, + "picomatch": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", + "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", + "dev": true + }, "pify": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", @@ -10244,6 +10425,12 @@ "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", "dev": true }, + "queue-microtask": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.2.tgz", + "integrity": "sha512-dB15eXv3p2jDlbOiNLyMabYg1/sXvppd8DP2J3EOCQ0AkuSXCW2tP7mnVouVLJKgUMY6yP0kcQDVpLCN13h4Xg==", + "dev": true + }, "raf": { "version": "3.4.1", "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz", @@ -10797,6 +10984,12 @@ "any-promise": "^1.3.0" } }, + "reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true + }, "rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", @@ -10805,6 +10998,15 @@ "glob": "^7.1.3" } }, + "run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "requires": { + "queue-microtask": "^1.2.2" + } + }, "rx-lite": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-3.1.2.tgz", @@ -11151,6 +11353,12 @@ } } }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + }, "slice-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", @@ -11954,6 +12162,15 @@ "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=" }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, "toidentifier": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", diff --git a/package.json b/package.json index 7aecb19e..d36e4db6 100644 --- a/package.json +++ b/package.json @@ -9,10 +9,10 @@ "description": "Unlimited planet canvas for placing pixels", "main": "server.js", "scripts": { - "build": "babel-node scripts/run prebuild && npm run webpack", - "build-en": "babel-node scripts/run prebuild && npm run extract", - "clean": "babel-node scripts/run clean", + "build": "npm run webpack && npm run minify-css", + "build-en": "npm run extract && npm run minify-css", "webpack": "webpack --config ./webpack.config.web.babel.js && parallel-webpack --config ./webpack.config.client.babel.js", + "minify-css": "babel-node scripts/minifyCss.js", "extract": "webpack --env extract --config ./webpack.config.web.babel.js && webpack --env extract --config ./webpack.config.client.babel.js", "babel-node": "cd $INIT_CWD && babel-node", "lint": "cd $INIT_CWD && eslint --ext .jsx --ext .js", @@ -120,6 +120,7 @@ "babel-plugin-transform-react-remove-prop-types": "^0.4.24", "babel-plugin-ttag": "^1.7.30", "clean-css": "^5.1.1", + "copy-webpack-plugin": "^8.0.0", "css-loader": "^5.1.3", "eslint": "^7.22.0", "eslint-config-airbnb": "^18.2.1", diff --git a/scripts/clean.js b/scripts/clean.js deleted file mode 100644 index 29062d87..00000000 --- a/scripts/clean.js +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Cleans up the output (build) directory. - */ - -import rimraf from 'rimraf'; -import path from 'path'; - -const builddir = path.resolve(__dirname, '..', 'build'); - - -function clean() { - return new Promise( - (resolve, reject) => rimraf(`${builddir}/*`, { - glob: { - nosort: true, - dot: true, - ignore: ['build/.git'], - }, - }, (err, result) => (err) ? reject(err) : resolve(result)), - ); -} - -export default clean; diff --git a/scripts/copy.js b/scripts/copy.js deleted file mode 100644 index 9617a754..00000000 --- a/scripts/copy.js +++ /dev/null @@ -1,102 +0,0 @@ -/** - * copies files to build directory - */ - -/* eslint-disable import/no-extraneous-dependencies */ - -import fs from 'fs'; -import path from 'path'; -import glob from 'glob'; -import mkdirp from 'mkdirp'; - -const builddir = path.resolve(__dirname, '..', 'build'); -const deploydir = path.resolve(__dirname, '..', 'deployment'); -const publicdir = path.resolve(__dirname, '..', 'public'); -const srcdir = path.resolve(__dirname, '..', 'src'); - -/* - * following functions are copied from - * React Starter Kit (https://www.reactstarterkit.com/) - * Copyright © 2014-present Kriasoft, LLC. All rights reserved. - * - * This source code is licensed under the MIT license found in the - * LICENSE.txt file in the root directory of this source tree. - */ - -// eslint-disable-next-line max-len -const readDir = (pattern, options) => new Promise((resolve, reject) => glob(pattern, options, (err, result) => (err ? reject(err) : resolve(result)))); - -const copyFile = (source, target) => new Promise((resolve, reject) => { - let cbCalled = false; - function done(err) { - if (!cbCalled) { - cbCalled = true; - if (err) { - reject(err); - } else { - resolve(); - } - } - } - const rd = fs.createReadStream(source); - rd.on('error', (err) => done(err)); - const wr = fs.createWriteStream(target); - wr.on('error', (err) => done(err)); - wr.on('close', (err) => done(err)); - rd.pipe(wr); -}); - -const copyDir = async (source, target) => { - const dirs = await readDir('**/*.*', { - cwd: source, - nosort: true, - dot: true, - }); - await Promise.all(dirs.map(async (dir) => { - const from = path.resolve(source, dir); - const to = path.resolve(target, dir); - mkdirp.sync(path.dirname(to)); - await copyFile(from, to); - })); -}; -/* - * ---------------------------------------------------------------------------- - */ - - - -/** - * Copies static files such as robots.txt, favicon.ico to the - * output (build) folder. - */ -async function copy() { - mkdirp.sync(`${builddir}/public/assets`); - return Promise.all([ - copyDir( - `${publicdir}`, - `${builddir}/public`, - ), - copyFile( - `${srcdir}/canvases.json`, - `${builddir}/canvases.json`, - ), - copyFile( - `${srcdir}/proxies.json`, - `${builddir}/proxies.json`, - ), - copyFile( - `${deploydir}/example-ecosystem.yml`, - `${builddir}/ecosystem.example.yml`, - ), - copyFile( - `${deploydir}/example-ecosystem-backup.yml`, - `${builddir}/ecosystem-backup.example.yml`, - ), - copyFile( - `${deploydir}/example-ecosystem-captchas.yml`, - `${builddir}/ecosystem-captchas.example.yml`, - ), - ]); -} - -export default copy; diff --git a/scripts/minifyCss.js b/scripts/minifyCss.js index 371470b2..5e5ddf9b 100644 --- a/scripts/minifyCss.js +++ b/scripts/minifyCss.js @@ -14,6 +14,7 @@ import fs from 'fs'; import path from 'path'; import CleanCSS from 'clean-css'; import crypto from 'crypto'; +import mkdirp from 'mkdirp'; const assetdir = path.resolve(__dirname, '..', 'build', 'public', 'assets'); const builddir = path.resolve(__dirname, '..', 'build'); @@ -55,4 +56,19 @@ async function minifyCss() { fs.writeFileSync(path.resolve(builddir, 'styleassets.json'), json); } +async function doMinifyCss() { + try { + mkdirp.sync(path.resolve(__dirname, '..', 'build', 'public', 'assets')); + await minifyCss(); + } catch (e) { + console.log('ERROR while minifying css', e); + process.exit(1); + } + process.exit(0); +} + +if (require.main === module) { + doMinifyCss(); +} + export default minifyCss; diff --git a/scripts/prebuild.js b/scripts/prebuild.js deleted file mode 100644 index a7825be1..00000000 --- a/scripts/prebuild.js +++ /dev/null @@ -1,26 +0,0 @@ -/** - * React Starter Kit (https://www.reactstarterkit.com/) - * - * Copyright © 2014-present Kriasoft, LLC. All rights reserved. - * - * This source code is licensed under the MIT license found in the - * LICENSE.txt file in the root directory of this source tree. - */ - - -import run from './run'; -import clean from './clean'; -import copy from './copy'; -import minifyCss from './minifyCss'; - -/** - * Compiles the project from source files into a distributable - * format and copies it to the output (build) folder. - */ -async function prebuild() { - await run(clean); - await run(copy); - await run(minifyCss); -} - -export default prebuild; diff --git a/scripts/run.js b/scripts/run.js deleted file mode 100644 index 678f41f6..00000000 --- a/scripts/run.js +++ /dev/null @@ -1,43 +0,0 @@ -/** - * React Starter Kit (https://www.reactstarterkit.com/) - * - * Copyright © 2014-present Kriasoft, LLC. All rights reserved. - * - * This source code is licensed under the MIT license found in the - * LICENSE.txt file in the root directory of this source tree. - */ - -export function format(time) { - return time.toTimeString().replace(/.*(\d{2}:\d{2}:\d{2}).*/, '$1'); -} - -function run(fn, options) { - const task = typeof fn.default === 'undefined' ? fn : fn.default; - const start = new Date(); - console.info( - `[${format(start)}] Starting '${task.name}${options ? ` (${options})` : ''}'...`, - ); - return task(options).then((resolution) => { - const end = new Date(); - const time = end.getTime() - start.getTime(); - console.info( - `[${format(end)}] Finished '${task.name}${options ? ` (${options})` : ''}' after ${time} ms`, - ); - return resolution; - }); -} - -if (require.main === module && process.argv.length > 2) { - // eslint-disable-next-line no-underscore-dangle - delete require.cache[__filename]; - - // eslint-disable-next-line global-require, import/no-dynamic-require - const module = require(`./${process.argv[2]}.js`).default; - - run(module).catch((err) => { - console.error(err.stack); - process.exit(1); - }); -} - -export default run; diff --git a/webpack.config.client.babel.js.old b/webpack.config.client.babel.js.old deleted file mode 100644 index 767d28fe..00000000 --- a/webpack.config.client.babel.js.old +++ /dev/null @@ -1,243 +0,0 @@ -/** - * This is an old webpack config that uses ttag-webpack-plugin - * Sadly this plugin has issues with webpack 5, so we can't use it. - * But we keep this config around, so that we can adjust in the case it - * might become stable. - * - * https://github.com/ttag-org/ttag-webpack-plugin/issues - */ - -import fs from 'fs'; -import path from 'path'; -import webpack from 'webpack'; -import AssetsPlugin from 'assets-webpack-plugin'; -import TtagWebpackPlugin from 'ttag-webpack-plugin'; -import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer'; - -import pkg from './package.json'; - -const isDebug = process.argv.includes('--debug'); -const VERBOSE = false; -const isAnalyze = process.argv.includes('--analyze') - || process.argv.includes('--analyse'); - -// activate for deprecation tracking -// process.traceDeprecation = true; - -const babelPlugins = [ - '@babel/transform-flow-strip-types', - ['@babel/plugin-proposal-decorators', { legacy: true }], - '@babel/plugin-proposal-function-sent', - '@babel/plugin-proposal-export-namespace-from', - '@babel/plugin-proposal-numeric-separator', - '@babel/plugin-proposal-throw-expressions', - ['@babel/plugin-proposal-class-properties', { loose: true }], - '@babel/proposal-object-rest-spread', - // react-optimize - '@babel/transform-react-constant-elements', - '@babel/transform-react-inline-elements', - 'transform-react-remove-prop-types', - 'transform-react-pure-class-to-function', -]; - -/* - * get all available languages - */ -const langDir = path.resolve(__dirname, 'i18n'); -const langs = fs.readdirSync(langDir) - .filter((e) => e.endsWith('.po')) - .map((l) => l.slice(0, -3)); - -/* - * create list of translations for ttag-webpack-plugin - */ -const translations = {}; -for (let i = 0; i < langs.length; i += 1) { - const lang = langs[i]; - translations[lang] = path.resolve(langDir, `${lang}.po`); -} - -/* - * Cache Groups for splitChunks - * (edit cache groups here, make sure that chunks is based on name) - */ -const cacheGroups = { - default: false, - defaultVendors: false, - - vendor: { - name: 'vendor', - chunks: (chunk) => chunk.name === 'client', - test: /[\\/]node_modules[\\/]/, - }, - three: { - name: 'three', - chunks: (chunk) => (chunk.name === 'globe' || chunk.name === 'voxel'), - test: /[\\/]node_modules[\\/]three[\\/]/, - }, -}; - - -/* - * automatically add Cache Groups for languages based on - * manually set cacheGroups - */ -const groups = Object.keys(cacheGroups); -for (let u = 0; u < groups.length; u += 1) { - const group = cacheGroups[groups[u]]; - if (!group.test) continue; - - for (let i = 0; i < langs.length; i += 1) { - const lang = langs[i]; - /* add lang */ - const key = `${groups[u]}-${lang}`; - const name = `${group.name}-${lang}`; - const { test, chunks } = group; - - cacheGroups[key] = { - name, - chunks: (chunk) => { - if (!chunk.name.endsWith(`-${lang}`)) { - return false; - } - return chunks({ - name: chunk.name.slice(0, -lang.length - 1), - }); - }, - test, - }; - } -} - - -export default { - name: 'client', - target: 'web', - - context: __dirname, - mode: (isDebug) ? 'development' : 'production', - devtool: 'source-map', - - entry: { - client: ['./src/client.js'], - globe: ['./src/globe.js'], - }, - - output: { - path: path.resolve(__dirname, 'build', 'public', 'assets'), - publicPath: '/assets/', - pathinfo: VERBOSE, - filename: isDebug ? '[name].js' : '[name].[chunkhash:8].js', - chunkFilename: isDebug ? '[name].chunk.js' : '[name].[chunkhash:8].js', - }, - - resolve: { - extensions: ['.js', '.jsx', '.json', '.ts', '.tsx'], - }, - - module: { - rules: [ - { - test: /\.svg$/, - use: [ - { - loader: 'babel-loader', - }, - { - loader: 'react-svg-loader', - options: { - svgo: { - plugins: [ - { - removeViewBox: false, - }, - { - removeDimensions: true, - }, - ], - }, - jsx: false, - }, - }, - ], - }, - { - test: /\.(js|jsx|ts|tsx)$/, - loader: 'babel-loader', - include: [ - path.resolve(__dirname, 'src'), - ], - options: { - cacheDirectory: isDebug, - babelrc: false, - presets: [ - ['@babel/preset-env', { - targets: { - browsers: pkg.browserslist, - }, - modules: false, - useBuiltIns: 'usage', - corejs: { - version: 3, - }, - debug: false, - }], - '@babel/typescript', - '@babel/react', - ], - plugins: babelPlugins, - }, - }, - { - test: /\.css/, - use: ['style-loader', - { - loader: 'css-loader', - options: { - sourceMap: isDebug, - modules: false, - }, - }, - ], - }, - ], - }, - - plugins: [ - // Define free variables - // https://webpack.github.io/docs/list-of-plugins.html#defineplugin - new webpack.DefinePlugin({ - 'process.env.NODE_ENV': isDebug ? '"development"' : '"production"', - 'process.env.BROWSER': true, - }), - - // make multiple bundles for each language - new TtagWebpackPlugin({ - translations, - }), - - // Emit a file with assets paths - // https://github.com/sporto/assets-webpack-plugin#options - new AssetsPlugin({ - path: path.resolve(__dirname, 'build'), - filename: 'assets.json', - prettyPrint: true, - }), - - // Webpack Bundle Analyzer - // https://github.com/th0r/webpack-bundle-analyzer - ...isAnalyze ? [new BundleAnalyzerPlugin()] : [], - ], - - optimization: { - splitChunks: { - chunks: 'all', - name: false, - cacheGroups, - }, - }, - - bail: !isDebug, - - cache: isDebug, -}; diff --git a/webpack.config.web.babel.js b/webpack.config.web.babel.js index 0f4cb6de..e4bcd86a 100644 --- a/webpack.config.web.babel.js +++ b/webpack.config.web.babel.js @@ -5,6 +5,7 @@ import path from 'path'; import webpack from 'webpack'; import nodeExternals from 'webpack-node-externals'; import GeneratePackageJsonPlugin from 'generate-package-json-webpack-plugin'; +import CopyPlugin from 'copy-webpack-plugin'; import patch from './scripts/patch'; import pkg from './package.json'; @@ -70,6 +71,7 @@ export default ({ output: { path: path.resolve(__dirname, 'build'), libraryTarget: 'commonjs2', + clean: true, }, resolve: { @@ -142,6 +144,40 @@ export default ({ path.resolve(__dirname, 'package.json'), ], }), + new CopyPlugin({ + patterns: [ + { + from: path.resolve(__dirname, 'public'), + to: path.resolve(__dirname, 'build', 'public'), + }, + path.resolve(__dirname, 'src', 'canvases.json'), + path.resolve(__dirname, 'src', 'proxies.json'), + { + from: path.resolve( + __dirname, 'deployment', 'example-ecosystem.yml' + ), + to: path.resolve( + __dirname, 'build', 'ecosystem.yml' + ), + }, + { + from: path.resolve( + __dirname, 'deployment', 'example-ecosystem-backup.yml' + ), + to: path.resolve( + __dirname, 'build', 'ecosystem-backup.yml' + ), + }, + { + from: path.resolve( + __dirname, 'deployment', 'example-ecosystem-captchas.yml' + ), + to: path.resolve( + __dirname, 'build', 'ecosystem-captchas.yml' + ), + }, + ], + }), ], stats: {