From 1e4665f657cb789499a235389b4afb1297ffc0ee Mon Sep 17 00:00:00 2001 From: GarboMuffin Date: Mon, 3 Jul 2023 19:30:23 -0500 Subject: [PATCH 1/5] Validate that SVGs do not contain --- development/builder.js | 48 +++++++++++++++++++++++++++++++++++------ development/colors.js | 9 ++++++++ development/validate.js | 19 +++++++++++++++- 3 files changed, 69 insertions(+), 7 deletions(-) create mode 100644 development/colors.js diff --git a/development/builder.js b/development/builder.js index 757cf7e492..5f1bf1f686 100644 --- a/development/builder.js +++ b/development/builder.js @@ -7,8 +7,6 @@ const compatibilityAliases = require('./compatibility-aliases'); * @typedef {'development'|'production'|'desktop'} Mode */ -const IMAGE_EXTENSIONS = ['png', 'jpg', 'svg']; - /** * Recursively read a directory. * @param {string} directory @@ -52,6 +50,10 @@ class DiskFile { read () { return fs.readFileSync(this.path); } + + validate () { + // no-op + } } class ExtensionFile extends DiskFile { @@ -63,10 +65,12 @@ class ExtensionFile extends DiskFile { // TODO: we can add some code to eg. show a message when the extension was modified on disk? } -class HTMLFile { +class HTMLFile extends DiskFile { constructor (path, data) { - this.path = path; + super(path); this.data = data; + // force development server to use read() + this.getDiskPath = null; } getType () { @@ -78,6 +82,20 @@ class HTMLFile { } } +class SVGFile extends DiskFile { + validate () { + const contents = this.read(); + if (contents.includes(' elements -- please convert the text to a path. This ensures it will display correctly on all devices.'); + } + } +} + +const IMAGE_FORMATS = new Map(); +IMAGE_FORMATS.set('.png', DiskFile); +IMAGE_FORMATS.set('.jpg', DiskFile); +IMAGE_FORMATS.set('.svg', SVGFile); + class Build { constructor () { this.files = {}; @@ -134,14 +152,16 @@ class Builder { const images = {}; for (const [imageFilename, path] of readDirectory(this.imagesRoot)) { - if (!IMAGE_EXTENSIONS.some(extension => imageFilename.endsWith(`.${extension}`))) { + const extension = pathUtil.extname(imageFilename); + const ImageFileClass = IMAGE_FORMATS.get(extension); + if (!ImageFileClass) { continue; } const extensionId = imageFilename.split('.')[0]; if (extensionId !== 'unknown') { images[extensionId] = imageFilename; } - build.files[`/images/${imageFilename}`] = new DiskFile(path); + build.files[`/images/${imageFilename}`] = new ImageFileClass(path); } const extensionFiles = []; @@ -212,6 +232,22 @@ class Builder { callback(this.tryBuild()); }); } + + validate () { + const errors = []; + const build = this.build(); + for (const [fileName, file] of Object.entries(build.files)) { + try { + file.validate(); + } catch (e) { + errors.push({ + fileName, + error: e + }); + } + } + return errors; + } } module.exports = Builder; diff --git a/development/colors.js b/development/colors.js new file mode 100644 index 0000000000..6dc21194d1 --- /dev/null +++ b/development/colors.js @@ -0,0 +1,9 @@ +const enableColor = !process.env.NO_COLOR; +const color = (i) => enableColor ? i : ''; + +module.exports = { + RESET: color('\x1b[0m'), + BOLD: color('\x1b[1m'), + RED: color('\x1b[31m'), + GREEN: color('\x1b[32m') +}; diff --git a/development/validate.js b/development/validate.js index 79f37a5eee..e9386baebe 100644 --- a/development/validate.js +++ b/development/validate.js @@ -1 +1,18 @@ -require('./build-production'); +const Builder = require('./builder'); +const Colors = require('./colors'); + +const builder = new Builder('production'); +const errors = builder.validate(); + +if (errors.length === 0) { + console.log(`${Colors.GREEN}${Colors.BOLD}Validation checks passed.${Colors.RESET}`); + process.exit(0); +} else { + console.error(`${Colors.RED}${Colors.BOLD}${errors.length} ${errors.length === 1 ? 'file' : 'files'} failed validation.${Colors.RESET}`); + console.error(''); + for (const {fileName, error} of errors) { + console.error(`${Colors.BOLD}${fileName}${Colors.RESET}: ${error}`); + } + console.error(``); + process.exit(1); +} From 7402d755786238877f7865fce3b1befa3aff9952 Mon Sep 17 00:00:00 2001 From: GarboMuffin Date: Mon, 3 Jul 2023 19:34:06 -0500 Subject: [PATCH 2/5] Validate that images are exactly 2:1 aspect ratio --- development/builder.js | 20 +++++++++++++++++--- package-lock.json | 20 ++++++++++++++++---- package.json | 3 ++- 3 files changed, 35 insertions(+), 8 deletions(-) diff --git a/development/builder.js b/development/builder.js index 5f1bf1f686..9a2f025994 100644 --- a/development/builder.js +++ b/development/builder.js @@ -1,5 +1,6 @@ const fs = require('fs'); const pathUtil = require('path'); +const sizeOfImage = require('image-size'); const renderTemplate = require('./render-template'); const compatibilityAliases = require('./compatibility-aliases'); @@ -82,18 +83,31 @@ class HTMLFile extends DiskFile { } } -class SVGFile extends DiskFile { +class ImageFile extends DiskFile { + validate () { + const contents = this.read(); + const {width, height} = sizeOfImage(contents); + const aspectRatio = width / height; + if (aspectRatio !== 2) { + throw new Error(`Aspect ratio must be exactly 2, but found ${aspectRatio.toFixed(4)} (${width}x${height})`); + } + } +} + +class SVGFile extends ImageFile { validate () { const contents = this.read(); if (contents.includes(' elements -- please convert the text to a path. This ensures it will display correctly on all devices.'); } + + super.validate(); } } const IMAGE_FORMATS = new Map(); -IMAGE_FORMATS.set('.png', DiskFile); -IMAGE_FORMATS.set('.jpg', DiskFile); +IMAGE_FORMATS.set('.png', ImageFile); +IMAGE_FORMATS.set('.jpg', ImageFile); IMAGE_FORMATS.set('.svg', SVGFile); class Build { diff --git a/package-lock.json b/package-lock.json index 120c844694..4375bd2a51 100644 --- a/package-lock.json +++ b/package-lock.json @@ -125,10 +125,6 @@ "fastq": "^1.6.0" } }, - "@turbowarp/types": { - "version": "git+https://github.com/TurboWarp/types-tw.git#59febbb5494a25898defda095ebe306a747974dd", - "from": "git+https://github.com/TurboWarp/types-tw.git#59febbb5494a25898defda095ebe306a747974dd" - }, "accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -806,6 +802,14 @@ "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", "dev": true }, + "image-size": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-1.0.2.tgz", + "integrity": "sha512-xfOoWjceHntRb3qFCrh5ZFORYH8XCdYpASltMhZ/Q0KZiOwjdE/Yl2QCiWdwD+lygV5bMCvauzgu5PxBX/Yerg==", + "requires": { + "queue": "6.0.2" + } + }, "import-fresh": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", @@ -1124,6 +1128,14 @@ "side-channel": "^1.0.4" } }, + "queue": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz", + "integrity": "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==", + "requires": { + "inherits": "~2.0.3" + } + }, "queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", diff --git a/package.json b/package.json index 562be34f1c..faffa558b0 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,8 @@ "@turbowarp/types": "git+https://github.com/TurboWarp/types-tw.git#tw", "chokidar": "^3.5.3", "ejs": "^3.1.9", - "express": "^4.18.2" + "express": "^4.18.2", + "image-size": "^1.0.2" }, "devDependencies": { "eslint": "^8.43.0" From 1d2874b11765ebafb7c90f75c3fcb4051dd82730 Mon Sep 17 00:00:00 2001 From: GarboMuffin Date: Mon, 3 Jul 2023 19:42:44 -0500 Subject: [PATCH 3/5] Update or remove images to pass validation /images/clouddata-ping.svg: Error: Aspect ratio must be exactly 2, but found 2.0127 (159x79) /images/godslayerakp/http.png: Error: Aspect ratio must be exactly 2, but found 1.6129 (600x372) /images/utilities.svg: Error: Aspect ratio must be exactly 2, but found 2.0127 (159x79) --- images/clouddata-ping.svg | 2 +- images/godslayerakp/http.png | Bin 27809 -> 0 bytes images/utilities.svg | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) delete mode 100644 images/godslayerakp/http.png diff --git a/images/clouddata-ping.svg b/images/clouddata-ping.svg index 274b7585c3..6eae7df964 100644 --- a/images/clouddata-ping.svg +++ b/images/clouddata-ping.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/godslayerakp/http.png b/images/godslayerakp/http.png deleted file mode 100644 index cc0d60026e8d9ec0856470dd863603c4b369ec9c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 27809 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 z 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 SH;#Nkz)w?MSFJ(?8~J}s7oy?- diff --git a/images/utilities.svg b/images/utilities.svg index aeeda95117..ab0ce25a11 100644 --- a/images/utilities.svg +++ b/images/utilities.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file From 4303a294d3b421ce10904c41caf873d654b76615 Mon Sep 17 00:00:00 2001 From: GarboMuffin Date: Mon, 3 Jul 2023 19:44:31 -0500 Subject: [PATCH 4/5] Update godslayerakp/http description --- website/index.ejs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/website/index.ejs b/website/index.ejs index 653cd4d146..1e620f2d0d 100644 --- a/website/index.ejs +++ b/website/index.ejs @@ -688,8 +688,8 @@
<%- banner('godslayerakp/http') %> -

http/https

-

Extension HTTP extension. Created by RedMan13.

+

HTTP

+

Comprehensive extension for interacting with external websites. Created by RedMan13.

From 8faec3e7ac2f461e0d7a2c746d8150906a4dbfe4 Mon Sep 17 00:00:00 2001 From: GarboMuffin Date: Mon, 3 Jul 2023 19:46:16 -0500 Subject: [PATCH 5/5] Fix package-lock.json --- package-lock.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/package-lock.json b/package-lock.json index 4375bd2a51..7362fb5480 100644 --- a/package-lock.json +++ b/package-lock.json @@ -125,6 +125,10 @@ "fastq": "^1.6.0" } }, + "@turbowarp/types": { + "version": "git+https://github.com/TurboWarp/types-tw.git#59febbb5494a25898defda095ebe306a747974dd", + "from": "git+https://github.com/TurboWarp/types-tw.git#tw" + }, "accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",