diff --git a/app.js b/app.js index e25e009..ae07a38 100644 --- a/app.js +++ b/app.js @@ -4,7 +4,7 @@ var path = require('path'); var cookieParser = require('cookie-parser'); var mLogger = require('morgan'); var logger = require('./config/winston'); -const helmet = require("helmet"); +const helmet = require('helmet'); var indexRouter = require('./routes/index'); var aboutRouter = require('./routes/about'); @@ -12,7 +12,8 @@ var contactRouter = require('./routes/contact'); var app = express(); -if (process.env.IS_DOCKER != 'true') app.set('trust proxy', 'loopback,uniquelocal'); +if (process.env.IS_DOCKER != 'true') + app.set('trust proxy', 'loopback,uniquelocal'); app.disable('x-powered-by'); // view engine setup @@ -20,26 +21,43 @@ app.set('views', path.join(__dirname, 'views')); app.set('view engine', 'pug'); if (process.env.NODE_ENV === 'production') { - app.use(mLogger("common", { "stream": logger.stream })); + app.use(mLogger('common', { stream: logger.stream })); } else { - app.use(mLogger('dev')); + app.use(mLogger('dev')); } app.use(helmet()); app.use( - helmet.contentSecurityPolicy({ - directives: { - defaultSrc: ["'self'"], - scriptSrc: ["'self'", "'unsafe-inline'", "'unsafe-eval'", "https://hcaptcha.com", "https://*.hcaptcha.com", "https://cdn.ravenjs.com/"], - imgSrc: ["'self'", "https://blog.pastel.codes", "https://static.ghost.org", "https://secure.gravatar.com"], - styleSrc: ["'self'", "'unsafe-inline'", "https://hcaptcha.com", "https://*.hcaptcha.com"], - fontSrc: ["'self'", "data:"], - frameSrc: ["https://hcaptcha.com", "https://*.hcaptcha.com"], - objectSrc: ["'none'"], - upgradeInsecureRequests: [], - }, - }) - ); + helmet.contentSecurityPolicy({ + directives: { + defaultSrc: ["'self'"], + scriptSrc: [ + "'self'", + "'unsafe-inline'", + "'unsafe-eval'", + 'https://hcaptcha.com', + 'https://*.hcaptcha.com', + 'https://cdn.ravenjs.com/', + ], + imgSrc: [ + "'self'", + 'https://blog.pastel.codes', + 'https://static.ghost.org', + 'https://secure.gravatar.com', + ], + styleSrc: [ + "'self'", + "'unsafe-inline'", + 'https://hcaptcha.com', + 'https://*.hcaptcha.com', + ], + fontSrc: ["'self'", 'data:'], + frameSrc: ['https://hcaptcha.com', 'https://*.hcaptcha.com'], + objectSrc: ["'none'"], + upgradeInsecureRequests: [], + }, + }) +); app.use(express.json()); app.use(express.urlencoded({ extended: false })); @@ -51,19 +69,19 @@ app.use('/about', aboutRouter); app.use('/contact', contactRouter); // catch 404 and forward to error handler -app.use(function(req, res, next) { - next(createError(404)); +app.use(function (req, res, next) { + next(createError(404)); }); // error handler -app.use(function(err, req, res, next) { - // set locals, only providing error in development - res.locals.message = err.message; - res.locals.error = req.app.get('env') === 'development' ? err : {}; +app.use(function (err, req, res, _next) { + // set locals, only providing error in development + res.locals.message = err.message; + res.locals.error = req.app.get('env') === 'development' ? err : {}; - // render the error page - res.status(err.status || 500); - res.render('error', { title: 'Error', description: "Error" }); + // render the error page + res.status(err.status || 500); + res.render('error', { title: 'Error', description: 'Error' }); }); module.exports = app; diff --git a/bin/www b/bin/www index 2a4ae56..416ed5e 100755 --- a/bin/www +++ b/bin/www @@ -35,19 +35,19 @@ server.on('listening', onListening); */ function normalizePort(val) { - var port = parseInt(val, 10); + var port = parseInt(val, 10); - if (isNaN(port)) { - // named pipe - return val; - } + if (isNaN(port)) { + // named pipe + return val; + } - if (port >= 0) { - // port number - return port; - } + if (port >= 0) { + // port number + return port; + } - return false; + return false; } /** @@ -55,27 +55,25 @@ function normalizePort(val) { */ function onError(error) { - if (error.syscall !== 'listen') { - throw error; - } + if (error.syscall !== 'listen') { + throw error; + } - var bind = typeof port === 'string' - ? 'Pipe ' + port - : 'Port ' + port; + var bind = typeof port === 'string' ? 'Pipe ' + port : 'Port ' + port; - // handle specific listen errors with friendly messages - switch (error.code) { - case 'EACCES': - console.error(bind + ' requires elevated privileges'); - process.exit(1); - break; - case 'EADDRINUSE': - console.error(bind + ' is already in use'); - process.exit(1); - break; - default: - throw error; - } + // handle specific listen errors with friendly messages + switch (error.code) { + case 'EACCES': + console.error(bind + ' requires elevated privileges'); + process.exit(1); + break; + case 'EADDRINUSE': + console.error(bind + ' is already in use'); + process.exit(1); + break; + default: + throw error; + } } /** @@ -83,9 +81,7 @@ function onError(error) { */ function onListening() { - var addr = server.address(); - var bind = typeof addr === 'string' - ? 'pipe ' + addr - : 'port ' + addr.port; - debug('Listening on ' + bind); + var addr = server.address(); + var bind = typeof addr === 'string' ? 'pipe ' + addr : 'port ' + addr.port; + debug('Listening on ' + bind); } diff --git a/config/winston.js b/config/winston.js index 5d865ca..fa9dc56 100644 --- a/config/winston.js +++ b/config/winston.js @@ -2,29 +2,29 @@ var winston = require('winston'); var appRoot = require('app-root-path'); var logger = new winston.createLogger({ - transports: [ - new winston.transports.File({ - level: 'info', - filename: `${appRoot}/logs/app.log`, - handleExceptions: true, - json: true, - maxsize: 5242880, //5MB - maxFiles: 5, - colorize: false - }), - new winston.transports.Console({ - level: 'debug', - handleExceptions: true, - json: false, - colorize: true - }) - ], - exitOnError: false + transports: [ + new winston.transports.File({ + level: 'info', + filename: `${appRoot}/logs/app.log`, + handleExceptions: true, + json: true, + maxsize: 5242880, //5MB + maxFiles: 5, + colorize: false, + }), + new winston.transports.Console({ + level: 'debug', + handleExceptions: true, + json: false, + colorize: true, + }), + ], + exitOnError: false, }); logger.stream = { - write: function(message, encoding){ - logger.info(message); - } + write: function (message, _encoding) { + logger.info(message); + }, }; -module.exports = logger \ No newline at end of file +module.exports = logger; diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 0000000..cfe3839 --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,20 @@ +import globals from 'globals'; +import pluginJs from '@eslint/js'; + +export default [ + { files: ['**/*.js'], languageOptions: { sourceType: 'commonjs' } }, + { languageOptions: { globals: { ...globals.browser, ...globals.node } } }, + pluginJs.configs.recommended, + { + rules: { + 'no-unused-vars': [ + 'error', + { + argsIgnorePattern: '^_', + varsIgnorePattern: '^_', + caughtErrorsIgnorePattern: '^_', + }, + ], + }, + }, +]; diff --git a/package-lock.json b/package-lock.json index 4e33d45..faddbff 100644 --- a/package-lock.json +++ b/package-lock.json @@ -28,8 +28,10 @@ "winston": "^3.3.3" }, "devDependencies": { + "@eslint/js": "^9.1.1", "eslint": "^9.1.1", "eslint-config-prettier": "^9.1.0", + "globals": "^15.1.0", "husky": "^9.0.11", "lint-staged": "^15.2.2", "prettier": "^3.2.5", @@ -217,6 +219,18 @@ } } }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@eslint/eslintrc/node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -2118,9 +2132,9 @@ } }, "node_modules/globals": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", - "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.1.0.tgz", + "integrity": "sha512-926gJqg+4mkxwYKiFvoomM4J0kWESfk3qfTvRL2/oc/tK/eTDBbrfcKnSa2KtfdxB5onoL7D3A3qIHQFpd4+UA==", "dev": true, "engines": { "node": ">=18" @@ -5212,6 +5226,12 @@ "ms": "2.1.2" } }, + "globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true + }, "strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -6605,9 +6625,9 @@ } }, "globals": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", - "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.1.0.tgz", + "integrity": "sha512-926gJqg+4mkxwYKiFvoomM4J0kWESfk3qfTvRL2/oc/tK/eTDBbrfcKnSa2KtfdxB5onoL7D3A3qIHQFpd4+UA==", "dev": true }, "globby": { diff --git a/package.json b/package.json index 2215410..173ff6d 100644 --- a/package.json +++ b/package.json @@ -41,8 +41,10 @@ "winston": "^3.3.3" }, "devDependencies": { + "@eslint/js": "^9.1.1", "eslint": "^9.1.1", "eslint-config-prettier": "^9.1.0", + "globals": "^15.1.0", "husky": "^9.0.11", "lint-staged": "^15.2.2", "prettier": "^3.2.5", diff --git a/postcss.config.js b/postcss.config.js index a8dc3e9..3ea9307 100644 --- a/postcss.config.js +++ b/postcss.config.js @@ -1,6 +1,3 @@ module.exports = { - plugins: [ - require('tailwindcss'), - require('autoprefixer') - ] -} \ No newline at end of file + plugins: [require('tailwindcss'), require('autoprefixer')], +}; diff --git a/public/stylesheets/old-style.sass b/public/stylesheets/old-style.sass index fed903f..e377c19 100644 --- a/public/stylesheets/old-style.sass +++ b/public/stylesheets/old-style.sass @@ -3,293 +3,289 @@ $black: #002234 $green: #CDE7B0 @font-face - font-family: 'Titling Gothic FB' - src: url("../fonts/TITLINGGOTHICFB-WIDE.OTF") format('opentype') + font-family: 'Titling Gothic FB' + src: url("../fonts/TITLINGGOTHICFB-WIDE.OTF") format('opentype') @font-face - font-family: 'Gilroy' - src: url("../fonts/Gilroy-ExtraBold.otf") format('opentype') + font-family: 'Gilroy' + src: url("../fonts/Gilroy-ExtraBold.otf") format('opentype') @font-face - font-family: 'Apercu Mono' - src: url("../fonts/ApercuMono.ttf") format('truetype') + font-family: 'Apercu Mono' + src: url("../fonts/ApercuMono.ttf") format('truetype') html, body - width: 100% - height: 100% + width: 100% + height: 100% body - background-color: $black - color: $pink + background-color: $black + color: $pink h1 - font-family: "Gilroy", sans-serif + font-family: "Gilroy", sans-serif h2 - font-weight: bold - font-family: "Apercu Mono", monospace + font-weight: bold + font-family: "Apercu Mono", monospace p, label, input, textarea - font-family: "Apercu Mono", monospace + font-family: "Apercu Mono", monospace label - font-size: 3vh + font-size: 3vh a:hover - color: $green + color: $green article - min-height: 100% - display: grid - grid-template-rows: auto 1fr auto - grid-template-columns: 100% + min-height: 100% + display: grid + grid-template-rows: auto 1fr auto + grid-template-columns: 100% header - nav - a - span - font-size: 2rem - font-family: 'Titling Gothic FB', sans-serif - color: $pink + nav + a + span + font-size: 2rem + font-family: 'Titling Gothic FB', sans-serif + color: $pink #navbarSupportedContent23 - ul - background-color: $pink - li - transition: 0.5s - background-color: $pink - text-align: center - a - span - transition: 0.2s - color: $black - font-family: "Apercu Mono", monospace + ul + background-color: $pink + li + transition: 0.5s + background-color: $pink + text-align: center + a + span + transition: 0.2s + color: $black + font-family: "Apercu Mono", monospace li:hover - background-color: $black - a - span - color: $pink + background-color: $black + a + span + color: $pink .active - background-color: $black - a - span - color: $green + background-color: $black + a + span + color: $green .active:hover - background-color: $pink - a - span - color: $black + background-color: $pink + a + span + color: $black main - padding: 0.5rem - h1 - padding-bottom: 1rem - font-size: 4.5rem - span - text-decoration: underline $pink - text-decoration-style: wavy + padding: 0.5rem + h1 + padding-bottom: 1rem + font-size: 4.5rem + span + text-decoration: underline $pink + text-decoration-style: wavy p - font-size: 2rem - margin-bottom: 5px - + font-size: 2rem + margin-bottom: 5px footer - text-align: center - font-size: 1rem - padding: 0.5rem - a - color: $pink - text-decoration: underline $pink + text-align: center + font-size: 1rem + padding: 0.5rem + a + color: $pink + text-decoration: underline $pink .ef - max-height: 85vh - min-height: 85vh !important + max-height: 85vh + min-height: 85vh !important .error - text-align: center + text-align: center .pink-block - background-color: $pink - min-height: 100vh + background-color: $pink + min-height: 100vh .center-v - min-height: 100% /* Fallback for browsers do NOT support vh unit */ - min-height: 100vh /* These two lines are counted as one :-) */ + min-height: 100% /* Fallback for browsers do NOT support vh unit */ + min-height: 100vh /* These two lines are counted as one :-) */ - display: flex - align-items: center + display: flex + align-items: center .center-v-h - display: flex - justify-content: center - align-items: center - min-height: 100vh + display: flex + justify-content: center + align-items: center + min-height: 100vh .logos-container - width: 3.5rem + width: 3.5rem .logo - width: auto - height: 3.5rem - fill: $black - margin-bottom: 2.5rem + width: auto + height: 3.5rem + fill: $black + margin-bottom: 2.5rem .logo-container - cursor: pointer + cursor: pointer .about-pos - p - font-size: 3vh - margin-bottom: 3vh + p + font-size: 3vh + margin-bottom: 3vh .pr - img - width: 100% - border: 2vh solid $pink + img + width: 100% + border: 2vh solid $pink margin-bottom: 3vh margin-top: 1vh - .pr-text - a - color: $pink - h1 + a + color: $pink + h1 - font-size: 4vh - margin-bottom: 0 - padding-bottom: 0 + font-size: 4vh + margin-bottom: 0 + padding-bottom: 0 a:hover - color: $green + color: $green p - font-size: 3vh + font-size: 3vh .start - margin-top: 3vh + margin-top: 3vh #contact-message - margin-top: 2vh - p - color: $green - span - text-decoration: underline $green + margin-top: 2vh + p + color: $green + span + text-decoration: underline $green .h-captcha - margin-bottom: 0.5vh + margin-bottom: 0.5vh .button-c - display: inline-block - font-weight: 400 - color: #212529 - text-align: center - vertical-align: middle - cursor: pointer - user-select: none - border: 1px solid $black - padding: 0.375rem 0.75rem - font-size: 1rem - line-height: 1.5 - border-radius: 0.25rem - transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out - font-family: "Apercu Mono" + display: inline-block + font-weight: 400 + color: #212529 + text-align: center + vertical-align: middle + cursor: pointer + user-select: none + border: 1px solid $black + padding: 0.375rem 0.75rem + font-size: 1rem + line-height: 1.5 + border-radius: 0.25rem + transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out + font-family: "Apercu Mono" .button-c - background-color: $pink + background-color: $pink .button-c:hover - background-color: $black - color: $pink - border-color: $pink + background-color: $black + color: $pink + border-color: $pink // Nav stuff .ham - width: 30px - height: 20px - position: relative - margin: 0px - -webkit-transform: rotate(0deg) - -moz-transform: rotate(0deg) - -o-transform: rotate(0deg) - transform: rotate(0deg) - -webkit-transition: .5s ease-in-out - -moz-transition: .5s ease-in-out - -o-transition: .5s ease-in-out - transition: .5s ease-in-out - cursor: pointer + width: 30px + height: 20px + position: relative + margin: 0px + -webkit-transform: rotate(0deg) + -moz-transform: rotate(0deg) + -o-transform: rotate(0deg) + transform: rotate(0deg) + -webkit-transition: .5s ease-in-out + -moz-transition: .5s ease-in-out + -o-transition: .5s ease-in-out + transition: .5s ease-in-out + cursor: pointer .ham span - display: block - position: absolute - height: 3px - width: 100% - border-radius: 9px - opacity: 1 - left: 0 - -webkit-transform: rotate(0deg) - -moz-transform: rotate(0deg) - -o-transform: rotate(0deg) - transform: rotate(0deg) - -webkit-transition: .25s ease-in-out - -moz-transition: .25s ease-in-out - -o-transition: .25s ease-in-out - transition: .25s ease-in-out - background: $pink + display: block + position: absolute + height: 3px + width: 100% + border-radius: 9px + opacity: 1 + left: 0 + -webkit-transform: rotate(0deg) + -moz-transform: rotate(0deg) + -o-transform: rotate(0deg) + transform: rotate(0deg) + -webkit-transition: .25s ease-in-out + -moz-transition: .25s ease-in-out + -o-transition: .25s ease-in-out + transition: .25s ease-in-out + background: $pink .ham span:nth-child(1) - top: 0 + top: 0 .ham span:nth-child(2), .ham span:nth-child(3) - top: 10px + top: 10px .ham span:nth-child(4) - top: 20px + top: 20px .ham.open span:nth-child(1) - top: 11px - width: 0 - left: 50% + top: 11px + width: 0 + left: 50% .ham.open span:nth-child(2) - -webkit-transform: rotate(45deg) - -moz-transform: rotate(45deg) - -o-transform: rotate(45deg) - transform: rotate(45deg) + -webkit-transform: rotate(45deg) + -moz-transform: rotate(45deg) + -o-transform: rotate(45deg) + transform: rotate(45deg) .ham.open span:nth-child(3) - -webkit-transform: rotate(-45deg) - -moz-transform: rotate(-45deg) - -o-transform: rotate(-45deg) - transform: rotate(-45deg) + -webkit-transform: rotate(-45deg) + -moz-transform: rotate(-45deg) + -o-transform: rotate(-45deg) + transform: rotate(-45deg) .ham.open span:nth-child(4) - top: 11px - width: 0 - left: 50% + top: 11px + width: 0 + left: 50% @media only screen and (max-height: 421px) - .pr-text - margin-bottom: 5vh !important + .pr-text + margin-bottom: 5vh !important @media only screen and (max-width: 575px) - .logo - height: 5rem + .logo + height: 5rem .logos-container - width: 5rem + width: 5rem .aaa - min-height: 40vh !important + min-height: 40vh !important .aaaa - margin-top: 5vh !important + margin-top: 5vh !important .ef - max-height: none !important - min-height: 0 !important + max-height: none !important + min-height: 0 !important .ff - min-height: 82.8vh !important - + min-height: 82.8vh !important @media only screen and (max-height: 815px) - .ef - max-height: none !important - min-height: 0 !important - + .ef + max-height: none !important + min-height: 0 !important diff --git a/routes/about.js b/routes/about.js index 8a66270..eda7c08 100644 --- a/routes/about.js +++ b/routes/about.js @@ -3,25 +3,35 @@ const axios = require('axios'); var router = express.Router(); /* GET home page. */ -router.get('/', function(req, res, next) { - const GHOST_KEY = process.env.GHOST_KEY - const base_url = `https://blog.pastel.codes/ghost/api/v3/content/posts/?key=${GHOST_KEY}` +router.get('/', function (req, res, _next) { + const GHOST_KEY = process.env.GHOST_KEY; + const base_url = `https://blog.pastel.codes/ghost/api/v3/content/posts/?key=${GHOST_KEY}`; - axios.all([ - axios.get(`${base_url}&limit=3`), - axios.get(`${base_url}&limit=3&filter=tag:project`), + axios + .all([ + axios.get(`${base_url}&limit=3`), + axios.get(`${base_url}&limit=3&filter=tag:project`), ]) - .then(axios.spread((response1, response2) => { - var base = { title: 'About', description: 'Who??? What??? AAAAaaa, about me.'}; - var blog = JSON.parse(JSON.stringify(response1.data).split('"posts":').join('"blog":')); - var projects = JSON.parse(JSON.stringify(response2.data).split('"posts":').join('"project":')); - var out = Object.assign(base, blog, projects); + .then( + axios.spread((response1, response2) => { + var base = { + title: 'About', + description: 'Who??? What??? AAAAaaa, about me.', + }; + var blog = JSON.parse( + JSON.stringify(response1.data).split('"posts":').join('"blog":') + ); + var projects = JSON.parse( + JSON.stringify(response2.data).split('"posts":').join('"project":') + ); + var out = Object.assign(base, blog, projects); - res.render('about', out); - })) - .catch(error => { - console.log(error); - }); + res.render('about', out); + }) + ) + .catch((error) => { + console.log(error); + }); }); module.exports = router; diff --git a/routes/contact.js b/routes/contact.js index db3e0bf..ed3635d 100644 --- a/routes/contact.js +++ b/routes/contact.js @@ -1,73 +1,80 @@ var express = require('express'); -var rate_limit = require("express-rate-limit") -const {verify} = require('hcaptcha'); -const nodemailer = require('nodemailer') +var rate_limit = require('express-rate-limit'); +const { verify } = require('hcaptcha'); var router = express.Router(); const sgMail = require('@sendgrid/mail'); sgMail.setApiKey(process.env.SENDGRID_API_KEY); const contact_rate_limit = rate_limit({ - windowMs: 10 * 60 * 1000, // 10 minutes - max: 5, // limit each IP to 10 requests per windowMs - message: "Too many contact requests, try again later.", - handler: function (req, res /*, next*/) { - res.render('error', { - title: "Error", - message: "Too many contact requests, try again later.", - error: {status: null} - }) - }, + windowMs: 10 * 60 * 1000, // 10 minutes + max: 5, // limit each IP to 10 requests per windowMs + message: 'Too many contact requests, try again later.', + handler: function (req, res /*, next*/) { + res.render('error', { + title: 'Error', + message: 'Too many contact requests, try again later.', + error: { status: null }, + }); + }, }); // POST route from contact form router.post('/', contact_rate_limit, (req, res) => { - const TO_MAIL_USER = process.env.TO_MAIL_USER - const FROM_MAIL_USER = process.env.FROM_MAIL_USER - const HCAPTCHA_KEY = process.env.HCAPTCHA_KEY - const REPLY_TO_MAIL = process.env.REPLY_TO_MAIL - const token = req.body["g-recaptcha-response"]; - const ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress; + const TO_MAIL_USER = process.env.TO_MAIL_USER; + const FROM_MAIL_USER = process.env.FROM_MAIL_USER; + const HCAPTCHA_KEY = process.env.HCAPTCHA_KEY; + const REPLY_TO_MAIL = process.env.REPLY_TO_MAIL; + const token = req.body['g-recaptcha-response']; + const ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress; - verify(HCAPTCHA_KEY, token) - .then((data) => { - if (data.success === true) { - const msg = { - to: TO_MAIL_USER, - from: FROM_MAIL_USER, - subject: 'New message from contact form at pastel.codes', - text: `${req.body.firstname} ${req.body.lastname} (${req.body.email})\nsays: ${req.body.message}\n\nip: ${ip}` - }; + verify(HCAPTCHA_KEY, token) + .then((data) => { + if (data.success === true) { + const msg = { + to: TO_MAIL_USER, + from: FROM_MAIL_USER, + subject: 'New message from contact form at pastel.codes', + text: `${req.body.firstname} ${req.body.lastname} (${req.body.email})\nsays: ${req.body.message}\n\nip: ${ip}`, + }; - sgMail - .send(msg) - .then(() => { - res.render('contact', { - title: 'Contact', - message: "I will get back to you soon!", - success: "Make sure the email is from ", - email: REPLY_TO_MAIL - }) - }) - .catch(error => { - console.log(error) - res.render('error', {title: 'Contact', message: "Email did not send"}) - }); - - } else { - // rerender with same info in the text box and show error message - res.render('contact', {title: 'Contact', message: "Captcha failed, try again"}); - } - }) - .catch(error => { + sgMail + .send(msg) + .then(() => { + res.render('contact', { + title: 'Contact', + message: 'I will get back to you soon!', + success: 'Make sure the email is from ', + email: REPLY_TO_MAIL, + }); + }) + .catch((error) => { console.log(error); - res.render('contact', {title: 'Contact', message: "Something wrong happened, try again later"}); + res.render('error', { + title: 'Contact', + message: 'Email did not send', + }); + }); + } else { + // rerender with same info in the text box and show error message + res.render('contact', { + title: 'Contact', + message: 'Captcha failed, try again', }); -}) + } + }) + .catch((error) => { + console.log(error); + res.render('contact', { + title: 'Contact', + message: 'Something wrong happened, try again later', + }); + }); +}); /* GET home page. */ -router.get('/', function (req, res, next) { - res.render('contact', {title: 'Contact', description: "Contact me!"}); +router.get('/', function (req, res, _next) { + res.render('contact', { title: 'Contact', description: 'Contact me!' }); }); module.exports = router; diff --git a/routes/index.js b/routes/index.js index 293698f..0650032 100644 --- a/routes/index.js +++ b/routes/index.js @@ -2,8 +2,8 @@ var express = require('express'); var router = express.Router(); /* GET home page. */ -router.get('/', function(req, res, next) { - res.render('index', { title: 'Home', description: "Hello, I'm E" }); +router.get('/', function (req, res, _next) { + res.render('index', { title: 'Home', description: "Hello, I'm E" }); }); module.exports = router; diff --git a/src/tailwind.css b/src/tailwind.css index 9286609..a20ff0e 100644 --- a/src/tailwind.css +++ b/src/tailwind.css @@ -2,23 +2,23 @@ @tailwind components; @font-face { - font-family: 'Titling Gothic FB'; - src: url("../fonts/TITLINGGOTHICFB-WIDE.OTF") format('opentype') + font-family: 'Titling Gothic FB'; + src: url('../fonts/TITLINGGOTHICFB-WIDE.OTF') format('opentype'); } @font-face { - font-family: 'Gilroy'; - src: url("../fonts/Gilroy-ExtraBold.otf") format('opentype') + font-family: 'Gilroy'; + src: url('../fonts/Gilroy-ExtraBold.otf') format('opentype'); } @font-face { - font-family: 'Apercu Mono'; - src: url("../fonts/ApercuMono.ttf") format('truetype'); + font-family: 'Apercu Mono'; + src: url('../fonts/ApercuMono.ttf') format('truetype'); } .wavy { - text-decoration: underline; - text-decoration-style: wavy; + text-decoration: underline; + text-decoration-style: wavy; } @tailwind utilities; diff --git a/tailwind.config.js b/tailwind.config.js index cffa2ef..635be20 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -1,13 +1,13 @@ module.exports = { - mode: "jit", + mode: 'jit', purge: ['views/*.pug'], darkMode: false, // or 'media' or 'class' theme: { extend: { fontFamily: { - 'extra': ['"Titling Gothic FB"'], - 'sans': ['Gilroy'], - 'mono': ['"Apercu Mono"'], + extra: ['"Titling Gothic FB"'], + sans: ['Gilroy'], + mono: ['"Apercu Mono"'], }, colors: { transparent: 'transparent', @@ -20,14 +20,12 @@ module.exports = { }, green: { DEFAULT: '#CDE7B0', - } - } + }, + }, }, }, variants: { extend: {}, }, - plugins: [ - require('tailwind-hamburgers'), - ], -} + plugins: [require('tailwind-hamburgers')], +};