From 6a31f1c57339bc64f2d033768a09b522ab257e4a Mon Sep 17 00:00:00 2001 From: Chalarangelo Date: Tue, 25 Aug 2020 20:20:02 +0300 Subject: [PATCH 01/39] Add VSCode settings --- .vscode/settings.json | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 000000000..c8ff90094 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,16 @@ +{ + "editor.tabSize": 2, + "editor.insertSpaces": true, + "editor.detectIndentation": false, + "eslint.autoFixOnSave": true, + "git.detectSubmodules": false, + "editor.rulers": [ + 80 + ], + "files.insertFinalNewline": true, + "editor.codeActionsOnSave": { + "source.fixAll.eslint": true + }, + "diffEditor.ignoreTrimWhitespace": false, + "files.trimTrailingWhitespace": true +} From 8d77d5f4072c7b224d4e6a08043c00e49db40c13 Mon Sep 17 00:00:00 2001 From: Chalarangelo Date: Tue, 25 Aug 2020 21:30:41 +0300 Subject: [PATCH 02/39] Replace kleur with chalk --- gatsby-node.js | 2 +- package-lock.json | 642 +++++++++++++++++++++++++++++++++++- package.json | 2 +- src/yild/logOutput/index.js | 11 +- 4 files changed, 644 insertions(+), 13 deletions(-) diff --git a/gatsby-node.js b/gatsby-node.js index 802fc2e96..a267e81ce 100644 --- a/gatsby-node.js +++ b/gatsby-node.js @@ -1,4 +1,4 @@ -const { green } = require('kleur'); +const { green } = require('chalk'); const env = require('./.build/env').default; const { diff --git a/package-lock.json b/package-lock.json index 11a468d80..acecdd38a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -258,6 +258,19 @@ "@babel/helper-validator-identifier": "^7.10.4", "chalk": "^2.0.0", "js-tokens": "^4.0.0" + }, + "dependencies": { + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + } } }, "@babel/parser": { @@ -507,6 +520,19 @@ "@babel/helper-validator-identifier": "^7.9.0", "chalk": "^2.0.0", "js-tokens": "^4.0.0" + }, + "dependencies": { + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + } } }, "@babel/parser": { @@ -740,6 +766,19 @@ "@babel/helper-validator-identifier": "^7.10.1", "chalk": "^2.0.0", "js-tokens": "^4.0.0" + }, + "dependencies": { + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + } } }, "@babel/parser": { @@ -1914,6 +1953,17 @@ "slash": "^2.0.0" }, "dependencies": { + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, "slash": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", @@ -1970,6 +2020,17 @@ "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", "dev": true }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, "slash": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", @@ -2045,6 +2106,17 @@ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", "dev": true }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, "slash": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", @@ -2144,6 +2216,17 @@ "write-file-atomic": "2.4.1" }, "dependencies": { + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, "slash": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", @@ -2254,6 +2337,17 @@ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", "dev": true }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, "is-fullwidth-code-point": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", @@ -2412,6 +2506,19 @@ "string-width": "^2.1.0", "strip-ansi": "^5.1.0", "through": "^2.3.6" + }, + "dependencies": { + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + } } }, "is-fullwidth-code-point": { @@ -2538,6 +2645,19 @@ "sockjs-client": "1.4.0", "strip-ansi": "5.2.0", "text-table": "0.2.0" + }, + "dependencies": { + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + } } }, "react-error-overlay": { @@ -4272,6 +4392,28 @@ "integrity": "sha512-AEzsGvjBJL0lby/87W96PyEvwN0GsYvk5LHsglLg9tW37K4BqvAvoSCdWIE13OZQ8afupqZ73+oL/1LkedN8hA==", "dev": true }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "dependencies": { + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, "electron-to-chromium": { "version": "1.3.458", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.458.tgz", @@ -5615,6 +5757,17 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.1.tgz", "integrity": "sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==", "dev": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } } } }, @@ -5973,14 +6126,55 @@ "dev": true }, "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", "dev": true, "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "dev": true, + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } } }, "character-entities": { @@ -6450,6 +6644,19 @@ "@types/q": "^1.5.1", "chalk": "^2.4.1", "q": "^1.1.2" + }, + "dependencies": { + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + } } }, "code-point-at": { @@ -6649,6 +6856,28 @@ "yargs": "^13.3.0" }, "dependencies": { + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "dependencies": { + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, "date-fns": { "version": "2.15.0", "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.15.0.tgz", @@ -7571,6 +7800,34 @@ "integrity": "sha512-NTBIIbAfkJeIletyABbVtdPgeKfDafR+1mZV/AyyfC1UkVkp9iUjV+wwmqtUgphHYajbI86jejBJp5e+jkGTiQ==", "dev": true }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "dependencies": { + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, "commander": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", @@ -8823,6 +9080,17 @@ "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", "dev": true }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, "cross-spawn": { "version": "6.0.5", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", @@ -10121,6 +10389,17 @@ "worker-rpc": "^0.1.0" }, "dependencies": { + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, "chokidar": { "version": "2.1.8", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", @@ -12578,6 +12857,43 @@ "integrity": "sha512-AEzsGvjBJL0lby/87W96PyEvwN0GsYvk5LHsglLg9tW37K4BqvAvoSCdWIE13OZQ8afupqZ73+oL/1LkedN8hA==", "dev": true }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + } + } + }, "chokidar": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.0.tgz", @@ -14092,6 +14408,19 @@ "@babel/helper-validator-identifier": "^7.10.1", "chalk": "^2.0.0", "js-tokens": "^4.0.0" + }, + "dependencies": { + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + } } }, "@babel/runtime": { @@ -15769,6 +16098,19 @@ "term-size": "^1.2.0", "type-fest": "^0.3.0", "widest-line": "^2.0.0" + }, + "dependencies": { + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + } } }, "cross-spawn": { @@ -16863,6 +17205,19 @@ "prompts": "^2.0.1", "realpath-native": "^1.1.0", "yargs": "^13.3.0" + }, + "dependencies": { + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + } } } } @@ -17006,6 +17361,17 @@ "babel-plugin-jest-hoist": "^24.9.0" } }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, "slash": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", @@ -17024,6 +17390,19 @@ "diff-sequences": "^24.9.0", "jest-get-type": "^24.9.0", "pretty-format": "^24.9.0" + }, + "dependencies": { + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + } } }, "jest-docblock": { @@ -17046,6 +17425,19 @@ "jest-get-type": "^24.9.0", "jest-util": "^24.9.0", "pretty-format": "^24.9.0" + }, + "dependencies": { + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + } } }, "jest-environment-jsdom": { @@ -17215,6 +17607,19 @@ "jest-util": "^24.9.0", "pretty-format": "^24.9.0", "throat": "^4.0.0" + }, + "dependencies": { + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + } } }, "jest-leak-detector": { @@ -17237,6 +17642,19 @@ "jest-diff": "^24.9.0", "jest-get-type": "^24.9.0", "pretty-format": "^24.9.0" + }, + "dependencies": { + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + } } }, "jest-message-util": { @@ -17255,6 +17673,17 @@ "stack-utils": "^1.0.1" }, "dependencies": { + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, "slash": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", @@ -17295,6 +17724,19 @@ "chalk": "^2.0.1", "jest-pnp-resolver": "^1.2.1", "realpath-native": "^1.1.0" + }, + "dependencies": { + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + } } }, "jest-resolve-dependencies": { @@ -17333,6 +17775,19 @@ "jest-worker": "^24.6.0", "source-map-support": "^0.5.6", "throat": "^4.0.0" + }, + "dependencies": { + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + } } }, "jest-runtime": { @@ -17366,6 +17821,17 @@ "yargs": "^13.3.0" }, "dependencies": { + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, "slash": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", @@ -17401,6 +17867,17 @@ "semver": "^6.2.0" }, "dependencies": { + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, "semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", @@ -17435,6 +17912,17 @@ "source-map": "^0.6.0" }, "dependencies": { + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, "is-ci": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", @@ -17470,6 +17958,19 @@ "jest-get-type": "^24.9.0", "leven": "^3.1.0", "pretty-format": "^24.9.0" + }, + "dependencies": { + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + } } }, "jest-watcher": { @@ -17499,6 +18000,17 @@ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", "dev": true }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, "string-length": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/string-length/-/string-length-2.0.0.tgz", @@ -17943,6 +18455,17 @@ "figures": "^2.0.0" }, "dependencies": { + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, "cli-cursor": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", @@ -18267,6 +18790,19 @@ "dev": true, "requires": { "chalk": "^2.4.2" + }, + "dependencies": { + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + } } }, "log-update": { @@ -19472,6 +20008,19 @@ "string-width": "^2.0.0", "term-size": "^1.2.0", "widest-line": "^2.0.0" + }, + "dependencies": { + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + } } }, "camelcase": { @@ -19782,6 +20331,19 @@ "latest-version": "^3.0.0", "semver-diff": "^2.0.0", "xdg-basedir": "^3.0.0" + }, + "dependencies": { + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + } } }, "url-parse-lax": { @@ -20893,6 +21455,28 @@ "supports-color": "^6.1.0" }, "dependencies": { + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "dependencies": { + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -23086,6 +23670,19 @@ "@babel/helper-validator-identifier": "^7.10.4", "chalk": "^2.0.0", "js-tokens": "^4.0.0" + }, + "dependencies": { + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + } } }, "@babel/parser": { @@ -25266,6 +25863,17 @@ "util.promisify": "~1.0.0" }, "dependencies": { + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, "css-select": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/css-select/-/css-select-2.1.0.tgz", @@ -27077,6 +27685,17 @@ "webpack-sources": "^1.0.0" }, "dependencies": { + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, "schema-utils": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", @@ -28017,6 +28636,17 @@ "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", "dev": true }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, "is-ci": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", diff --git a/package.json b/package.json index 930dc41e8..3d3f4fd68 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "@testing-library/react": "^10.4.8", "babel-jest": "^26.3.0", "babel-loader": "^8.0.6", + "chalk": "^4.1.0", "copy-to-clipboard": "^3.3.1", "cross-env": "^6.0.3", "css-loader": "^3.4.2", @@ -41,7 +42,6 @@ "jest": "^24.9.0", "jest-environment-jsdom-fourteen": "^1.0.1", "jest-transform-stub": "^2.0.0", - "kleur": "^3.0.3", "mdast-util-to-hast": "^9.1.0", "node-sass": "^4.14.1", "npm-watch": "^0.6.0", diff --git a/src/yild/logOutput/index.js b/src/yild/logOutput/index.js index d58db3b1c..f1cbf021b 100644 --- a/src/yild/logOutput/index.js +++ b/src/yild/logOutput/index.js @@ -1,15 +1,16 @@ -import kleur, { bold, blue, green, red, yellow } from 'kleur'; +import chalk from 'chalk'; import process from 'process'; +const { bold, blue, green, red, yellow } = chalk; global._yild_logOutput_instance = undefined; /** - * Format a string with the given kleur formatter. + * Format a string with the given chalk formatter. * @param {string} msg - The message to be formatted. - * @param {array} format - The name of the kleur function(s) to use. + * @param {array} format - The name of the chalk function(s) to use. */ export const format = (msg, ...format) => - format.reduce((m, f) => kleur[f] ? kleur[f](m) : m, msg); + format.reduce((m, f) => chalk[f] ? chalk[f](m) : m, msg); /** * Logger class-like, should be used to have a logger singleton. @@ -57,7 +58,7 @@ function logger() { let message = breakLine ? `${msg}\n` : `${msg}`; if(procName) message = `[${bold(procName)}] ${message}`; - if(validTypes.includes(type)) message = `${prefixes[type]} | ${message}`; + if(validTypes.includes(type)) message = `${prefixes[type]} ${message}`; this.outputStream.write(message); }; From 3a7a6565d9be71b0097834d42078af18e232e466 Mon Sep 17 00:00:00 2001 From: Chalarangelo Date: Tue, 25 Aug 2020 22:56:05 +0300 Subject: [PATCH 03/39] Merge language background generation into icon generation Combine steps by using one template for both. --- assets/icons.woff2 | Bin 2704 -> 2696 bytes package.json | 2 +- src/config/icons.json | 6 +++- src/config/paths.json | 1 - src/styles/_icon_colors.scss | 46 -------------------------- src/styles/_icons.scss | 42 ++++++++++++++++++++++- src/styles/index.scss | 1 - src/yild/core/actions.js | 7 ---- src/yild/makeIcons/cssTemplate.hbs | 11 ++++++ src/yild/makeIcons/index.js | 11 ++++-- src/yild/makeLangBackgrounds/index.js | 33 ------------------ 11 files changed, 67 insertions(+), 93 deletions(-) delete mode 100644 src/styles/_icon_colors.scss delete mode 100644 src/yild/makeLangBackgrounds/index.js diff --git a/assets/icons.woff2 b/assets/icons.woff2 index 159b87368fa293d8dfc07a1e5cdd933911204d53..e8d67afa27563ffceb382a1cfa2164d5f7861b23 100644 GIT binary patch delta 2661 zcmV-r3Yzth6^IoWcTYw#00961000Vz01E&B000;S000U)kr+UKM`8@lqaV?QJ~x`` z|K(ye9KRtMbqn>(#Sg*rK@V)^fX zs!}`Z+F~uvBG93K$oKtizdN1nNY0X#y_7MAnl4yazyjdd3wHz5S3*i4uff{%a1~&& zumHPWo&^Df$ukQ%JZI4=;#(Vgx6_S=elFnOQf%F{p@Dafq7^R%Uc?cscUatn0hV(W z;Pbye6NfZNjDj9w+4}lgDnH>*?VJQ6oGQ}-a;sLr*!rY@i{nD;AWE+qiz586G>g=v z(c!1|W)prAwy(AVc8Nk`p4)Np2oWYilo)YZu;f3y1g#`#qaB0;Z5{;>ov3bypM*(p zmLR|i1XzOr8xUXz1lR=u_CSC`Ai!Y|;0OqC6a+X10vrbcZUF(dAizEdZ~_Fl6$Cg5 z0^9}y+>SVZEag?kjsruXp9+;kh)g0FgnIq3o;I zJ?C>yAM_}kmSi#+Ex|X-yck!f;>5t^{-+?La0tK}Sr?@%5(!;j;2GgWk6A>q1zMgt zUgz!4W7O3lqC;zxQZiIA7^unF>4X|Ypa2r=F3{l#dN7@+jm+O{DB(yN5Mk(3F7TrH^F3|DWEGQ9+ z7yuti<4kvE0*;c5I?975cy<4>5NvaQce8EmEDHX+*yYwR{`x}e=kj>!vF^bhe_`^7 zQ*3xCUR1;RavT(!rX@XR z|M!nEhbJtRfm)yfZBKj7SNzvs_m#lV{LR|L@GbfxCVUCJ>8V5kxEe|hP``wKq+SQo znPpG;h4>2>7seM3`8$@ThNm95HGFHyQ(i%G@s@9Tddxw)pqln#`Jvk*OR~pZI7Cdg zttpxBHn$fT*00CVyFwW8`scy~#x{S;HLYRg8llDOuL~XMpj+2z#;mbV4iqM9#zg+~ z^VicYGq71^7o~_mW#NaVeyrVwGO6Q^btub=-^1A4`>| zm~jYAEv0fQRr}`ePyPSDfiv<0rfGXGyM1jF39B>8A4W6mtKG*)M)b+#d67GC-9pE8 zlw(M}pXX<}%XQpi(J@z!&YpD$y&iJr-xj?+x$>$pQKHlD@3=n(epADLYT7cS&Iq?~ z_uYjY87)~hO%FLkdRoOg86iw)K~a(7IHj#jQ^SPjgWrzj#BbpDg7^XKdDq|Q@$ThX#g z26Flg6CAZ|cP_aL+)Ivs2S1Qt%G4&d+se1+`S0oPLG!e)1bKh!RzDwTpKkZI!9wc_ zci0^p8EZP~tBdXnLmP@`!b6Uv;HFD$Zf@1?$Ze&3dQE892tWNnZ9yjK;isX}9aJ$IE;_sS}v+y$X$ z6EPmioHAyn)BT1~Oxq@Hea&n~C|~%dSPx9ZWG)MgmX_JI6qot(UiE5Lwn;nD%9yaj zR<^9O64PXC#YI$EM|CmC=%^_HZ$Y`|vXIqGxLZJ@^x>A) z$=9u~rdqc?*iv1i)D*W4KqJ^D7fP)I4A61CN9h6JyPGlwz-B1b09*rQ2%zJRyHW$F zGOM)<73|G_Pc^7HUkIdp^%yX-8zuaO*Z?SsfXlE3ejxq;`?En&AT*e_AU4~4=<~zF zn)*CEq%^7}`uo>^+kf_bXM>!<@#gZ#uz!wCTR5_Y6| z-}0;yB$ACl91~77X(oNw9soBhM$`m-*l{$>J?9<7_FE=E87l?&56!9JZGCbOHFk3V zi5%)5NBeM_w*gU#s)$OHw3YD^Prw) z?tl=E?r;|C>lqa!ikO~o77$DHctRu-y}gd;pY~WR1|JIsC1p1RmjV$6T0mFU^s028%AdM^ zx)DXU**e7p;w-HwjUH5kzhz_8R<}Cf&fnZ=6)M!pNfpa~|5KIPQP&o0aTb9NMZWKE z``zhmM{<^|?4^u;Cj^-aD*OzmcUUp33T{lsvG`Dwy(AV zb_Nas`P`0y0D=f1j0mELAr4Lc!%JWYNem+ekOFNU0RS3Bbqe?+nFP)Z1TY5yEIg8()`04G2I4}kzqf&d-{0h~e{ zEMUZLp964z29U2o+V?=8yc=~43dBqfMNERUg%Bl~HVTdi2oz03>8nXQvF9yXBvmwF zMkmG8LLd;#$EH%Ixhblp2DLHGY#~3Zby-9OvSc{IGJ;Vk!R=)x=QH1fd0JDV;m@tf zg^R8~82OU-ayjN}*|_uYSi;MR%s)EfyK1sa5z|b6lR$n%cN!WVk$Xc`0G@G@Zt=1Z z`y1<#e-vI3GhO^m1P{dXg*w+d`qc6we1Zsx-!0Lu4h3k&#TFuVFHqJ$51D#O3drZ?~)ZZr}bHV)!k5c1yuE5B^K;~n@ z$H?1%PXzpI?xr*DghQd3%_wJe$FtntR^Q(LJRFxVD2?1k{rovg4{j(7OyM+GXmkUE zCTGstBF4;@7Ms?Ng(t}w{<@<`TYyIQBeJt8cQ!U{zZ5erp&c)~?}!Qw5M>t4!?8!Q z1a~`TXt?WXmf92OS%>J+F&Dd1_?Wot%ve)@?GyBRS3Vw|OY;g48AKV%zIxqrKIim7 zkHTq5CX>+;e6!4padj$A3|#Ji3Ni|Z0IZR9QMw|L(DenL5l-}&MHE}0<(cDk-u^sB zT^%Aiv_>f%Y(uv8{V;$o}G*;=djE|WIg78 zUu*l7Ap`z=ogU9_`s-DC9NKF499tQ+gJ~w>`PMiXhl&TYk_wAvM{?1Pq}sfOn4C7V zSt8=%C3*RRiey??3iD8{l;n(OJ~wi?Ziz%f3u9`Ol3i@k{R8I$9iPpD60wK@@S!x$ zbY~{uD9Na!Ja~dv_b&^{LqI?VN3k~H|zgN{2Wb+lF5M2eJT+ER-t48_2L}a^LLzoYUrt}F9^M0-c!CC3~RT1IWZv*+L~(GwS{*Z6KtMM7)SOI6K$tt zewn#FTcTEj#N=s`^r0`2w59(4Z@K?#i8Brf`p}0+*dpkzI)TlOezL7F;cSll>6bo~ zZkd^7mSHEj&2}@JpZG5qX11_@S=d-JP8he1-6o!Z6jYoQHDM7mEL`rz=5MsZ7Pj97 zfxQ;ba%=B5e_;J@8o1>LOcVBAJX7dILW>MHOAsiT+&e}xqEDWDFmeZ6JE9E5l_B+h zo}cBVhBEGpY`(Z@_ECl4hl1+R3nMQ|Zo0HNg2=X4jl6R+{>n>y@g$gk$dFNd*~^Ls zGJ@gcqS&YQiN)PoWr$>G!JJ@poKo*zy6eW7iU$hEH?sMio zp8n!oBO_lQ-2LFWJHw+t*jLZ+BvF=F#9TNj%EEZxY3MY2LBQGbaF&feR9NDOpJg`N zHp2u*VcXShxEx9e?IL5OOnj=r}w5a$w2n(!ZwS9Cc`yq2aq`+_g)6;Z;j|ujZ19V@g$e z<#OpYLdwscbKfhac+uH%xmQtYtVohaX*2$+FNDAN%H^5wQ39Vi=e{SP_s&eb@{7Ob z$;;!jLoa{%!GnhmhQrnp>yrGTDSJNlxGZj1$?)U7Cc$QZH=OB*P7mbZR5i6eo4Rg| zNp-Wgzf^jStY)mqGN!rtQmc^4u1{4@MY4Uo+@KpUXTib~{Ks>Kp7W0(dpDKHyN`@* z`}EkSwvQcs*O9mudUfjnG{UjPW@7^k&}qL%$pP?lH{~e+9Dx!C;8rLL0G&?U6%DAW z#?@Mcz4^_5IpJ>OLUMKBF1-8OPn9#!+QA=x3}36ge(#O=_P+)g4+8wi8T+r^ zw>&F=k!*rECLU~>Y3$kq;1R`$nxGFmjz+oXd=An5mI;JdDe!+ZNBeAja)^xG9AFIc zkNg{oz%A~Y@lsd{)j5<#e8^_m^}~jo!chf5LYB06CZ-e5h1}~FcOQ?JQl1;HguFIB z-C%6j#bPR4qxMd+i|^$?=D%@yR818KIi*2 ztLAmv*8XnCcU!Hl)$_W`uH)w#zTaES=WC*Wnsd5sG&#CD`c8Azt!Sz6v_4<+JohOA z0+U;catbQ<0j;A>Ug2{snN@e$jr#`b=4PFLS!0=q%-DV;I{fm7;zFLNs&PT3hu_PKSEK8QJgfHl%OF>(lDiH zghmlMJ+HgEwdK})QEheW(rLKPt%%)w;B`A&m%6JRmxvIKqJ`J2H~i4?NGrXd(`xoi zs@;mWWH{X=x94`0({EI~9(S&+uj<`arBfG;Zrf$cebH+6eco&IRPQdo(d|gjtvJ5w bAM!n?5x~xTzuBqxMc=P@hQHeMeb)m3(V;AP diff --git a/package.json b/package.json index 3d3f4fd68..8df0d3f27 100644 --- a/package.json +++ b/package.json @@ -74,7 +74,7 @@ "watch-assets": "npm-watch prepare-assets", "serve-snippets": "NODE_PATH=src npx --node-arg '-r esm' ./src/jobs/yild.js -n=DEVELOPMENT -s", "yild": "NODE_PATH=src npx --node-arg '-r esm' ./src/jobs/yild.js", - "prebuild": "NODE_PATH=src npx --node-arg '-r esm' ./src/jobs/yild.js -u -a -e -i -b -n=PRODUCTION -c", + "prebuild": "NODE_PATH=src npx --node-arg '-r esm' ./src/jobs/yild.js -u -a -e -i -n=PRODUCTION -c", "predevelop": "NODE_PATH=src npx --node-arg '-r esm' ./src/jobs/yild.js -n=DEVELOPMENT -c", "pretest": "NODE_PATH=src npx --node-arg '-r esm' ./src/jobs/yild.js -n=DEVELOPMENT -c", "build": "NODE_PATH=src npx --node-arg '-r esm' gatsby build", diff --git a/src/config/icons.json b/src/config/icons.json index 7ce272e06..d2b66166f 100644 --- a/src/config/icons.json +++ b/src/config/icons.json @@ -5,5 +5,9 @@ "cssTemplatePath": "src/yild/makeIcons/cssTemplate.hbs", "cssSelector": ".icon", "cssClassName": "icon", - "cssClassPrefix": "icon-" + "cssClassPrefix": "icon-", + "cssLanguageSelectors": [ + ".card-icon", + ".btn" + ] } diff --git a/src/config/paths.json b/src/config/paths.json index cfcc9f0d0..4c57fdd79 100644 --- a/src/config/paths.json +++ b/src/config/paths.json @@ -7,7 +7,6 @@ "buildPath": ".build", "rawIconPath": "src/icons/*.svg", "iconFontPath": "src/styles/_icons.scss", - "iconBgFilePath": "src/styles/_icon_colors.scss", "queryPath": "./src/queries", "templatesPath": "./src/components/templates", "templates": [ diff --git a/src/styles/_icon_colors.scss b/src/styles/_icon_colors.scss deleted file mode 100644 index 11ddd26fe..000000000 --- a/src/styles/_icon_colors.scss +++ /dev/null @@ -1,46 +0,0 @@ - - .card-icon.icon-blog, .btn.icon-blog { - background: #1f253d; - color: #edf0fc; - } - - .card-icon.icon-js, .btn.icon-js { - background: #f6d854; - color: #392f31; - } - - .card-icon.icon-csharp, .btn.icon-csharp { - background: #672179; - color: #ffffff; - } - - .card-icon.icon-css, .btn.icon-css { - background: #3f4de4; - color: #ffffff; - } - - .card-icon.icon-dart, .btn.icon-dart { - background: #1b2634; - color: #ffffff; - } - - .card-icon.icon-golang, .btn.icon-golang { - background: #5ac9e2; - color: #000000; - } - - .card-icon.icon-php, .btn.icon-php { - background: #8b9bd6; - color: #2a2843; - } - - .card-icon.icon-python, .btn.icon-python { - background: #3c77a9; - color: #ffffff; - } - - .card-icon.icon-react, .btn.icon-react { - background: #282c34; - color: #61dafb; - } - \ No newline at end of file diff --git a/src/styles/_icons.scss b/src/styles/_icons.scss index d736c71fc..19dc12a03 100644 --- a/src/styles/_icons.scss +++ b/src/styles/_icons.scss @@ -1,6 +1,6 @@ @font-face { font-family: "icons"; - src: url("../../assets/icons.woff2?bc96d006b08d44606f3122178a9e0225") format("woff2"); + src: url("../../assets/icons.woff2?ee05ab874cb7c5179be6f88e879bb65c") format("woff2"); } .icon:before { @@ -80,3 +80,43 @@ .icon.icon-twitter:before { content: "\f116"; } + +.card-icon, +.btn { + &.icon-blog { + background: #1f253d; + color: #edf0fc; + } + &.icon-js { + background: #f6d854; + color: #392f31; + } + &.icon-csharp { + background: #672179; + color: #ffffff; + } + &.icon-css { + background: #3f4de4; + color: #ffffff; + } + &.icon-dart { + background: #1b2634; + color: #ffffff; + } + &.icon-golang { + background: #5ac9e2; + color: #000000; + } + &.icon-php { + background: #8b9bd6; + color: #2a2843; + } + &.icon-python { + background: #3c77a9; + color: #ffffff; + } + &.icon-react { + background: #282c34; + color: #61dafb; + } +} diff --git a/src/styles/index.scss b/src/styles/index.scss index 58d5d477a..97685c0f2 100644 --- a/src/styles/index.scss +++ b/src/styles/index.scss @@ -1,7 +1,6 @@ @import './fonts'; @import './icons'; @import './global_variables'; -@import './icon_colors'; @import './reset'; @import './code'; @import './anchor'; diff --git a/src/yild/core/actions.js b/src/yild/core/actions.js index bd26c620b..50d16edd4 100644 --- a/src/yild/core/actions.js +++ b/src/yild/core/actions.js @@ -4,7 +4,6 @@ import extractSnippets from '../extractSnippets'; import serveSnippets from '../serveSnippets'; import updateContent from '../updateContent'; import makeIcons from '../makeIcons'; -import makeLangBackgrounds from '../makeLangBackgrounds'; import prepareEnv from '../prepareEnv'; import prepareCacheKey from '../prepareCacheKey'; @@ -46,12 +45,6 @@ const actions = { step: 0, matcher: /^-{0,2}i(cons)?$/gi, }, - 'backgrounds': { - description: 'generate SCSS styles from the provided icons', - process: makeLangBackgrounds, - step: 0, - matcher: /^-{0,2}b(ackgrounds)?$/gi, - }, 'environment': { description: `generate environment configuration file\n${format('ENV', 'green', 'bold')} can be one of: (DEVELOPMENT, PRODUCTION)`, process: prepareEnv, diff --git a/src/yild/makeIcons/cssTemplate.hbs b/src/yild/makeIcons/cssTemplate.hbs index f1e46c86b..08c02a5e9 100644 --- a/src/yild/makeIcons/cssTemplate.hbs +++ b/src/yild/makeIcons/cssTemplate.hbs @@ -19,3 +19,14 @@ content: "\\{{ this }}"; } {{/ each }} + +{{# each langSelectors }} +{{this}}{{#if @last}} { {{else}}, {{/if}} +{{/ each}} +{{# each langIcons }} + &.{{ ../classPrefix }}{{ this.iconName }} { + background: {{ this.backColor }}; + color: {{ this.foreColor }}; + } +{{/ each }} +} diff --git a/src/yild/makeIcons/index.js b/src/yild/makeIcons/index.js index 5dcd39eb9..ff1bf2798 100644 --- a/src/yild/makeIcons/index.js +++ b/src/yild/makeIcons/index.js @@ -2,7 +2,7 @@ import glob from 'glob'; import fs from 'fs-extra'; import path from 'path'; import webfontsGenerator from 'webfonts-generator'; -import { initAction } from '../core'; +import { initAction, loadContentConfigs } from '../core'; import iconConfig from 'config/icons'; const { @@ -13,18 +13,21 @@ const { cssSelector, cssClassName, cssClassPrefix, + cssLanguageSelectors, } = iconConfig; /** * Generate a woff2 fle with the icon font and CSS styles to go with it. */ const makeIcons = () => { - const [boundLog, , inPath, outPath, cssPath] = initAction('makeIcons', [ + const [boundLog, , inPath, contentPath, outPath, cssPath] = initAction('makeIcons', [ ['paths', 'rawIconPath'], + ['paths', 'rawContentPath'], ['paths', 'rawAssetPath'], ['paths', 'iconFontPath'], ]); const files = glob.sync(`${inPath}`); + const configs = loadContentConfigs(contentPath, boundLog); boundLog(`Generating icon font and styles from ${files.length} files...`, 'info'); const config = { @@ -41,6 +44,10 @@ const makeIcons = () => { baseSelector: cssSelector, baseClassNames: cssClassName, classPrefix: cssClassPrefix, + langSelectors: cssLanguageSelectors, + langIcons: configs + .map(cfg => cfg.theme) + .filter(Boolean), }, }; diff --git a/src/yild/makeLangBackgrounds/index.js b/src/yild/makeLangBackgrounds/index.js deleted file mode 100644 index 42ef82765..000000000 --- a/src/yild/makeLangBackgrounds/index.js +++ /dev/null @@ -1,33 +0,0 @@ -import fs from 'fs-extra'; -import path from 'path'; -import { initAction, loadContentConfigs } from '../core'; - -/** - * Generate a SCSS file with the language background styles. - */ -const makeLanguageBgs = async() => { - const [boundLog, , inPath, outPath] = initAction('makeLanguageBgs', [ - ['paths', 'rawContentPath'], ['paths', 'iconBgFilePath'], - ]); - boundLog('Generating language background styles from config...', 'info'); - - const configs = loadContentConfigs(inPath, boundLog); - boundLog(`Generating SCSS code from configuration files`, 'success'); - const scss = configs - .map(cfg => cfg.theme) - .filter(Boolean) - .reduce((acc, cfg) => `${acc} - .card-icon.icon-${cfg.iconName}, .btn.icon-${cfg.iconName} { - background: ${cfg.backColor}; - color: ${cfg.foreColor}; - } - `, ''); - - boundLog(`Writing SCSS code to ${path.resolve(outPath)}`, 'info'); - await fs.writeFile(outPath, scss); - boundLog('Generating language background styles complete', 'success'); - - return; -}; - -export default makeLanguageBgs; From a46e5b25c9e9e7d43a54a36a87d06b0027b17a93 Mon Sep 17 00:00:00 2001 From: Chalarangelo Date: Tue, 25 Aug 2020 23:40:32 +0300 Subject: [PATCH 04/39] Move individual snippet parsing to own function Allow each snippet to be parsed as a single unit, decouple from readSnippets, allowing individual rebuilds. --- src/yild/extractSnippets/parseSnippets.js | 233 ++++++++++++---------- 1 file changed, 127 insertions(+), 106 deletions(-) diff --git a/src/yild/extractSnippets/parseSnippets.js b/src/yild/extractSnippets/parseSnippets.js index 21237aa38..ded53e1dd 100644 --- a/src/yild/extractSnippets/parseSnippets.js +++ b/src/yild/extractSnippets/parseSnippets.js @@ -161,6 +161,131 @@ export const getTags = tagStr => [...new Set(tagStr.split(','))]; */ export const getId = (snippetFilename, sourceDir) => `${sourceDir}/${snippetFilename.slice(0, -3)}`; +export const parseSnippet = async( + snippetsPath, snippet, { + sourceDir, commonData, slugPrefix, repoUrlPrefix, assetPath, langData, language, + isCssSnippet, isBlogSnippet, hasOptionalLanguage, languages, icon, biasPenaltyMultiplier, + } +) => { + let data, gitMetadata; + await Promise.all([ + getData(snippetsPath, snippet), + getGitMetadata(snippet, snippetsPath), + ]).then(values => { + data = values[0]; + gitMetadata = values[1]; + }); + const tags = getTags(data.attributes.tags); + const text = getTextualContent(data.body); + const [ code, rawCode ] = isBlogSnippet + ? [ null, [ ] ] + : getCodeBlocks(data.body, { + isCssSnippet, + hasOptionalLanguage, + languages, + snippetName: snippet.slice(0, -3), + }); + const type = isBlogSnippet ? `blog.${data.attributes.type}` : 'snippet'; + + let excerpt, cover, shortSliceIndex, authorsData, langIcon, shortText; + + if (isBlogSnippet) { + excerpt = data.attributes.excerpt; + cover = `${assetPath}${data.attributes.cover}`; + shortSliceIndex = text.indexOf('\n\n') <= 180 + ? text.indexOf('\n\n') + : text.indexOf(' ', 160); + shortText = excerpt && excerpt.trim().length !== 0 + ? excerpt + : `${text.slice(0, shortSliceIndex)}...`; + authorsData = getTags(data.attributes.authors).map(a => authors[a]); + langIcon = langData.find(l => tags.includes(l.language)); + } else + shortText = text.slice(0, text.indexOf('\n\n')); + + const html = parseMarkdown( + { + texts: { + fullDescription: isBlogSnippet ? data.body : text, + description: shortText, + }, + codeBlocks: rawCode, + }, { + isBlog: isBlogSnippet, + type, + assetPath, + } + ); + + const snippetData = { + ...commonData, + id: getId(snippet, sourceDir), + title: data.attributes.title, + type, + tags: { + all: tags, + primary: tags[0], + }, + code, + expertise: isBlogSnippet ? 'blog' : determineExpertiseFromTags(tags), + text: { + full: isBlogSnippet ? data.body : text, + short: shortText, + }, + cover, + authors: authorsData, + icon: langIcon ? langIcon.icon : icon, + searchTokens: uniqueElements( + isBlogSnippet ? [ + ...stripExpertiseFromTags(tags), + ...tokenizeSnippet(`${shortText} ${data.attributes.title}`), + ].map(v => v.toLowerCase()) : [ + data.attributes.title, + language.short, + language.long, + ...stripExpertiseFromTags(tags), + ...tokenizeSnippet(shortText), + ].map(v => v.toLowerCase()) + ).join(' '), + html, + ...gitMetadata, + slug: `/${slugPrefix}${convertToSeoSlug(snippet.slice(0, -3))}`, + url: `${repoUrlPrefix}/${snippet}`, + }; + + snippetData.ranking = rankSnippet({ + ...snippetData, + language: commonData.language, + biasPenaltyMultiplier: biasPenaltyMultiplier + ? biasPenaltyMultiplier + : 1.0, + }); + + return snippetData; +}; + +export const getParams = (config, langData, assetPath) => { + const isCssSnippet = config.dirName === '30css'; + const isBlogSnippet = config.isBlog; + const hasOptionalLanguage = !isCssSnippet && !isBlogSnippet && config.optionalLanguage && config.optionalLanguage.short; + const languages = isBlogSnippet ? [] : [ + config.language.short, + isCssSnippet ? config.secondLanguage.short : null, + hasOptionalLanguage || isCssSnippet ? config.optionalLanguage.short : null, + ].filter(Boolean).join('|'); + const icon = config.theme ? config.theme.iconName : null; + return { + sourceDir: `${config.dirName}/${config.snippetPath}`, + commonData: config.commonData, + slugPrefix: config.slugPrefix, + language: config.language, + biasPenaltyMultiplier: config.biasPenaltyMultiplier, + repoUrlPrefix: config.repoUrlPrefix, + isCssSnippet, isBlogSnippet, hasOptionalLanguage, languages, icon, + langData, assetPath, + }; +}; + /** * Synchronously read all snippets and sort them as necessary. * The sorting is case-insensitive. @@ -173,116 +298,12 @@ export const getId = (snippetFilename, sourceDir) => `${sourceDir}/${snippetFile */ export const readSnippets = async(snippetsPath, assetPath, config, langData, boundLog) => { const snippetFilenames = getFilesInDir(snippetsPath, boundLog); - const sourceDir = `${config.dirName}/${config.snippetPath}`; - const { commonData, slugPrefix, repoUrlPrefix } = config; - - const isCssSnippet = config.dirName === '30css'; - const isBlogSnippet = config.isBlog; - const hasOptionalLanguage = !isCssSnippet && !isBlogSnippet && config.optionalLanguage && config.optionalLanguage.short; - const languages = isBlogSnippet ? [] : [ - config.language.short, - isCssSnippet ? config.secondLanguage.short : null, - hasOptionalLanguage || isCssSnippet ? config.optionalLanguage.short : null, - ].filter(Boolean).join('|'); - const icon = config.theme ? config.theme.iconName : null; + const params = getParams(config, langData, assetPath); let snippets = []; try { for (let snippet of snippetFilenames) { - let data, gitMetadata; - await Promise.all([ - getData(snippetsPath, snippet), - getGitMetadata(snippet, snippetsPath), - ]).then(values => { - data = values[0]; - gitMetadata = values[1]; - }); - const tags = getTags(data.attributes.tags); - const text = getTextualContent(data.body); - const [ code, rawCode ] = isBlogSnippet - ? [ null, [ ] ] - : getCodeBlocks(data.body, { - isCssSnippet, - hasOptionalLanguage, - languages, - snippetName: snippet.slice(0, -3), - }); - const type = isBlogSnippet ? `blog.${data.attributes.type}` : 'snippet'; - - let excerpt, cover, shortSliceIndex, authorsData, langIcon, shortText; - - if (isBlogSnippet) { - excerpt = data.attributes.excerpt; - cover = `${assetPath}${data.attributes.cover}`; - shortSliceIndex = text.indexOf('\n\n') <= 180 - ? text.indexOf('\n\n') - : text.indexOf(' ', 160); - shortText = excerpt && excerpt.trim().length !== 0 - ? excerpt - : `${text.slice(0, shortSliceIndex)}...`; - authorsData = getTags(data.attributes.authors).map(a => authors[a]); - langIcon = langData.find(l => tags.includes(l.language)); - } else - shortText = text.slice(0, text.indexOf('\n\n')); - - const html = parseMarkdown( - { - texts: { - fullDescription: isBlogSnippet ? data.body : text, - description: shortText, - }, - codeBlocks: rawCode, - }, { - isBlog: isBlogSnippet, - type, - assetPath, - } - ); - - const snippetData = { - ...commonData, - id: getId(snippet, sourceDir), - title: data.attributes.title, - type, - tags: { - all: tags, - primary: tags[0], - }, - code, - expertise: isBlogSnippet ? 'blog' : determineExpertiseFromTags(tags), - text: { - full: isBlogSnippet ? data.body : text, - short: shortText, - }, - cover, - authors: authorsData, - icon: langIcon ? langIcon.icon : icon, - searchTokens: uniqueElements( - isBlogSnippet ? [ - ...stripExpertiseFromTags(tags), - ...tokenizeSnippet(`${shortText} ${data.attributes.title}`), - ].map(v => v.toLowerCase()) : [ - data.attributes.title, - config.language.short, - config.language.long, - ...stripExpertiseFromTags(tags), - ...tokenizeSnippet(shortText), - ].map(v => v.toLowerCase()) - ).join(' '), - html, - ...gitMetadata, - slug: `/${slugPrefix}${convertToSeoSlug(snippet.slice(0, -3))}`, - url: `${repoUrlPrefix}/${snippet}`, - }; - - snippetData.ranking = rankSnippet({ - ...snippetData, - language: commonData.language, - biasPenaltyMultiplier: config.biasPenaltyMultiplier - ? config.biasPenaltyMultiplier - : 1.0, - }); - + const snippetData = await parseSnippet(snippetsPath, snippet, params); snippets.push(snippetData); } } catch (err) { From 32a53dd3571a008028a00d5f72b0e150431319bb Mon Sep 17 00:00:00 2001 From: Chalarangelo Date: Wed, 26 Aug 2020 00:12:17 +0300 Subject: [PATCH 05/39] Fix a bug with recommendation ranking mutability recommendationRanking mutated the snippet object, allowing for previous recommendations to rank in certain cases. --- src/engines/recommendationEngine.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/engines/recommendationEngine.js b/src/engines/recommendationEngine.js index 4dcdeb1e9..74ef1231a 100644 --- a/src/engines/recommendationEngine.js +++ b/src/engines/recommendationEngine.js @@ -27,10 +27,9 @@ const determineRecommendedSnippets = (snippetNodes, snippetContext) => { return snippetNodes .map(v => { + v.recommendationRanking = 0; // Filter out any nodes with the same id (this very snippet) - if(v.id === snippetContext.id) - v.recommendationRanking = 0; - else { + if(v.id !== snippetContext.id) { // Determine score for language: // * Same language, as language = 100% of language score // * Same language, but as a tag = 25% of language score From 6f4e2cb71816da8b80bed9cf2cfd78bade32b6b1 Mon Sep 17 00:00:00 2001 From: Chalarangelo Date: Wed, 26 Aug 2020 00:14:24 +0300 Subject: [PATCH 06/39] Trim down parsed snippets in memory, write data Write individual snippet data in its own file, minimize amount of data stored in memory. --- src/yild/extractSnippets/extract.js | 2 +- src/yild/extractSnippets/parseSnippets.js | 42 +++++++++++++++++++---- 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/src/yild/extractSnippets/extract.js b/src/yild/extractSnippets/extract.js index 5ce6574fd..21131ae20 100644 --- a/src/yild/extractSnippets/extract.js +++ b/src/yild/extractSnippets/extract.js @@ -27,7 +27,7 @@ const extract = (configs, langData, parentLog) => configs.map(cfg => { boundLog(`Extracting snippets from ${snippetsPath}`, 'info'); return new Promise((resolve, reject) => - parseSnippets(snippetsPath, assetPath, {...cfg, commonData, slugPrefix, repoUrlPrefix}, langData, boundLog) + parseSnippets(snippetsPath, assetPath, contentOutDir, {...cfg, commonData, slugPrefix, repoUrlPrefix}, langData, boundLog) .then(snippetsArray => { const completeData = { data: snippetsArray, diff --git a/src/yild/extractSnippets/parseSnippets.js b/src/yild/extractSnippets/parseSnippets.js index ded53e1dd..5e4fe7ec8 100644 --- a/src/yild/extractSnippets/parseSnippets.js +++ b/src/yild/extractSnippets/parseSnippets.js @@ -163,8 +163,9 @@ export const getId = (snippetFilename, sourceDir) => `${sourceDir}/${snippetFile export const parseSnippet = async( snippetsPath, snippet, { - sourceDir, commonData, slugPrefix, repoUrlPrefix, assetPath, langData, language, - isCssSnippet, isBlogSnippet, hasOptionalLanguage, languages, icon, biasPenaltyMultiplier, + sourceDir, commonData, slugPrefix, repoUrlPrefix, assetPath, outPath, + langData, language, isCssSnippet, isBlogSnippet, hasOptionalLanguage, + languages, icon, biasPenaltyMultiplier, } ) => { let data, gitMetadata; @@ -261,10 +262,36 @@ export const parseSnippet = async( : 1.0, }); - return snippetData; + const outDir = `${outPath}/${snippetData.slug.slice(1)}`; + fs.ensureDirSync(outDir); + fs.writeFileSync( + `${outDir}/snippet.json`, + JSON.stringify(snippetData, null, 2) + ); + + const trimmedData = { + id: snippetData.id, + tags: snippetData.tags, + language: { + long: snippetData.language.long, + short: snippetData.language.short, + }, + searchTokens: snippetData.searchTokens, + ranking: snippetData.ranking, + blog: snippetData.blog, + title: snippetData.title, + expertise: snippetData.expertise, + icon: snippetData.icon, + slug: snippetData.slug, + html: { + description: snippetData.html.description, + }, + }; + + return trimmedData; }; -export const getParams = (config, langData, assetPath) => { +export const getParams = (config, langData, assetPath, outPath) => { const isCssSnippet = config.dirName === '30css'; const isBlogSnippet = config.isBlog; const hasOptionalLanguage = !isCssSnippet && !isBlogSnippet && config.optionalLanguage && config.optionalLanguage.short; @@ -282,7 +309,7 @@ export const getParams = (config, langData, assetPath) => { biasPenaltyMultiplier: config.biasPenaltyMultiplier, repoUrlPrefix: config.repoUrlPrefix, isCssSnippet, isBlogSnippet, hasOptionalLanguage, languages, icon, - langData, assetPath, + langData, assetPath, outPath, }; }; @@ -291,14 +318,15 @@ export const getParams = (config, langData, assetPath) => { * The sorting is case-insensitive. * @param {string} snippetsPath - The path of the snippets directory. * @param {string} assetPath - The public path of the assets directory. + * @param {string} outPath - The output path of the snippets directory. * @param {object} config - The project's enriched configuration * (containing the spread config, commonData and prefixes). * @param {array} langData - An array of `(language, icon)` tuples. * @param {function} boundLog - A bound logger.log function. */ -export const readSnippets = async(snippetsPath, assetPath, config, langData, boundLog) => { +export const readSnippets = async(snippetsPath, assetPath, outPath, config, langData, boundLog) => { const snippetFilenames = getFilesInDir(snippetsPath, boundLog); - const params = getParams(config, langData, assetPath); + const params = getParams(config, langData, assetPath, outPath); let snippets = []; try { From d54fcbceaf2edd28e45a4aaf0ae08d70336f9f16 Mon Sep 17 00:00:00 2001 From: Chalarangelo Date: Wed, 26 Aug 2020 00:14:46 +0300 Subject: [PATCH 07/39] Post-process snippet recommendations Rewrite system to output to individual files. --- src/yild/extractSnippets/extract.js | 3 +- src/yild/extractSnippets/postProcess.js | 80 +++++++++++-------------- 2 files changed, 36 insertions(+), 47 deletions(-) diff --git a/src/yild/extractSnippets/extract.js b/src/yild/extractSnippets/extract.js index 21131ae20..d9fe385d9 100644 --- a/src/yild/extractSnippets/extract.js +++ b/src/yild/extractSnippets/extract.js @@ -12,7 +12,6 @@ const extract = (configs, langData, parentLog) => configs.map(cfg => { const snippetsPath = `${contentDir}/sources/${cfg.dirName}/${cfg.snippetPath}`; const assetPath = `/${assetDir}/`; - const outputJson = `${contentOutDir}/${cfg.dirName}.json`; const slugPrefix = `${cfg.slug}/s`; const repoUrlPrefix = `${cfg.repoUrl}/blob/master/${cfg.snippetPath}`; const isBlog = !!cfg.isBlog; @@ -46,7 +45,7 @@ const extract = (configs, langData, parentLog) => configs.map(cfg => { }; boundLog(`Finished extracting ${snippetsPath}`, 'success'); resolve({ - outputFile: outputJson, + snippetsPath, data: completeData, }); }) diff --git a/src/yild/extractSnippets/postProcess.js b/src/yild/extractSnippets/postProcess.js index 129126e2c..952f0f300 100644 --- a/src/yild/extractSnippets/postProcess.js +++ b/src/yild/extractSnippets/postProcess.js @@ -4,51 +4,41 @@ import recommendationEngine from 'engines/recommendationEngine'; const postProcess = (allData, allSnippetData, parentLog) => { const boundLog = parentLog.rebind('postProcess'); - return allData.map(({ outputFile, data }) => new Promise((resolve, reject) => { - boundLog(`Post-processing snippets for ${outputFile}`, 'info'); - const outputData = { - data: data.data.map(snippet => { - const recommendedSnippets = recommendationEngine(allSnippetData, snippet) - .map(({ - id, title, expertise, tags, language, - icon, html, slug, searchTokens, - recommendationRanking, - }) => ({ - id, title, expertise, icon, slug, searchTokens, - recommendationRanking: +recommendationRanking, - html: { - description: html.description, - }, - tags: { - primary: tags.primary, - }, - language: { - short: language.short, - long: language.long, - }, - })); - return { - ...snippet, - recommendedSnippets, - }; - }), - meta: data.meta, - }; - fs.writeFile( - outputFile, - JSON.stringify(outputData, null, 2), - err => { - if (err) { - boundLog(`Encountered an error while writing ${outputFile}`, 'error'); - boundLog(`${err}`, 'error'); - reject(err); - } else { - boundLog(`Finished writing ${outputFile}`, 'success'); - resolve(); - } - } - ); - })); + return allData.map(async({ snippetsPath, data }) => { + const { + contentPath: contentOutDir, + } = global._yild_instance.config.paths; + boundLog(`Post-processing snippets for ${snippetsPath}`, 'info'); + + for (let snippet of data.data) { + const recommendedSnippets = recommendationEngine(allSnippetData, snippet) + .map(({ + id, title, expertise, tags, language, + icon, html, slug, searchTokens, + recommendationRanking, + }) => ({ + id, title, expertise, icon, slug, searchTokens, + recommendationRanking: +recommendationRanking, + html: { + description: html.description, + }, + tags: { + primary: tags.primary, + }, + language: { + short: language.short, + long: language.long, + }, + })); + + const outDir = `${contentOutDir}/${snippet.slug.slice(1)}`; + fs.ensureDirSync(outDir); + await fs.writeFile( + `${outDir}/recommendations.json`, + JSON.stringify(recommendedSnippets, null, 2) + ); + } + }); }; export default postProcess; From 054f6f1841f22b9cf0b1a78d93ecb81cbaa01e87 Mon Sep 17 00:00:00 2001 From: Chalarangelo Date: Wed, 26 Aug 2020 00:45:37 +0300 Subject: [PATCH 08/39] Transform snippet data from yild --- src/yild/extractSnippets/parseSnippets.js | 4 ++-- src/yild/extractSnippets/postProcess.js | 23 ++++------------------- 2 files changed, 6 insertions(+), 21 deletions(-) diff --git a/src/yild/extractSnippets/parseSnippets.js b/src/yild/extractSnippets/parseSnippets.js index 5e4fe7ec8..b247b5c08 100644 --- a/src/yild/extractSnippets/parseSnippets.js +++ b/src/yild/extractSnippets/parseSnippets.js @@ -5,7 +5,7 @@ import frontmatter from 'front-matter'; import { exec } from 'child_process'; import tokenizeSnippet from 'engines/searchIndexingEngine'; import { convertToSeoSlug, uniqueElements } from 'utils'; -import { determineExpertiseFromTags, stripExpertiseFromTags } from 'build/transformers'; +import { determineExpertiseFromTags, stripExpertiseFromTags, transformSnippetContext } from 'build/transformers'; import rankSnippet from 'engines/rankingEngine'; import parseMarkdown from './parseMarkdown'; // TODO: Consider parsing this via a new parser or similar @@ -266,7 +266,7 @@ export const parseSnippet = async( fs.ensureDirSync(outDir); fs.writeFileSync( `${outDir}/snippet.json`, - JSON.stringify(snippetData, null, 2) + JSON.stringify(transformSnippetContext(snippetData), null, 2) ); const trimmedData = { diff --git a/src/yild/extractSnippets/postProcess.js b/src/yild/extractSnippets/postProcess.js index 952f0f300..c307e2bc2 100644 --- a/src/yild/extractSnippets/postProcess.js +++ b/src/yild/extractSnippets/postProcess.js @@ -1,5 +1,6 @@ import fs from 'fs-extra'; import recommendationEngine from 'engines/recommendationEngine'; +import { transformSnippetIndex } from 'build/transformers'; const postProcess = (allData, allSnippetData, parentLog) => { const boundLog = parentLog.rebind('postProcess'); @@ -11,25 +12,9 @@ const postProcess = (allData, allSnippetData, parentLog) => { boundLog(`Post-processing snippets for ${snippetsPath}`, 'info'); for (let snippet of data.data) { - const recommendedSnippets = recommendationEngine(allSnippetData, snippet) - .map(({ - id, title, expertise, tags, language, - icon, html, slug, searchTokens, - recommendationRanking, - }) => ({ - id, title, expertise, icon, slug, searchTokens, - recommendationRanking: +recommendationRanking, - html: { - description: html.description, - }, - tags: { - primary: tags.primary, - }, - language: { - short: language.short, - long: language.long, - }, - })); + const recommendedSnippets = transformSnippetIndex( + recommendationEngine(allSnippetData, snippet).map(v => ( { node: v })) + ); const outDir = `${contentOutDir}/${snippet.slug.slice(1)}`; fs.ensureDirSync(outDir); From cfa6b16141457d63ae7e947bddf57e2bd8ffbc6c Mon Sep 17 00:00:00 2001 From: Chalarangelo Date: Wed, 26 Aug 2020 12:10:45 +0300 Subject: [PATCH 09/39] Add cardTemplate to content configs --- content/configs/30blog.json | 3 ++- content/configs/30css.json | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/content/configs/30blog.json b/content/configs/30blog.json index 6857a1b6a..a2957ba5e 100644 --- a/content/configs/30blog.json +++ b/content/configs/30blog.json @@ -19,5 +19,6 @@ "images": { "name": "blog_images", "path": "blog_images" - } + }, + "cardTemplate": "BlogSnippetCard" } diff --git a/content/configs/30css.json b/content/configs/30css.json index 66668b354..68e0d0f51 100644 --- a/content/configs/30css.json +++ b/content/configs/30css.json @@ -26,5 +26,6 @@ "foreColor": "#ffffff", "iconName": "css" }, - "biasPenaltyMultiplier": 1.05 + "biasPenaltyMultiplier": 1.05, + "cardTemplate": "CssSnippetCard" } From 1fba87d133879c5b6095e263b301d80c43ac0b7a Mon Sep 17 00:00:00 2001 From: Chalarangelo Date: Wed, 26 Aug 2020 12:11:05 +0300 Subject: [PATCH 10/39] Write snippet metadata to JSON --- src/yild/extractSnippets/extract.js | 1 + src/yild/extractSnippets/parseSnippets.js | 21 ++++++++++++++++++--- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/yild/extractSnippets/extract.js b/src/yild/extractSnippets/extract.js index d9fe385d9..291bdb245 100644 --- a/src/yild/extractSnippets/extract.js +++ b/src/yild/extractSnippets/extract.js @@ -23,6 +23,7 @@ const extract = (configs, langData, parentLog) => configs.map(cfg => { if (cfg.secondLanguage) otherLanguages.push(cfg.secondLanguage); if (cfg.optionalLanguage) otherLanguages.push(cfg.optionalLanguage); if (otherLanguages.length) commonData.language.otherLanguages = otherLanguages; + if (!cfg.cardTemplate) cfg.cardTemplate = 'StandardSnippetCard'; boundLog(`Extracting snippets from ${snippetsPath}`, 'info'); return new Promise((resolve, reject) => diff --git a/src/yild/extractSnippets/parseSnippets.js b/src/yild/extractSnippets/parseSnippets.js index b247b5c08..e8807c3c2 100644 --- a/src/yild/extractSnippets/parseSnippets.js +++ b/src/yild/extractSnippets/parseSnippets.js @@ -5,7 +5,13 @@ import frontmatter from 'front-matter'; import { exec } from 'child_process'; import tokenizeSnippet from 'engines/searchIndexingEngine'; import { convertToSeoSlug, uniqueElements } from 'utils'; -import { determineExpertiseFromTags, stripExpertiseFromTags, transformSnippetContext } from 'build/transformers'; +import { + determineExpertiseFromTags, + stripExpertiseFromTags, + transformSnippetContext, + transformBreadcrumbs, + transformSnippetDescription +} from 'build/transformers'; import rankSnippet from 'engines/rankingEngine'; import parseMarkdown from './parseMarkdown'; // TODO: Consider parsing this via a new parser or similar @@ -165,7 +171,7 @@ export const parseSnippet = async( snippetsPath, snippet, { sourceDir, commonData, slugPrefix, repoUrlPrefix, assetPath, outPath, langData, language, isCssSnippet, isBlogSnippet, hasOptionalLanguage, - languages, icon, biasPenaltyMultiplier, + languages, icon, biasPenaltyMultiplier, cardTemplate, } ) => { let data, gitMetadata; @@ -266,7 +272,15 @@ export const parseSnippet = async( fs.ensureDirSync(outDir); fs.writeFileSync( `${outDir}/snippet.json`, - JSON.stringify(transformSnippetContext(snippetData), null, 2) + JSON.stringify(transformSnippetContext(snippetData, cardTemplate), null, 2) + ); + fs.writeFileSync( + `${outDir}/metadata.json`, + JSON.stringify({ + cardTemplate, + breadcrumbs: transformBreadcrumbs(snippetData, cardTemplate), + pageDescription: transformSnippetDescription(snippetData, cardTemplate), + }, null, 2) ); const trimmedData = { @@ -306,6 +320,7 @@ export const getParams = (config, langData, assetPath, outPath) => { commonData: config.commonData, slugPrefix: config.slugPrefix, language: config.language, + cardTemplate: config.cardTemplate, biasPenaltyMultiplier: config.biasPenaltyMultiplier, repoUrlPrefix: config.repoUrlPrefix, isCssSnippet, isBlogSnippet, hasOptionalLanguage, languages, icon, From daee9f4727d652fc09ad5f83261e37090c51de62 Mon Sep 17 00:00:00 2001 From: Chalarangelo Date: Wed, 26 Aug 2020 14:28:06 +0300 Subject: [PATCH 11/39] Extract listing pages data from yild Mirror logic previously in createListingPages. --- src/yild/extractSnippets/postProcess.js | 244 ++++++++++++++++++++++++ 1 file changed, 244 insertions(+) diff --git a/src/yild/extractSnippets/postProcess.js b/src/yild/extractSnippets/postProcess.js index c307e2bc2..080e58c7b 100644 --- a/src/yild/extractSnippets/postProcess.js +++ b/src/yild/extractSnippets/postProcess.js @@ -1,10 +1,254 @@ import fs from 'fs-extra'; import recommendationEngine from 'engines/recommendationEngine'; import { transformSnippetIndex } from 'build/transformers'; +import { chunk } from 'utils'; +import EXPERTISE_LEVELS from 'config/expertise'; +import literals from 'lang/en/listing'; + +const ORDERS_MAP = { + 'p': literals.orders.popularity, + 'a': literals.orders.alphabetical, + 'e': literals.orders.expertise, +}; + +const CARDS_PER_PAGE = 40; + +const compileListingPages = ( + indexedChunks, + context, + baseUrl, + slugOrderingSegment, + ordersList +) => { + const { + contentPath: contentOutDir, + } = global._yild_instance.config.paths; + + indexedChunks.forEach((chunk, i, chunks) => { + const outDir = `${contentOutDir}${baseUrl}/${slugOrderingSegment}/${i + 1}`; + fs.ensureDirSync(outDir); + + fs.writeFileSync( + `${outDir}/snippetList.json`, + JSON.stringify(chunk, null, 2) + ); + fs.writeFileSync( + `${outDir}/metadata.json`, + JSON.stringify({ + isMainListing: + context.listingType === 'main' && + slugOrderingSegment === 'p' && + i === 0, + paginator: { + pageNumber: i + 1, + totalPages: chunks.length, + baseUrl, + slugOrderingSegment, + }, + sorter: { + orders: ordersList.map(order => ( + { + url: `${baseUrl}/${order}/1`, + title: ORDERS_MAP[order], + } + )), + selectedOrder: ORDERS_MAP[slugOrderingSegment], + }, + ...context, + }, null, 2) + ); + }); +}; + +const compileListingPagesWithOrderOptions = ( + context, + baseUrl, + orders, + chunks, + contextCustomizer = () => ({}) +) => { + orders.forEach((order, i) => { + compileListingPages( + chunks[i], + { ...context, ...contextCustomizer(order, i)}, + baseUrl, + order, + orders + ); + }); +}; + +const compileListingData = (snippetIndex, listingMetas) => { + // 1. Create listing pages for the main listing: + // Tranform and chunk data for popularity, alphabetical and expertise ordering + const transformedIndex = transformSnippetIndex( + snippetIndex.map(v => ( { node: v })) + ); + const popularChunks = chunk(transformedIndex, CARDS_PER_PAGE); + const alphabeticalChunks = chunk(transformedIndex.sort((a, b) => + a.title.localeCompare(b.title) + ), CARDS_PER_PAGE); + const expertiseChunks = chunk(transformedIndex.sort((a, b) => + a.expertise === b.expertise ? a.title.localeCompare(b.title) : + !a.expertise ? 1 : !b.expertise ? -1 : + EXPERTISE_LEVELS.indexOf(a.expertise) - EXPERTISE_LEVELS.indexOf(b.expertise) + ), CARDS_PER_PAGE); + // Create main listing sublinks and customization method for context + const mainListingSublinks = listingMetas + .map(v => v.featured > 0 ? v : {...v, featured: 500 }) + .sort((a, b) => a.featured === b.featured ? a.name - b.name : a.featured - b.featured); + const mainContextCustomizer = order => { + return { + listingSublinks: mainListingSublinks + .map(l => ({ + ...l, + url: l.url.replace('/p/1', `/${order}/1`), + })), + }; + }; + // Create the listing pages with the order options provided + compileListingPagesWithOrderOptions( + { + listingName: literals.snippetList, + listingTitle: literals.snippetList, + listingType: 'main', + listingSublinks: mainListingSublinks, + pageDescription: literals.pageDescription('main', { + snippetCount: transformedIndex.length, + }), + }, + '/list', + ['p', 'a', 'e'], + [popularChunks, alphabeticalChunks, expertiseChunks], + mainContextCustomizer + ); + + // 2. Create listing pages for the language listings + listingMetas.forEach(listingMeta => { + // Determine slug prefix and relevant information, create chunks from data for + // each of the ordering options + const slugPrefix = listingMeta.slugPrefix; + const snippetIndexName = snippetIndex + .find(s => s.slug.startsWith(`${slugPrefix}`)).language.long || ''; + const snippetIndexSlugData = snippetIndex.filter(s => + s.slug.startsWith(`${slugPrefix}`) || + (s.blog && s.tags.all.find(t => t.toLowerCase() === snippetIndexName.toLowerCase())) + ); + const transformedSlugChunks = transformSnippetIndex( + snippetIndexSlugData.map(v => ( { node: v })) + ); + const popularSlugChunks = chunk(transformedSlugChunks, CARDS_PER_PAGE); + const alphabeticalSlugChunks = chunk(transformedSlugChunks.sort((a, b) => + a.title.localeCompare(b.title) + ), CARDS_PER_PAGE); + const expertiseSlugChunks = chunk(transformedSlugChunks.sort((a, b) => + a.expertise === b.expertise ? a.title.localeCompare(b.title) : + !a.expertise ? 1 : !b.expertise ? -1 : + EXPERTISE_LEVELS.indexOf(a.expertise) - EXPERTISE_LEVELS.indexOf(b.expertise) + ), CARDS_PER_PAGE); + // Determine tag prefixes for the listing + const snippetIndexTagPrefixes = listingMeta.tags; + const slugContextCustomizer = order => { + return { + listingSublinks: listingMeta.blog ? [] : [ + { + url: `${slugPrefix}/${order}/1`, + name: literals.tag('all'), + selected: true, + }, + ...listingMeta.tags + .map(tag => ({ + url: `${slugPrefix}/t/${tag}/${order}/1`, + name: literals.tag(tag), + })), + ], + }; + }; + // Create the listing pages with the order options provided + compileListingPagesWithOrderOptions( + { + listingName: listingMeta.blog ? literals.blog : literals.codelang(snippetIndexName), + listingTitle: listingMeta.blog ? literals.blog : literals.codelang(snippetIndexName), + listingType: listingMeta.blog ? 'blog' : 'language', + pageDescription: literals.pageDescription(listingMeta.blog ? 'blog' : 'language', { + snippetCount: snippetIndexSlugData.length, + listingLanguage: listingMeta.blog ? 'blog' : snippetIndexName, + }), + }, + `${slugPrefix}`, + ['p', 'a', 'e'], + [popularSlugChunks, alphabeticalSlugChunks, expertiseSlugChunks], + slugContextCustomizer + ); + + // 3. Create listing pages for the tag listings + snippetIndexTagPrefixes.forEach(tagPrefix => { + // Determine slug prefix and relevant information, create chunks from data + // for each of the ordering options + const snippetIndexTagData = snippetIndex + .filter(s => + s.tags.primary === tagPrefix && s.slug.startsWith(`${slugPrefix}`) || + ( s.blog && + s.tags.all.find(t => t.toLowerCase() === snippetIndexName.toLowerCase()) && + s.tags.all.find(t => t.toLowerCase() === tagPrefix.toLowerCase()) + ) + ); + const transformedTagChunks = transformSnippetIndex( + snippetIndexTagData.map(v => ( { node: v })) + ); + const popularTagChunks = chunk(transformedTagChunks, CARDS_PER_PAGE); + const alphabeticalTagChunks = chunk(transformedTagChunks.sort((a, b) => + a.title.localeCompare(b.title) + ), CARDS_PER_PAGE); + const expertiseTagChunks = chunk(transformedTagChunks.sort((a, b) => + a.expertise === b.expertise ? a.title.localeCompare(b.title) : + !a.expertise ? 1 : !b.expertise ? -1 : + EXPERTISE_LEVELS.indexOf(a.expertise) - EXPERTISE_LEVELS.indexOf(b.expertise) + ), CARDS_PER_PAGE); + const tagContextCustomizer = order => { + return { + listingSublinks: listingMeta.blog ? [] : [ + { + url: `${slugPrefix}/${order}/1`, + name: literals.tag('all'), + selected: true, + }, + ...listingMeta.tags + .map(tag => ({ + url: `${slugPrefix}/t/${tag}/${order}/1`, + name: literals.tag(tag), + })), + ].map(tag => ({ ...tag, selected: tag.url.indexOf(`/t/${tagPrefix}/`) !== -1 })), + }; + }; + // Create the listing pages with the order options provided + compileListingPagesWithOrderOptions( + { + listingName: literals.codelangTag(snippetIndexName, tagPrefix), + listingTitle: literals.codelang(snippetIndexName), + listingType: 'tag', + pageDescription: literals.pageDescription('tag', { + snippetCount: snippetIndexSlugData.length, + listingLanguage: snippetIndexName, + listingTag: tagPrefix, + }), + }, + `${slugPrefix}/t/${tagPrefix}`, + ['p', 'a', 'e'], + [popularTagChunks, alphabeticalTagChunks, expertiseTagChunks], + tagContextCustomizer + ); + }); + }); +}; const postProcess = (allData, allSnippetData, parentLog) => { const boundLog = parentLog.rebind('postProcess'); + // Generate listing datas + compileListingData(allSnippetData, allData.map(({ data }) => data.meta)); + + // Write snippet recommendations return allData.map(async({ snippetsPath, data }) => { const { contentPath: contentOutDir, From f1504bcd24e9f1aa7c93646591edd05f5a259855 Mon Sep 17 00:00:00 2001 From: Chalarangelo Date: Wed, 26 Aug 2020 19:38:26 +0300 Subject: [PATCH 12/39] Add index.json for all pages Temporarily generate JSON data for statics. --- src/yild/extractSnippets/index.js | 42 +++++++++++++++++++++++ src/yild/extractSnippets/parseSnippets.js | 13 ++++++- src/yild/extractSnippets/postProcess.js | 23 +++++++++---- 3 files changed, 71 insertions(+), 7 deletions(-) diff --git a/src/yild/extractSnippets/index.js b/src/yild/extractSnippets/index.js index b9c32a1d7..ed35aab8e 100644 --- a/src/yild/extractSnippets/index.js +++ b/src/yild/extractSnippets/index.js @@ -2,6 +2,7 @@ import fs from 'fs-extra'; import { initAction, loadContentConfigs } from '../core'; import extract from './extract'; import postProcess from './postProcess'; +import literals from 'lang/en'; const extractSnippets = async() => { const [boundLog, , inPath, outPath] = initAction('extractSnippets', [ @@ -35,6 +36,47 @@ const extractSnippets = async() => { .all(postProcess(allData, allSnippetData, boundLog)); boundLog('Snippet post-processing complete', 'success'); + // TODO: Temporary, let's move this after the next restructure + [ + { + slug: '/404', + context: {}, + template: 'NotFoundPage', + priority: 0.0, + }, + { + slug: '/about', + context: {stringLiterals: literals.about}, + template: 'StaticPage', + priority: 0.25, + }, + { + slug: '/cookies', + context: {stringLiterals: literals.cookies}, + template: 'StaticPage', + priority: 0.25, + }, + { + slug: '/settings', + context: {stringLiterals: literals.settings}, + template: 'SettingsPage', + priority: 0.01, + }, + ].forEach(p => { + const outDir = `${outPath}${p.slug}`; + fs.ensureDirSync(outDir); + fs.writeFileSync( + `${outDir}/index.json`, + JSON.stringify({ + template: p.template, + fullRoute: `https://30secondsofcode.org${p.slug}`, + relRoute: p.slug, + priority: p.priority, + }, null, 2) + ); + fs.writeFileSync(`${outDir}/context.json`, JSON.stringify(p.context, null, 2)); + }); + return; }; diff --git a/src/yild/extractSnippets/parseSnippets.js b/src/yild/extractSnippets/parseSnippets.js index e8807c3c2..97167b679 100644 --- a/src/yild/extractSnippets/parseSnippets.js +++ b/src/yild/extractSnippets/parseSnippets.js @@ -270,9 +270,20 @@ export const parseSnippet = async( const outDir = `${outPath}/${snippetData.slug.slice(1)}`; fs.ensureDirSync(outDir); + fs.writeFileSync( + `${outDir}/index.json`, + JSON.stringify({ + template: 'SnippetPage', + fullRoute: `https://30secondsofcode.org${snippetData.slug}`, + relRoute: `${snippetData.slug}`, + priority: (snippetData.ranking * 0.85).toFixed(2), + }, null, 2) + ); fs.writeFileSync( `${outDir}/snippet.json`, - JSON.stringify(transformSnippetContext(snippetData, cardTemplate), null, 2) + JSON.stringify({ + snippet: transformSnippetContext(snippetData, cardTemplate), + }, null, 2) ); fs.writeFileSync( `${outDir}/metadata.json`, diff --git a/src/yild/extractSnippets/postProcess.js b/src/yild/extractSnippets/postProcess.js index 080e58c7b..8c9a616ce 100644 --- a/src/yild/extractSnippets/postProcess.js +++ b/src/yild/extractSnippets/postProcess.js @@ -25,20 +25,29 @@ const compileListingPages = ( } = global._yild_instance.config.paths; indexedChunks.forEach((chunk, i, chunks) => { + const isMainListing = context.listingType === 'main' && slugOrderingSegment === 'p' && i === 0; const outDir = `${contentOutDir}${baseUrl}/${slugOrderingSegment}/${i + 1}`; fs.ensureDirSync(outDir); + fs.writeFileSync( + `${outDir}/index.json`, + JSON.stringify({ + template: 'ListingPage', + fullRoute: `https://30secondsofcode.org${baseUrl}/${slugOrderingSegment}/${i + 1}`, + relRoute: `${baseUrl}/${slugOrderingSegment}/${i + 1}`, + priority: isMainListing ? 1.0 : 0.7, + }, null, 2) + ); fs.writeFileSync( `${outDir}/snippetList.json`, - JSON.stringify(chunk, null, 2) + JSON.stringify({ + snippetList: chunk, + }, null, 2) ); fs.writeFileSync( `${outDir}/metadata.json`, JSON.stringify({ - isMainListing: - context.listingType === 'main' && - slugOrderingSegment === 'p' && - i === 0, + isMainListing, paginator: { pageNumber: i + 1, totalPages: chunks.length, @@ -264,7 +273,9 @@ const postProcess = (allData, allSnippetData, parentLog) => { fs.ensureDirSync(outDir); await fs.writeFile( `${outDir}/recommendations.json`, - JSON.stringify(recommendedSnippets, null, 2) + JSON.stringify({ + recommendedSnippets, + }, null, 2) ); } }); From af9ca507ee5e3900d79677e2047eae7a2297ca8e Mon Sep 17 00:00:00 2001 From: Chalarangelo Date: Wed, 26 Aug 2020 21:55:14 +0300 Subject: [PATCH 13/39] Replace GraphQL layer with home-brewed system Pass generated data to createPages, cut out sourceNodes, querying, graphQL, transformations etc. --- gatsby-node.js | 9 +- src/build/createPages.js | 25 ++ src/build/createPages/createListingPages.js | 300 ------------------ src/build/createPages/createSnippetPages.js | 40 --- src/build/createPages/createStaticPage.js | 12 - .../createPages/createStaticPage.test.js | 18 -- src/build/createPages/index.js | 108 ------- src/build/index.js | 2 - src/build/parsers/index.js | 2 - src/build/parsers/parseQueries.js | 26 -- src/build/parsers/parseQueries.test.js | 40 --- src/build/parsers/parseRequirables.js | 22 +- src/build/parsers/parseRequirables.test.js | 13 +- src/build/sourceNodes.js | 36 --- src/build/sourceNodes.test.js | 40 --- src/queries/createPagesQuery.graphql | 189 ----------- src/queries/getSearchIndex.graphql | 27 -- 17 files changed, 54 insertions(+), 855 deletions(-) create mode 100644 src/build/createPages.js delete mode 100644 src/build/createPages/createListingPages.js delete mode 100644 src/build/createPages/createSnippetPages.js delete mode 100644 src/build/createPages/createStaticPage.js delete mode 100644 src/build/createPages/createStaticPage.test.js delete mode 100644 src/build/createPages/index.js delete mode 100644 src/build/parsers/parseQueries.js delete mode 100644 src/build/parsers/parseQueries.test.js delete mode 100644 src/build/sourceNodes.js delete mode 100644 src/build/sourceNodes.test.js delete mode 100644 src/queries/createPagesQuery.graphql delete mode 100644 src/queries/getSearchIndex.graphql diff --git a/gatsby-node.js b/gatsby-node.js index a267e81ce..73a2d7551 100644 --- a/gatsby-node.js +++ b/gatsby-node.js @@ -2,12 +2,10 @@ const { green } = require('chalk'); const env = require('./.build/env').default; const { - sourceNodes, createPages, onCreateWebpackConfig, } = require(`./src/build`); const { - parseQueries, parseRequirables, parseTemplates, } = require(`./src/build/parsers`); @@ -19,11 +17,6 @@ console.log(`${green('success')} parse requirables`); const templates = parseTemplates(env === 'DEVELOPMENT' ? paths.devTemplates : paths.templates, paths.templatesPath); console.log(`${green('success')} parse templates`); -const pagesQuery = parseQueries(paths.queryPath); -console.log(`${green('success')} parse queries`); - -exports.createPages = createPages(pagesQuery, templates, requirables); - -exports.sourceNodes = sourceNodes(requirables); +exports.createPages = createPages(templates, requirables); exports.onCreateWebpackConfig = onCreateWebpackConfig; diff --git a/src/build/createPages.js b/src/build/createPages.js new file mode 100644 index 000000000..b0184a959 --- /dev/null +++ b/src/build/createPages.js @@ -0,0 +1,25 @@ +/** + * Tell plugins to add pages. + * Takes a list of requirable objects and a templates object. + * Creates pages by running createPage for each ne. + */ +const createPages = (templates, requirables) => ({ actions }) => { + const { createPage } = actions; + + requirables.forEach(req => + createPage({ + path: req.relRoute, + component: templates[req.template], + context: req.context, + }) + ); + + const mainListing = requirables.find(req => req.context.isMainListing); + createPage({ + path: '/', + component: templates[mainListing.template], + context: mainListing.context, + }); +}; + +export default createPages; diff --git a/src/build/createPages/createListingPages.js b/src/build/createPages/createListingPages.js deleted file mode 100644 index c32933692..000000000 --- a/src/build/createPages/createListingPages.js +++ /dev/null @@ -1,300 +0,0 @@ -import { chunk } from 'utils'; -import { transformSnippetIndex } from 'build/transformers'; -import EXPERTISE_LEVELS from 'config/expertise'; -import literals from 'lang/en/listing'; - -const ORDERS_MAP = { - 'p': literals.orders.popularity, - 'a': literals.orders.alphabetical, - 'e': literals.orders.expertise, -}; - -const CARDS_PER_PAGE = 40; - -/** - * Creates listing pages from the data provided. - * @param {*} indexedChunks - Chunked snippets. - * @param {*} listingPage - Listing page template. - * @param {*} createPage - Page creation method from gatsby. - * @param {*} context - Page context. - * @param {*} baseUrl - Base url slug. - * @param {*} slugOrderingSegment - Ordering segment for the url slug. - * @param {*} ordersList - List of orders. - */ -const createListingPages = ( - indexedChunks, - listingPage, - createPage, - context, - baseUrl, - slugOrderingSegment, - ordersList -) => { - indexedChunks.forEach((chunk, i, chunks) => { - createPage({ - path: `${baseUrl}/${slugOrderingSegment}/${i + 1}`, - component: listingPage, - context: { - snippetList: chunk, - paginator: { - pageNumber: i + 1, - totalPages: chunks.length, - baseUrl, - slugOrderingSegment, - }, - sorter: { - orders: ordersList.map(order => ( - { - url: `${baseUrl}/${order}/1`, - title: ORDERS_MAP[order], - } - )), - selectedOrder: ORDERS_MAP[slugOrderingSegment], - }, - ...context, - }, - }); - }); - // Create Home page - if (context.listingType === 'main' && slugOrderingSegment === 'p') { - createPage({ - path: `/`, - component: listingPage, - context: { - snippetList: indexedChunks[0], - paginator: { - pageNumber: 1, - totalPages: indexedChunks.length, - baseUrl, - slugOrderingSegment, - }, - sorter: { - orders: ordersList.map(order => ( - { - url: `${baseUrl}/${order}/1`, - title: ORDERS_MAP[order], - } - )), - selectedOrder: ORDERS_MAP[slugOrderingSegment], - }, - ...context, - }, - }); - } -}; - -/** - * Creates listing pages using the provided orders and customization. - * @param {*} listingPage - Listing page template. - * @param {*} createPage - Page creation method from gatsby. - * @param {*} context - Page context. - * @param {*} baseUrl - Base url slug. - * @param {*} orders - List of orders. - * @param {*} chunks - Chunked snippets. - * @param {*} contextCustomizer - A function for customizing context based on order. - */ -const createListingPagesWithOrderOptions = ( - listingPage, - createPage, - context, - baseUrl, - orders, - chunks, - contextCustomizer = () => ({}) -) => { - orders.forEach((order, i) => { - createListingPages( - chunks[i], - listingPage, - createPage, - { ...context, ...contextCustomizer(order, i)}, - baseUrl, - order, - orders - ); - }); -}; - -/** - * (Export) Creates all the listing pages, including data for order options. - * @param {*} searchIndex - The raw search index data. - * @param {*} listingMetas - Listing pages metadata. - * @param {*} listingPage - Listing page template. - * @param {*} createPage - Page creation method from gatsby. - * @param {*} context - Page context. - */ -/* eslint-disable no-extra-boolean-cast */ -const createAllListingPages = ( - searchIndex, - listingMetas, - listingPage, - createPage, - context -) => { - // 1. Create listing pages for the main listing: - // Tranform and chunk data for popularity, alphabetical and expertise ordering - const transformedIndex = transformSnippetIndex(searchIndex.edges); - const popularChunks = chunk(transformedIndex, CARDS_PER_PAGE); - const alphabeticalChunks = chunk(transformedIndex.sort((a, b) => - a.title.localeCompare(b.title) - ), CARDS_PER_PAGE); - const expertiseChunks = chunk(transformedIndex.sort((a, b) => - a.expertise === b.expertise ? a.title.localeCompare(b.title) : - !a.expertise ? 1 : !b.expertise ? -1 : - EXPERTISE_LEVELS.indexOf(a.expertise) - EXPERTISE_LEVELS.indexOf(b.expertise) - ), CARDS_PER_PAGE); - // Create main listing sublinks and customization method for context - const mainListingSublinks = listingMetas - .map(v => v.featured > 0 ? v : {...v, featured: 500 }) - .sort((a, b) => a.featured === b.featured ? a.name - b.name : a.featured - b.featured); - const mainContextCustomizer = order => { - return { - listingSublinks: mainListingSublinks - .map(l => ({ - ...l, - url: l.url.replace('/p/1', `/${order}/1`), - })), - }; - }; - // Create the listing pages with the order options provided - createListingPagesWithOrderOptions( - listingPage, - createPage, - { - ...context, - listingName: literals.snippetList, - listingTitle: literals.snippetList, - listingType: 'main', - listingSublinks: mainListingSublinks, - pageDescription: literals.pageDescription('main', { - snippetCount: transformedIndex.length, - }), - }, - '/list', - ['p', 'a', 'e'], - [popularChunks, alphabeticalChunks, expertiseChunks], - mainContextCustomizer - ); - - // 2. Create listing pages for the language listings - listingMetas.forEach(listingMeta => { - // Determine slug prefix and relevant information, create chunks from data for - // each of the ordering options - const slugPrefix = listingMeta.slugPrefix; - const searchIndexName = searchIndex.edges - .find(s => s.node.slug.startsWith(`${slugPrefix}`)).node.language.long || ''; - const searchIndexSlugData = searchIndex.edges.filter(s => - s.node.slug.startsWith(`${slugPrefix}`) || - (s.node.blog && s.node.tags.all.find(t => t.toLowerCase() === searchIndexName.toLowerCase())) - ); - const transformedSlugChunks = transformSnippetIndex(searchIndexSlugData); - const popularSlugChunks = chunk(transformedSlugChunks, CARDS_PER_PAGE); - const alphabeticalSlugChunks = chunk(transformedSlugChunks.sort((a, b) => - a.title.localeCompare(b.title) - ), CARDS_PER_PAGE); - const expertiseSlugChunks = chunk(transformedSlugChunks.sort((a, b) => - a.expertise === b.expertise ? a.title.localeCompare(b.title) : - !a.expertise ? 1 : !b.expertise ? -1 : - EXPERTISE_LEVELS.indexOf(a.expertise) - EXPERTISE_LEVELS.indexOf(b.expertise) - ), CARDS_PER_PAGE); - // Determine tag prefixes for the listing - const searchIndexTagPrefixes = listingMeta.tags; - const slugContextCustomizer = order => { - return { - listingSublinks: listingMeta.blog ? [] : [ - { - url: `${slugPrefix}/${order}/1`, - name: literals.tag('all'), - selected: true, - }, - ...listingMeta.tags - .map(tag => ({ - url: `${slugPrefix}/t/${tag}/${order}/1`, - name: literals.tag(tag), - })), - ], - }; - }; - // Create the listing pages with the order options provided - createListingPagesWithOrderOptions( - listingPage, - createPage, - { - ...context, - listingName: listingMeta.blog ? literals.blog : literals.codelang(searchIndexName), - listingTitle: listingMeta.blog ? literals.blog : literals.codelang(searchIndexName), - listingType: listingMeta.blog ? 'blog' : 'language', - pageDescription: literals.pageDescription(listingMeta.blog ? 'blog' : 'language', { - snippetCount: searchIndexSlugData.length, - listingLanguage: listingMeta.blog ? 'blog' : searchIndexName, - }), - }, - `${slugPrefix}`, - ['p', 'a', 'e'], - [popularSlugChunks, alphabeticalSlugChunks, expertiseSlugChunks], - slugContextCustomizer - ); - - // 3. Create listing pages for the tag listings - searchIndexTagPrefixes.forEach(tagPrefix => { - // Determine slug prefix and relevant information, create chunks from data - // for each of the ordering options - const searchIndexTagData = searchIndex.edges - .filter(s => - s.node.tags.primary === tagPrefix && s.node.slug.startsWith(`${slugPrefix}`) || - ( s.node.blog && - s.node.tags.all.find(t => t.toLowerCase() === searchIndexName.toLowerCase()) && - s.node.tags.all.find(t => t.toLowerCase() === tagPrefix.toLowerCase()) - ) - ); - const transformedTagChunks = transformSnippetIndex(searchIndexTagData); - const popularTagChunks = chunk(transformedTagChunks, CARDS_PER_PAGE); - const alphabeticalTagChunks = chunk(transformedTagChunks.sort((a, b) => - a.title.localeCompare(b.title) - ), CARDS_PER_PAGE); - const expertiseTagChunks = chunk(transformedTagChunks.sort((a, b) => - a.expertise === b.expertise ? a.title.localeCompare(b.title) : - !a.expertise ? 1 : !b.expertise ? -1 : - EXPERTISE_LEVELS.indexOf(a.expertise) - EXPERTISE_LEVELS.indexOf(b.expertise) - ), CARDS_PER_PAGE); - const tagContextCustomizer = order => { - return { - listingSublinks: listingMeta.blog ? [] : [ - { - url: `${slugPrefix}/${order}/1`, - name: literals.tag('all'), - selected: true, - }, - ...listingMeta.tags - .map(tag => ({ - url: `${slugPrefix}/t/${tag}/${order}/1`, - name: literals.tag(tag), - })), - ].map(tag => ({ ...tag, selected: tag.url.indexOf(`/t/${tagPrefix}/`) !== -1 })), - }; - }; - // Create the listing pages with the order options provided - createListingPagesWithOrderOptions( - listingPage, - createPage, - { - ...context, - listingName: literals.codelangTag(searchIndexName, tagPrefix), - listingTitle: literals.codelang(searchIndexName), - listingType: 'tag', - pageDescription: literals.pageDescription('tag', { - snippetCount: searchIndexSlugData.length, - listingLanguage: searchIndexName, - listingTag: tagPrefix, - }), - }, - `${slugPrefix}/t/${tagPrefix}`, - ['p', 'a', 'e'], - [popularTagChunks, alphabeticalTagChunks, expertiseTagChunks], - tagContextCustomizer - ); - }); - }); -}; - -export default createAllListingPages; diff --git a/src/build/createPages/createSnippetPages.js b/src/build/createPages/createSnippetPages.js deleted file mode 100644 index 4e0ced8f3..000000000 --- a/src/build/createPages/createSnippetPages.js +++ /dev/null @@ -1,40 +0,0 @@ -import { - transformSnippetIndex, - transformSnippetContext, - transformSnippetDescription, - transformBreadcrumbs -} from 'build/transformers'; - -/** - * Creates individual snippet pages. - * @param {array} snippets - An array of snippets. - * @param {*} snippetPage - Snippet page template. - * @param {*} createPage - Page creation method from gatsby. - * @param {*} commonContext - Context to be passed to the page. - * @param {array} imageContext - Image context. - */ -const createSnippetPages = ( - snippets, - snippetPage, - createPage, - commonContext -) => { - snippets.forEach(snippet => { - const recommendedSnippets = transformSnippetIndex( - snippet.node.recommendedSnippets.map(v => ( { node: v })) - ); - createPage({ - path: `${snippet.node.slug}`, - component: snippetPage, - context: { - snippet: transformSnippetContext(snippet.node, commonContext.cardTemplate), - ...commonContext, - recommendedSnippets, - breadcrumbs: transformBreadcrumbs(snippet.node, commonContext.cardTemplate), - pageDescription: transformSnippetDescription(snippet.node, commonContext.cardTemplate), - }, - }); - }); -}; - -export default createSnippetPages; diff --git a/src/build/createPages/createStaticPage.js b/src/build/createPages/createStaticPage.js deleted file mode 100644 index fbb04e9a7..000000000 --- a/src/build/createPages/createStaticPage.js +++ /dev/null @@ -1,12 +0,0 @@ -/** - * Responsible for creating static pages (about, cookies, search, settings etc). - * @param {*} component - Static page template to be used. - * @param {*} createPage - Page creation method from gatsby. - * @param {*} context - Context to be passed to the page. - * @param {*} path - Page URL. - */ -const createStaticPage = (component, createPage, context, path) => { - createPage({ path, component, context }); -}; - -export default createStaticPage; diff --git a/src/build/createPages/createStaticPage.test.js b/src/build/createPages/createStaticPage.test.js deleted file mode 100644 index fcd0ae8b2..000000000 --- a/src/build/createPages/createStaticPage.test.js +++ /dev/null @@ -1,18 +0,0 @@ -import createStaticPage from './createStaticPage'; - -const createPageMock = jest.fn(); - -describe('createStaticPage', () => { - beforeAll(() => { - createStaticPage('my-component', createPageMock, 'test', '/static'); - }); - - it('calls createPage with the correct arguments', () => { - expect(createPageMock.mock.calls.length).toBe(1); - expect(createPageMock).toHaveBeenCalledWith({ - path: '/static', - component: 'my-component', - context: 'test', - }); - }); -}); diff --git a/src/build/createPages/index.js b/src/build/createPages/index.js deleted file mode 100644 index df7f02991..000000000 --- a/src/build/createPages/index.js +++ /dev/null @@ -1,108 +0,0 @@ -import createStaticPage from './createStaticPage'; -import createListingPages from './createListingPages'; -import createSnippetPages from './createSnippetPages'; -import { transformSnippetIndex } from 'build/transformers'; -import literals from 'lang/en'; - -/** - * Tell plugins to add pages. - * Takes a query string and a templates object. - * Takes a list of requirable objects after being loaded. - * Creates pages by running individual methods. - */ -const createPages = (query, templates, requirables) => ({ graphql, actions }) => { - const { createPage } = actions; - - return graphql(query) - .then(result => { - if (result.errors) throw result.errors; - - const searchIndex = result.data.searchIndex; - const listingMetas = requirables.map(rq => rq.meta); - - createStaticPage( - templates['NotFoundPage'], - createPage, - {}, - '/404' - ); - - createStaticPage( - templates['StaticPage'], - createPage, - { - stringLiterals: literals.about, - }, - '/about' - ); - - createStaticPage( - templates['StaticPage'], - createPage, - { - stringLiterals: literals.cookies, - }, - '/cookies' - ); - - createStaticPage( - templates['SettingsPage'], - createPage, - { - stringLiterals: literals.settings, - }, - '/settings' - ); - - createListingPages( - searchIndex, - listingMetas, - templates['ListingPage'], - createPage, - {}, - '/list' - ); - - createSnippetPages( - result.data.simpleSnippets.edges, - templates['SnippetPage'], - createPage, - { - cardTemplate: 'StandardSnippetCard', - } - ); - - createSnippetPages( - result.data.cssSnippets.edges, - templates['SnippetPage'], - createPage, - { - cardTemplate: 'CssSnippetCard', - } - ); - - createSnippetPages( - result.data.blogSnippets.edges, - templates['SnippetPage'], - createPage, - { - cardTemplate: 'BlogSnippetCard', - } - ); - - createStaticPage( - templates['SearchPage'], - createPage, - { - searchIndex: transformSnippetIndex(searchIndex.edges, true), - recommendedSnippets: transformSnippetIndex(searchIndex.edges.slice(0, 3)), - pageDescription: literals.search.pageDescription(searchIndex.edges.length), - }, - '/search' - ); - - return null; - }); -}; - -export default createPages; diff --git a/src/build/index.js b/src/build/index.js index 959d0d2be..7af14bea1 100644 --- a/src/build/index.js +++ b/src/build/index.js @@ -1,9 +1,7 @@ -import sourceNodes from './sourceNodes'; import createPages from './createPages'; import onCreateWebpackConfig from './onCreateWebpackConfig'; export { - sourceNodes, createPages, onCreateWebpackConfig, }; diff --git a/src/build/parsers/index.js b/src/build/parsers/index.js index 5a8e62ca4..d981e4928 100644 --- a/src/build/parsers/index.js +++ b/src/build/parsers/index.js @@ -1,9 +1,7 @@ -import parseQueries from './parseQueries'; import parseRequirables from './parseRequirables'; import parseTemplates from './parseTemplates'; export { - parseQueries, parseRequirables, parseTemplates }; diff --git a/src/build/parsers/parseQueries.js b/src/build/parsers/parseQueries.js deleted file mode 100644 index 127474fda..000000000 --- a/src/build/parsers/parseQueries.js +++ /dev/null @@ -1,26 +0,0 @@ -import glob from 'glob'; -import fs from 'fs-extra'; -import path from 'path'; - -/** - * Combines the given GraphQL queries in the given directory, returning a - * single query string to be run against the GraphQL schema. - * @param {string} contentDirPath - The path to the queries directory. - */ -const parseQueries = queryDirPath => { - // Load queries - let queries = []; - glob.sync(`${queryDirPath}/*.graphql`) - .forEach( file => { - queries.push( - fs.readFileSync(path.resolve(`${file}`), 'utf8') - .replace(/^query\s+{\n/g, '\n') - .replace(/\n}\n*$/g, '\n') - ); - }); - return `query { - ${queries.join('\n')} - }`; -}; - -export default parseQueries; diff --git a/src/build/parsers/parseQueries.test.js b/src/build/parsers/parseQueries.test.js deleted file mode 100644 index acb0fffa6..000000000 --- a/src/build/parsers/parseQueries.test.js +++ /dev/null @@ -1,40 +0,0 @@ -import parseQueries from './parseQueries'; - -import glob from 'glob'; -import fs from 'fs-extra'; -import path from 'path'; - -jest.mock('glob'); -jest.mock('path'); -jest.mock('fs-extra'); - -const mockQuery = `query { - searchIndex: allSnippet( - sort: {fields: ranking, order: DESC} - ) { - edges { - node { - slug - } - } - } -}`; - -glob.sync.mockImplementation(jest.fn(() => ['my-query.graphql'])); -path.resolve.mockImplementation(jest.fn(f => f)); -fs.readFileSync.mockImplementation(() => mockQuery); - -let resultQuery; - -describe('parseQueries', () => { - beforeAll(() => { - resultQuery = parseQueries('my-queries-dir'); - }); - it('returns a usable GraphQL query', () => { - expect(resultQuery.indexOf('query')).not.toBe(-1); - expect(resultQuery.indexOf('searchIndex')).not.toBe(-1); - expect(resultQuery.indexOf('edges')).not.toBe(-1); - expect(resultQuery.indexOf('node')).not.toBe(-1); - expect(resultQuery.indexOf('slug')).not.toBe(-1); - }); -}); diff --git a/src/build/parsers/parseRequirables.js b/src/build/parsers/parseRequirables.js index 0326e34a3..2b7e079c1 100644 --- a/src/build/parsers/parseRequirables.js +++ b/src/build/parsers/parseRequirables.js @@ -9,11 +9,25 @@ import path from 'path'; const parseRequirables = contentDirPath => { // Load configurations let requirables = []; - glob.sync(`${contentDirPath}/*.json`) + glob + .sync(`${contentDirPath}/**/index.json`) .forEach( file => { - requirables.push( - require( path.resolve( file ) ) - ); + const dir = file.slice(0, file.lastIndexOf('/')); + const reqData = glob + .sync(`${dir}/!(index).json`) + .reduce((acc, dataFile) => { + const data = require(path.resolve(dataFile)); + acc.context = { + ...acc.context, + ...data, + }; + return acc; + }, + { + ...require(path.resolve(file)), + context: {}, + }); + requirables.push(reqData); }); return requirables; }; diff --git a/src/build/parsers/parseRequirables.test.js b/src/build/parsers/parseRequirables.test.js index 03a43e05d..d5464fd42 100644 --- a/src/build/parsers/parseRequirables.test.js +++ b/src/build/parsers/parseRequirables.test.js @@ -44,7 +44,13 @@ const mockRequirables = { }, }; -glob.sync.mockImplementation(jest.fn(() => ['stdRequirable.json', 'ltdRequirable.json'])); +glob.sync.mockImplementation( + jest + .fn() + .mockReturnValueOnce(['stdRequirable.json', 'ltdRequirable.json']) + .mockReturnValueOnce(['stdRequirable.json']) + .mockReturnValueOnce(['ltdRequirable.json']) +); path.resolve.mockImplementation(jest.fn(f => f)); // eslint-disable-next-line no-unused-vars @@ -60,9 +66,10 @@ jest.mock('ltdRequirable.json', describe('parseRequirables', () => { it('returns the array of the resulting requirables', () => { + console.log(); expect(parseRequirables('my-content-dir')).toEqual([ - mockRequirables['stdRequirable'], - mockRequirables['ltdRequirable'], + {...mockRequirables['stdRequirable'], context: mockRequirables['stdRequirable'] }, + {...mockRequirables['ltdRequirable'], context: mockRequirables['ltdRequirable']}, ]); }); }); diff --git a/src/build/sourceNodes.js b/src/build/sourceNodes.js deleted file mode 100644 index bb247799e..000000000 --- a/src/build/sourceNodes.js +++ /dev/null @@ -1,36 +0,0 @@ -import schema from 'typedefs'; - -/** - * Extension point to tell plugins to source nodes. - * Defines the custom Snippet type. - * Populates the newly-created nodes. - * API docs: https://www.gatsbyjs.org/docs/node-apis/#sourceNodes - */ -const sourceNodes = requirables => ({ actions, createNodeId, createContentDigest }) => { - const { createTypes, createNode } = actions; - - // Create the GraphQL schema, adding the custom types - const typeDefs = `${schema}`; - createTypes(typeDefs); - - // Use the passed requirables (JSON files) to create the GraphQL nodes for - // the snippet data nodes they include. - requirables - .forEach(sArr => { - sArr.data.forEach(sNode => { - createNode({ - id: createNodeId(`snippet${sNode.slug}`), - parent: null, - children: [], - internal: { - type: 'Snippet', - content: JSON.stringify(sNode), - contentDigest: createContentDigest(sNode), - }, - ...sNode, - }); - }); - }); -}; - -export default sourceNodes; diff --git a/src/build/sourceNodes.test.js b/src/build/sourceNodes.test.js deleted file mode 100644 index ce1a3ebbf..000000000 --- a/src/build/sourceNodes.test.js +++ /dev/null @@ -1,40 +0,0 @@ -import sourceNodes from './sourceNodes'; -import { requirables } from 'fixtures/requirables'; - -const createTypesMock = jest.fn(); -const createNodeMock = jest.fn(); -const actions = { - createTypes: createTypesMock, - createNode: createNodeMock, -}; - -const createNodeIdMock = jest.fn(s => s); -const createContentDigestMock = jest.fn(() => null); -const getNodesByTypeMock = jest.fn().mockReturnValue([ - {fileAbsolutePath: '30code/snippets/all.md'}, - {fileAbsolutePath: '30code/snippets/allEqual.md'}, - {fileAbsolutePath: '30csharp/snippets/FindIndexOfLastBy.md'}, - {fileAbsolutePath: '30csharp/snippets/FindLastBy.md'}, -]); - -describe('sourceNodes', () => { - beforeAll(() => { - sourceNodes(requirables)({ - actions, - createNodeId: createNodeIdMock, - createContentDigest: createContentDigestMock, - getNodesByType: getNodesByTypeMock, - }); - }); - - it('calls createTypes once', () => { - expect(createTypesMock.mock.calls.length).toBe(1); - }); - - it('calls createNode, createNodeId and createContentDigest once for each snippet', () => { - expect(createNodeMock.mock.calls.length).toBe(4); - expect(createNodeIdMock.mock.calls.length).toBe(4); - expect(createContentDigestMock.mock.calls.length).toBe(4); - }); -}); - diff --git a/src/queries/createPagesQuery.graphql b/src/queries/createPagesQuery.graphql deleted file mode 100644 index 87425b9f9..000000000 --- a/src/queries/createPagesQuery.graphql +++ /dev/null @@ -1,189 +0,0 @@ -query { - simpleSnippets: allSnippet( - sort: {fields: id}, - filter: {code: {src: {ne: null}}} - ) { - edges { - node { - id - slug - url - tags { - all - primary - } - text { - full - short - } - title - html { - code - example - style - description - fullDescription - } - code { - src - example - style - } - expertise - ranking - firstSeen - lastUpdated - language { - long - short - otherLanguages { - short - long - } - } - icon - searchTokens - recommendedSnippets { - id - title - expertise - icon - slug - tags { - primary - } - expertise - language { - short - long - } - searchTokens - html { - description - } - } - } - } - } - - cssSnippets: allSnippet( - sort: {fields: id}, - filter: {language: {short: {eq: "css"}}} - ) { - edges { - node { - id - slug - url - tags { - all - primary - } - text { - full - short - } - title - html { - html - css - js - description - fullDescription - } - code { - html - css - js - scopedCss - } - expertise - ranking - firstSeen - lastUpdated - language { - long - short - } - icon - searchTokens - recommendedSnippets { - id - title - expertise - icon - slug - tags { - primary - } - expertise - language { - short - long - } - searchTokens - html { - description - } - } - } - } - } - - blogSnippets: allSnippet( - sort: {fields: firstSeen, order: DESC}, - filter: {blog: {eq: true}} - ) { - edges { - node { - id - slug - url - tags { - all - primary - } - text { - full - short - } - title - html { - description - fullDescription - } - expertise - ranking - firstSeen - lastUpdated - authors { - name - profile - } - icon - cover - blog - searchTokens - recommendedSnippets { - id - title - expertise - icon - slug - tags { - primary - } - expertise - language { - short - long - } - searchTokens - html { - description - } - } - } - } - } -} diff --git a/src/queries/getSearchIndex.graphql b/src/queries/getSearchIndex.graphql deleted file mode 100644 index b729d71d3..000000000 --- a/src/queries/getSearchIndex.graphql +++ /dev/null @@ -1,27 +0,0 @@ -query { - searchIndex: allSnippet( - sort: {fields: ranking, order: DESC} - ) { - edges { - node { - slug - blog - title - html { - description - } - tags { - primary - all - } - expertise - language { - short - long - } - icon - searchTokens - } - } - } -} From 0dddde904fbfa73316873a4034420cc0d96f22df Mon Sep 17 00:00:00 2001 From: Chalarangelo Date: Wed, 26 Aug 2020 21:58:17 +0300 Subject: [PATCH 14/39] Move gatsby lifecycle hooks to own directory --- gatsby-node.js | 2 +- src/{build => gatsby}/createPages.js | 0 src/{build => gatsby}/index.js | 0 src/{build => gatsby}/onCreateWebpackConfig.js | 0 src/{build => gatsby}/onCreateWebpackConfig.test.js | 0 5 files changed, 1 insertion(+), 1 deletion(-) rename src/{build => gatsby}/createPages.js (100%) rename src/{build => gatsby}/index.js (100%) rename src/{build => gatsby}/onCreateWebpackConfig.js (100%) rename src/{build => gatsby}/onCreateWebpackConfig.test.js (100%) diff --git a/gatsby-node.js b/gatsby-node.js index 73a2d7551..0bd31ffec 100644 --- a/gatsby-node.js +++ b/gatsby-node.js @@ -4,7 +4,7 @@ const env = require('./.build/env').default; const { createPages, onCreateWebpackConfig, -} = require(`./src/build`); +} = require(`./src/gatsby`); const { parseRequirables, parseTemplates, diff --git a/src/build/createPages.js b/src/gatsby/createPages.js similarity index 100% rename from src/build/createPages.js rename to src/gatsby/createPages.js diff --git a/src/build/index.js b/src/gatsby/index.js similarity index 100% rename from src/build/index.js rename to src/gatsby/index.js diff --git a/src/build/onCreateWebpackConfig.js b/src/gatsby/onCreateWebpackConfig.js similarity index 100% rename from src/build/onCreateWebpackConfig.js rename to src/gatsby/onCreateWebpackConfig.js diff --git a/src/build/onCreateWebpackConfig.test.js b/src/gatsby/onCreateWebpackConfig.test.js similarity index 100% rename from src/build/onCreateWebpackConfig.test.js rename to src/gatsby/onCreateWebpackConfig.test.js From 15f80cd22ad9cedae3b3e8e3cc99a9c2ae952c68 Mon Sep 17 00:00:00 2001 From: Chalarangelo Date: Wed, 26 Aug 2020 22:17:53 +0300 Subject: [PATCH 15/39] Update transformSnippets for new data layer Remove GraphQL artifacts --- src/build/transformers/transformSnippets.js | 22 ++-- .../transformers/transformSnippets.test.js | 100 ++++++++---------- src/yild/extractSnippets/postProcess.js | 14 +-- src/yild/serveSnippets/index.js | 2 +- 4 files changed, 63 insertions(+), 75 deletions(-) diff --git a/src/build/transformers/transformSnippets.js b/src/build/transformers/transformSnippets.js index 63afb9c53..3888277ee 100644 --- a/src/build/transformers/transformSnippets.js +++ b/src/build/transformers/transformSnippets.js @@ -5,19 +5,19 @@ import literals from 'lang/en/snippet'; /** * Transform the indexed snippets to the appropriate format. * Used in listing pages to render snippet previews. - * @param {array} edges - An array of snippet edges. + * @param {array} snippets - An array of snippets. * @param {bool} withSearchTokens - Should include search tokens in the result? */ -export const transformSnippetIndex = (edges, withSearchTokens = false) => - edges.map(({ node }) => ({ - title: node.title, - expertise: transformTagName(node.expertise), - primaryTag: transformTagName(node.tags.primary), - language: node.language && node.language.long ? node.language.long : undefined, - icon: node.icon, - description: node.html.description.trim(), - url: node.slug, - ...(withSearchTokens ? { searchTokens: node.searchTokens } : {}), +export const transformSnippetIndex = (snippets, withSearchTokens = false) => + snippets.map(snippet => ({ + title: snippet.title, + expertise: transformTagName(snippet.expertise), + primaryTag: transformTagName(snippet.tags.primary), + language: snippet.language && snippet.language.long ? snippet.language.long : undefined, + icon: snippet.icon, + description: snippet.html.description.trim(), + url: snippet.slug, + ...(withSearchTokens ? { searchTokens: snippet.searchTokens } : {}), })); /** diff --git a/src/build/transformers/transformSnippets.test.js b/src/build/transformers/transformSnippets.test.js index d950120b4..ef4c9404a 100644 --- a/src/build/transformers/transformSnippets.test.js +++ b/src/build/transformers/transformSnippets.test.js @@ -6,82 +6,76 @@ import { describe('transformSnippetIndex', () => { it('transforms the snippet index', () => { - const edges = [ + const snippets = [ { - node: { - title: 'a', - expertise: 'Intermediate', - tags: { - primary: 'array', - }, - language: { - long: 'lang', - short: 'l', - }, - html: { - description: 'desc ', - }, - slug: '/a', - searchTokens: '', - irrelevantStuff: 'data', + title: 'a', + expertise: 'Intermediate', + tags: { + primary: 'array', }, + language: { + long: 'lang', + short: 'l', + }, + html: { + description: 'desc ', + }, + slug: '/a', + searchTokens: '', + irrelevantStuff: 'data', }, ]; - const result = transformSnippetIndex(edges); - expect(result[0].title).toBe(edges[0].node.title); + const result = transformSnippetIndex(snippets); + expect(result[0].title).toBe(snippets[0].title); expect(result[0].expertise).toBe('Intermediate'); expect(result[0].primaryTag).toBe('Array'); - expect(result[0].language).toBe(edges[0].node.language.long); - expect(result[0].description).toBe(edges[0].node.html.description.trim()); - expect(result[0].url).toBe(edges[0].node.slug); + expect(result[0].language).toBe(snippets[0].language.long); + expect(result[0].description).toBe(snippets[0].html.description.trim()); + expect(result[0].url).toBe(snippets[0].slug); expect(result[0].searchTokens).toBe(undefined); expect(result[0].irrelevantStuff).toBe(undefined); }); it('handles an empty language appropriately', () => { - const edges = [ + const snippets = [ { - node: { - title: 'a', - expertise: 'Intermediate', - tags: { - primary: 'array', - }, - language: {}, - html: { - description: 'desc ', - }, - slug: '/a', - searchTokens: '', - irrelevantStuff: 'data', + title: 'a', + expertise: 'Intermediate', + tags: { + primary: 'array', }, + language: {}, + html: { + description: 'desc ', + }, + slug: '/a', + searchTokens: '', + irrelevantStuff: 'data', }, ]; - const result = transformSnippetIndex(edges); + const result = transformSnippetIndex(snippets); expect(result[0].language).toBe(undefined); }); it('returns search tokens when explicitly told to do so', () => { - const edges = [ + const snippets = [ { - node: { - title: 'a', - expertise: 'Intermediate', - tags: { - primary: 'array', - }, - language: {}, - html: { - description: 'desc ', - }, - slug: '/a', - searchTokens: 'my tokens', - irrelevantStuff: 'data', + title: 'a', + expertise: 'Intermediate', + tags: { + primary: 'array', + }, + language: {}, + html: { + description: 'desc ', }, + slug: '/a', + searchTokens: 'my tokens', + irrelevantStuff: 'data', }, ]; - const result = transformSnippetIndex(edges, true); - expect(result[0].searchTokens).toBe(edges[0].node.searchTokens); + const result = transformSnippetIndex(snippets, true); + expect(result[0].searchTokens).toBe(snippets[0].searchTokens); }); }); diff --git a/src/yild/extractSnippets/postProcess.js b/src/yild/extractSnippets/postProcess.js index 8c9a616ce..59454becf 100644 --- a/src/yild/extractSnippets/postProcess.js +++ b/src/yild/extractSnippets/postProcess.js @@ -90,9 +90,7 @@ const compileListingPagesWithOrderOptions = ( const compileListingData = (snippetIndex, listingMetas) => { // 1. Create listing pages for the main listing: // Tranform and chunk data for popularity, alphabetical and expertise ordering - const transformedIndex = transformSnippetIndex( - snippetIndex.map(v => ( { node: v })) - ); + const transformedIndex = transformSnippetIndex(snippetIndex); const popularChunks = chunk(transformedIndex, CARDS_PER_PAGE); const alphabeticalChunks = chunk(transformedIndex.sort((a, b) => a.title.localeCompare(b.title) @@ -143,9 +141,7 @@ const compileListingData = (snippetIndex, listingMetas) => { s.slug.startsWith(`${slugPrefix}`) || (s.blog && s.tags.all.find(t => t.toLowerCase() === snippetIndexName.toLowerCase())) ); - const transformedSlugChunks = transformSnippetIndex( - snippetIndexSlugData.map(v => ( { node: v })) - ); + const transformedSlugChunks = transformSnippetIndex(snippetIndexSlugData); const popularSlugChunks = chunk(transformedSlugChunks, CARDS_PER_PAGE); const alphabeticalSlugChunks = chunk(transformedSlugChunks.sort((a, b) => a.title.localeCompare(b.title) @@ -202,9 +198,7 @@ const compileListingData = (snippetIndex, listingMetas) => { s.tags.all.find(t => t.toLowerCase() === tagPrefix.toLowerCase()) ) ); - const transformedTagChunks = transformSnippetIndex( - snippetIndexTagData.map(v => ( { node: v })) - ); + const transformedTagChunks = transformSnippetIndex(snippetIndexTagData); const popularTagChunks = chunk(transformedTagChunks, CARDS_PER_PAGE); const alphabeticalTagChunks = chunk(transformedTagChunks.sort((a, b) => a.title.localeCompare(b.title) @@ -266,7 +260,7 @@ const postProcess = (allData, allSnippetData, parentLog) => { for (let snippet of data.data) { const recommendedSnippets = transformSnippetIndex( - recommendationEngine(allSnippetData, snippet).map(v => ( { node: v })) + recommendationEngine(allSnippetData, snippet) ); const outDir = `${contentOutDir}/${snippet.slug.slice(1)}`; diff --git a/src/yild/serveSnippets/index.js b/src/yild/serveSnippets/index.js index 3d0030c1f..fb10cbb6f 100644 --- a/src/yild/serveSnippets/index.js +++ b/src/yild/serveSnippets/index.js @@ -72,7 +72,7 @@ const serveSnippets = () => { case 1: res.writeHead(200, { 'Content-Type': 'application/json' }); res.end( - JSON.stringify(transformSnippetIndex(data.map(s => ({ node: s })))) + JSON.stringify(transformSnippetIndex(data)) ); break; case 3: { From 0fdceebe95ecf752ec0641fab1a322356a2198c1 Mon Sep 17 00:00:00 2001 From: Chalarangelo Date: Wed, 26 Aug 2020 22:49:22 +0300 Subject: [PATCH 16/39] Move parsers into gatsby directory Combine remaining parsers into a single one, move into gatsby directory for ease of importing. --- content/sources/30blog | 2 +- gatsby-node.js | 16 ++++---- src/build/parsers/index.js | 7 ---- src/build/parsers/parseRequirables.js | 35 ---------------- src/build/parsers/parseTemplates.js | 14 ------- src/build/parsers/parseTemplates.test.js | 26 ------------ src/gatsby/index.js | 2 + src/gatsby/parseRequirements.js | 41 +++++++++++++++++++ .../parseRequirements.test.js} | 24 ++++++++++- 9 files changed, 73 insertions(+), 94 deletions(-) delete mode 100644 src/build/parsers/index.js delete mode 100644 src/build/parsers/parseRequirables.js delete mode 100644 src/build/parsers/parseTemplates.js delete mode 100644 src/build/parsers/parseTemplates.test.js create mode 100644 src/gatsby/parseRequirements.js rename src/{build/parsers/parseRequirables.test.js => gatsby/parseRequirements.test.js} (77%) diff --git a/content/sources/30blog b/content/sources/30blog index a14b59e4e..adbf1fbb9 160000 --- a/content/sources/30blog +++ b/content/sources/30blog @@ -1 +1 @@ -Subproject commit a14b59e4e041538da4526d2501f5949ed22318a7 +Subproject commit adbf1fbb9892bb776c37d700525e9e4d47fae52e diff --git a/gatsby-node.js b/gatsby-node.js index 0bd31ffec..97a72760e 100644 --- a/gatsby-node.js +++ b/gatsby-node.js @@ -4,18 +4,16 @@ const env = require('./.build/env').default; const { createPages, onCreateWebpackConfig, + parseRequirements, } = require(`./src/gatsby`); -const { - parseRequirables, - parseTemplates, -} = require(`./src/build/parsers`); const paths = require(`./src/config/paths`); -const requirables = parseRequirables(paths.contentPath); -console.log(`${green('success')} parse requirables`); - -const templates = parseTemplates(env === 'DEVELOPMENT' ? paths.devTemplates : paths.templates, paths.templatesPath); -console.log(`${green('success')} parse templates`); +const { requirables, templates} = parseRequirements( + env === 'DEVELOPMENT' ? paths.devTemplates : paths.templates, + paths.templatesPath, + paths.contentPath +); +console.log(`${green('success')} parse requirements`); exports.createPages = createPages(templates, requirables); diff --git a/src/build/parsers/index.js b/src/build/parsers/index.js deleted file mode 100644 index d981e4928..000000000 --- a/src/build/parsers/index.js +++ /dev/null @@ -1,7 +0,0 @@ -import parseRequirables from './parseRequirables'; -import parseTemplates from './parseTemplates'; - -export { - parseRequirables, - parseTemplates -}; diff --git a/src/build/parsers/parseRequirables.js b/src/build/parsers/parseRequirables.js deleted file mode 100644 index 2b7e079c1..000000000 --- a/src/build/parsers/parseRequirables.js +++ /dev/null @@ -1,35 +0,0 @@ -import glob from 'glob'; -import path from 'path'; - -/** - * Combines the given data JSONs, using the data files - * of the content, returning an array of objects from the files. - * @param {string} contentDirPath - The path to the content directory. - */ -const parseRequirables = contentDirPath => { - // Load configurations - let requirables = []; - glob - .sync(`${contentDirPath}/**/index.json`) - .forEach( file => { - const dir = file.slice(0, file.lastIndexOf('/')); - const reqData = glob - .sync(`${dir}/!(index).json`) - .reduce((acc, dataFile) => { - const data = require(path.resolve(dataFile)); - acc.context = { - ...acc.context, - ...data, - }; - return acc; - }, - { - ...require(path.resolve(file)), - context: {}, - }); - requirables.push(reqData); - }); - return requirables; -}; - -export default parseRequirables; diff --git a/src/build/parsers/parseTemplates.js b/src/build/parsers/parseTemplates.js deleted file mode 100644 index 0666feb0e..000000000 --- a/src/build/parsers/parseTemplates.js +++ /dev/null @@ -1,14 +0,0 @@ -const path = require(`path`); - -/** - * Combines the given list of templates into an object. - * @param {array} templates - An array of templates. - * @param {string} templatesDir - The path to the template directory. - */ -const parseTemplates = (templates, templatesDir) => - templates.reduce((acc, tmpl) => { - acc[tmpl.name] = path.resolve(`${templatesDir}/${tmpl.path}`); - return acc; - }, {}); - -export default parseTemplates; diff --git a/src/build/parsers/parseTemplates.test.js b/src/build/parsers/parseTemplates.test.js deleted file mode 100644 index b3a7475f6..000000000 --- a/src/build/parsers/parseTemplates.test.js +++ /dev/null @@ -1,26 +0,0 @@ -import parseTemplates from './parseTemplates'; - -import path from 'path'; -jest.mock('path'); - -path.resolve.mockImplementation(jest.fn(f => f)); - -const templates = [ - { - 'name': 'SnippetPage', - 'path': 'snippetPage/index.jsx', - }, - { - 'name': 'SearchPage', - 'path': 'searchPage/index.jsx', - }, -]; - -describe('parseTemplates', () => { - it('returns an object with the appropriate structure and data', () => { - expect(parseTemplates(templates, 'my-templates-dir')).toEqual({ - 'SnippetPage': 'my-templates-dir/snippetPage/index.jsx', - 'SearchPage': 'my-templates-dir/searchPage/index.jsx', - }); - }); -}); diff --git a/src/gatsby/index.js b/src/gatsby/index.js index 7af14bea1..b69f5b2c8 100644 --- a/src/gatsby/index.js +++ b/src/gatsby/index.js @@ -1,7 +1,9 @@ +import parseRequirements from './parseRequirements'; import createPages from './createPages'; import onCreateWebpackConfig from './onCreateWebpackConfig'; export { + parseRequirements, createPages, onCreateWebpackConfig, }; diff --git a/src/gatsby/parseRequirements.js b/src/gatsby/parseRequirements.js new file mode 100644 index 000000000..bd8cf6e01 --- /dev/null +++ b/src/gatsby/parseRequirements.js @@ -0,0 +1,41 @@ +import glob from 'glob'; +import path from 'path'; + +/** + * Combines the given data JSONs, using the data files + * of the content, returning an array of objects from the files. + * @param {string} contentDir - The path to the content directory. + */ +export const parseRequirables = contentDir => + glob.sync(`${contentDir}/**/index.json`).map(file => + glob.sync(`${file.slice(0, file.lastIndexOf('/'))}/!(index).json`) + .reduce((acc, dataFile) => { + acc.context = { ...acc.context, ...require(path.resolve(dataFile)) }; + return acc; + }, { ...require(path.resolve(file)), context: {} })); + +/** + * Combines the given list of templates into an object. + * @param {array} templates - An array of templates. + * @param {string} templatesDir - The path to the template directory. + */ +export const parseTemplates = (templates, templatesDir) => + templates.reduce((acc, tmpl) => { + acc[tmpl.name] = path.resolve(`${templatesDir}/${tmpl.path}`); + return acc; + }, {}); + +/* istanbul ignore next */ +/** + * Returns an object containing templates and requirables created by + * combining the given template and content parameters. + * @param {array} templates - An array of templates. + * @param {string} templatesDir - The path to the template directory. + * @param {string} contentDir - The path to the content directory. + */ +const parseRequirements = (templates, templatesDir, contentDir) => ({ + templates: parseTemplates(templates, templatesDir), + requirables: parseRequirables(contentDir), +}); + +export default parseRequirements; diff --git a/src/build/parsers/parseRequirables.test.js b/src/gatsby/parseRequirements.test.js similarity index 77% rename from src/build/parsers/parseRequirables.test.js rename to src/gatsby/parseRequirements.test.js index d5464fd42..1f62b483f 100644 --- a/src/build/parsers/parseRequirables.test.js +++ b/src/gatsby/parseRequirements.test.js @@ -1,4 +1,4 @@ -import parseRequirables from './parseRequirables'; +import { parseRequirables, parseTemplates } from './parseRequirements'; import glob from 'glob'; import path from 'path'; @@ -6,6 +6,18 @@ import path from 'path'; jest.mock('glob'); jest.mock('path'); + +const templates = [ + { + 'name': 'SnippetPage', + 'path': 'snippetPage/index.jsx', + }, + { + 'name': 'SearchPage', + 'path': 'searchPage/index.jsx', + }, +]; + const mockRequirables = { 'stdRequirable': { meta: { @@ -66,10 +78,18 @@ jest.mock('ltdRequirable.json', describe('parseRequirables', () => { it('returns the array of the resulting requirables', () => { - console.log(); expect(parseRequirables('my-content-dir')).toEqual([ {...mockRequirables['stdRequirable'], context: mockRequirables['stdRequirable'] }, {...mockRequirables['ltdRequirable'], context: mockRequirables['ltdRequirable']}, ]); }); }); + +describe('parseTemplates', () => { + it('returns an object with the appropriate structure and data', () => { + expect(parseTemplates(templates, 'my-templates-dir')).toEqual({ + 'SnippetPage': 'my-templates-dir/snippetPage/index.jsx', + 'SearchPage': 'my-templates-dir/searchPage/index.jsx', + }); + }); +}); From 08caa34904b52b9f6d1fa717191fad79f471cf48 Mon Sep 17 00:00:00 2001 From: Chalarangelo Date: Wed, 26 Aug 2020 22:58:05 +0300 Subject: [PATCH 17/39] Simplify parseRequirements API Minimize logic in gatsby-node. --- gatsby-node.js | 10 +--------- src/gatsby/parseRequirements.js | 19 +++++++++++-------- 2 files changed, 12 insertions(+), 17 deletions(-) diff --git a/gatsby-node.js b/gatsby-node.js index 97a72760e..8a3df2bc5 100644 --- a/gatsby-node.js +++ b/gatsby-node.js @@ -1,20 +1,12 @@ const { green } = require('chalk'); -const env = require('./.build/env').default; - const { createPages, onCreateWebpackConfig, parseRequirements, } = require(`./src/gatsby`); -const paths = require(`./src/config/paths`); -const { requirables, templates} = parseRequirements( - env === 'DEVELOPMENT' ? paths.devTemplates : paths.templates, - paths.templatesPath, - paths.contentPath -); +const { requirables, templates} = parseRequirements(); console.log(`${green('success')} parse requirements`); exports.createPages = createPages(templates, requirables); - exports.onCreateWebpackConfig = onCreateWebpackConfig; diff --git a/src/gatsby/parseRequirements.js b/src/gatsby/parseRequirements.js index bd8cf6e01..55ee63e80 100644 --- a/src/gatsby/parseRequirements.js +++ b/src/gatsby/parseRequirements.js @@ -1,5 +1,9 @@ import glob from 'glob'; import path from 'path'; +import paths from 'config/paths'; + +/* istanbul ignore next */ +const isDevelopment = process.env.NODE_ENV.toLowerCase() === 'development'; /** * Combines the given data JSONs, using the data files @@ -27,15 +31,14 @@ export const parseTemplates = (templates, templatesDir) => /* istanbul ignore next */ /** - * Returns an object containing templates and requirables created by - * combining the given template and content parameters. - * @param {array} templates - An array of templates. - * @param {string} templatesDir - The path to the template directory. - * @param {string} contentDir - The path to the content directory. + * Returns an object containing templates and requirables. */ -const parseRequirements = (templates, templatesDir, contentDir) => ({ - templates: parseTemplates(templates, templatesDir), - requirables: parseRequirables(contentDir), +const parseRequirements = () => ({ + templates: parseTemplates( + isDevelopment ? paths.devTemplates : paths.templates, + paths.templatesPath + ), + requirables: parseRequirables(paths.contentPath), }); export default parseRequirements; From 8be32e8a05bb1517800e64356b2a9dd9984298f5 Mon Sep 17 00:00:00 2001 From: Chalarangelo Date: Wed, 26 Aug 2020 23:33:33 +0300 Subject: [PATCH 18/39] Add search page to extracted data --- src/yild/extractSnippets/index.js | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/yild/extractSnippets/index.js b/src/yild/extractSnippets/index.js index ed35aab8e..d6b885f65 100644 --- a/src/yild/extractSnippets/index.js +++ b/src/yild/extractSnippets/index.js @@ -3,6 +3,7 @@ import { initAction, loadContentConfigs } from '../core'; import extract from './extract'; import postProcess from './postProcess'; import literals from 'lang/en'; +import { transformSnippetIndex } from 'build/transformers'; const extractSnippets = async() => { const [boundLog, , inPath, outPath] = initAction('extractSnippets', [ @@ -28,7 +29,9 @@ const extractSnippets = async() => { await Promise .all(extract(configs, langData, boundLog)) .then(res => { allData = res; }); - const allSnippetData = allData.reduce((acc, r) => [...acc, ...r.data.data], []); + const allSnippetData = allData + .reduce((acc, r) => [...acc, ...r.data.data], []) + .sort((a, b) => b.ranking - a.ranking); boundLog(`Extracted data for ${allSnippetData.length} snippets`, 'success'); boundLog('Post-processing snippet data', 'info'); @@ -62,6 +65,16 @@ const extractSnippets = async() => { template: 'SettingsPage', priority: 0.01, }, + { + slug: '/search', + context: { + searchIndex: transformSnippetIndex(allSnippetData, true), + recommendedSnippets: transformSnippetIndex(allSnippetData.slice(0, 3)), + pageDescription: literals.search.pageDescription(allSnippetData.length), + }, + template: 'SearchPage', + priority: 0.25, + }, ].forEach(p => { const outDir = `${outPath}${p.slug}`; fs.ensureDirSync(outDir); From c03dbe420e8d70a7f007fc3fd083b9217f5b26bf Mon Sep 17 00:00:00 2001 From: Chalarangelo Date: Wed, 26 Aug 2020 23:41:22 +0300 Subject: [PATCH 19/39] Introduce .env files Used for environment variables. More: https://www.gatsbyjs.com/docs/environment-variables --- .env.development | 1 + .env.production | 1 + 2 files changed, 2 insertions(+) create mode 100644 .env.development create mode 100644 .env.production diff --git a/.env.development b/.env.development new file mode 100644 index 000000000..d3ccabf50 --- /dev/null +++ b/.env.development @@ -0,0 +1 @@ +ENV=development diff --git a/.env.production b/.env.production new file mode 100644 index 000000000..4fdbe6fb6 --- /dev/null +++ b/.env.production @@ -0,0 +1 @@ +ENV=production From d3f2fe2c873dbd0c7142700b71182c3392c1e890 Mon Sep 17 00:00:00 2001 From: Chalarangelo Date: Wed, 26 Aug 2020 23:42:03 +0300 Subject: [PATCH 20/39] Deprecate env file Use .env files, instead. Deprecate yild preparation code. --- package.json | 10 ++--- src/components/organisms/shell/index.jsx | 3 +- src/components/organisms/shell/index.test.jsx | 2 - src/yild/core/actions.js | 10 ----- src/yild/index.js | 5 +-- src/yild/prepareEnv/index.js | 42 ------------------- 6 files changed, 8 insertions(+), 64 deletions(-) delete mode 100644 src/yild/prepareEnv/index.js diff --git a/package.json b/package.json index 8df0d3f27..e2f07df9d 100644 --- a/package.json +++ b/package.json @@ -70,13 +70,13 @@ "scripts": { "extract-snippets": "NODE_PATH=src npx --node-arg '-r esm' ./src/jobs/yild.js -e", "watch-snippets": "npm-watch extract-snippets", - "prepare-assets": "NODE_PATH=src npx --node-arg '-r esm' ./src/jobs/yild.js -e -n=DEVELOPMENT", + "prepare-assets": "NODE_PATH=src NODE_ENV=development npx --node-arg '-r esm' ./src/jobs/yild.js -e ", "watch-assets": "npm-watch prepare-assets", - "serve-snippets": "NODE_PATH=src npx --node-arg '-r esm' ./src/jobs/yild.js -n=DEVELOPMENT -s", + "serve-snippets": "NODE_PATH=src NODE_ENV=development npx --node-arg '-r esm' ./src/jobs/yild.js -s", "yild": "NODE_PATH=src npx --node-arg '-r esm' ./src/jobs/yild.js", - "prebuild": "NODE_PATH=src npx --node-arg '-r esm' ./src/jobs/yild.js -u -a -e -i -n=PRODUCTION -c", - "predevelop": "NODE_PATH=src npx --node-arg '-r esm' ./src/jobs/yild.js -n=DEVELOPMENT -c", - "pretest": "NODE_PATH=src npx --node-arg '-r esm' ./src/jobs/yild.js -n=DEVELOPMENT -c", + "prebuild": "NODE_PATH=src NODE_ENV=production npx --node-arg '-r esm' ./src/jobs/yild.js -u -a -e -i -c", + "predevelop": "NODE_PATH=src NODE_ENV=development npx --node-arg '-r esm' ./src/jobs/yild.js -c", + "pretest": "NODE_PATH=src NODE_ENV=test npx --node-arg '-r esm' ./src/jobs/yild.js -c", "build": "NODE_PATH=src npx --node-arg '-r esm' gatsby build", "develop": "NODE_PATH=src npx --node-arg '-r esm' gatsby develop -p 8000", "debug": "NODE_PATH=src npx --node-arg '-r esm --nolazy --inspect-brk' node_modules/.bin/gatsby develop", diff --git a/src/components/organisms/shell/index.jsx b/src/components/organisms/shell/index.jsx index e8507732e..f807723e3 100644 --- a/src/components/organisms/shell/index.jsx +++ b/src/components/organisms/shell/index.jsx @@ -6,7 +6,6 @@ import Footer from 'components/molecules/footer'; import CookieConsentPopup from 'components/molecules/cookieConsentPopup'; import literals from 'lang/en/client/common'; import { combineClassNames } from 'utils'; -import env from '../../../../.build/env'; const propTypes = { children: PropTypes.oneOfType([ @@ -64,7 +63,7 @@ const Shell = ({