diff options
| -rw-r--r-- | api-routes.js | 2 | ||||
| -rw-r--r-- | index.js | 3 | ||||
| -rw-r--r-- | routes.js | 8 | ||||
| -rw-r--r-- | static/css/mobile.css | 3 | ||||
| -rw-r--r-- | static/css/standard.css | 148 | ||||
| -rw-r--r-- | static/img/chaos.jpg | bin | 0 -> 665897 bytes | |||
| -rw-r--r-- | static/img/earth.jpg | bin | 0 -> 1612951 bytes | |||
| -rw-r--r-- | static/img/lake.jpg | bin | 0 -> 2353970 bytes | |||
| -rw-r--r-- | static/img/logo.png | bin | 0 -> 55444 bytes | |||
| -rw-r--r-- | static/index.html | 34 | ||||
| -rw-r--r-- | utils.js | 22 |
11 files changed, 207 insertions, 13 deletions
diff --git a/api-routes.js b/api-routes.js index 9f02edb..5c0ed7c 100644 --- a/api-routes.js +++ b/api-routes.js @@ -10,7 +10,7 @@ router.all('/', async (req, res) => { router.put('/:slug', async (req, res) => { try { const {url} = req.body; - const slug = req.params.slug; + const slug = req.params.slug.toLowerCase(); if (!utils.isUrlFormatted(url)) return utils.sendBadRequestError(res, 'URL "'+url+'" is malformatted. Must be a valid URL.'); if (!utils.isAlphaNumeric(slug)) @@ -21,6 +21,9 @@ async function serve() { app.use(express.urlencoded({extended: true})); app.use(express.json()); + app.use('/css', express.static(__dirname+'/static/css')); + app.use('/js', express.static(__dirname+'/static/js')); + app.use('/img', express.static(__dirname+'/static/img')); app.use('/api', apiRoutes); app.use('/', routes); @@ -5,14 +5,12 @@ const utils = require('./utils.js'); const router = express.Router(); router.get('/', async (req, res) => { - res.sendFile('static/index.html', { - root: path.join(__dirname) - }, () => utils.sendNotFoundError(res)); + utils.sendFile(res, 'static/index.html'); }); router.get('/:slug', async (req, res) => { try { - const url = await Url.findOne({slug: req.params.slug}); + const url = await Url.findOne({slug: req.params.slug.toLowerCase()}); if (url) res.redirect(301, url.url); else @@ -24,6 +22,6 @@ router.get('/:slug', async (req, res) => { router.all('/*', async (req, res) => { utils.sendNotFoundError(res); -}) +}); module.exports = router; diff --git a/static/css/mobile.css b/static/css/mobile.css new file mode 100644 index 0000000..364d400 --- /dev/null +++ b/static/css/mobile.css @@ -0,0 +1,3 @@ +@media screen and (max-width: 700px) { + +} diff --git a/static/css/standard.css b/static/css/standard.css new file mode 100644 index 0000000..26af287 --- /dev/null +++ b/static/css/standard.css @@ -0,0 +1,148 @@ +body,h1,h2,h3,h4,h5,h6,p { + margin: 0; +} +body { + margin: 0rem 8rem; + min-height: 100vh; + width: calc(100vw - 16rem); + background-repeat: no-repeat; + background-size: cover; + background-attachment: fixed; + font-family: var(--cflems-ff-text-primary); +} +body.dark { + color: #ffffff; + background-image: + linear-gradient(to top, #000000f0 20%, #00000090 50%, #00000050), + url('../img/earth.jpg'); +} +body.light { + color: #000000; + background-image: + linear-gradient(to bottom, #fffffff0 10%, #ffffff90 50%, #ffffff50), + url('../img/lake.jpg'); +} +#header { + padding: 2rem 0; + display: flex; + flex-direction: row; + justify-content: flex-start; + align-items: center; + cursor: default; + user-select: none; +} +#header #logo { + padding: 0.25em 0em 0em 1.75em; + background-image: url('../img/logo.png'); + background-repeat: no-repeat; + background-size: contain; + background-position: left center; + flex-grow: 1; + font-family: var(--cflems-ff-text-primary); + font-size: 3rem; +} +#content { + display: flex; + flex-direction: row; + align-items: flex-start; + height: 100%; +} +#content #lhs { + padding: 0rem 1rem; + flex-grow: 2; + background-color: #fcfcfc; + margin-right: 2rem; + color: #000000; + box-shadow: 0px 0px 0.5rem #000000b0; + border-radius: 0.25rem; + font-size: 16pt; + font-family: var(--cflems-ff-text-secondary); + font-weight: 400; + line-height: 1.5; +} +body.light #content #lhs { + background-color: #fdfbf9; + color: #28282b; + box-shadow: 0px 0px 0.5rem #d4d4d7b0; +} +body.dark #content #lhs { + background-color: #28282b; + color: #fdfbf9; + box-shadow: #000000b0; +} +#content #rhs { + flex-grow: 3; + font-family: var(--cflems-ff-text-primary); + font-size: 14pt; +} +.form-element { + margin: 1rem 0; +} +.form-element p { + display: flex; + flex-direction: row; + align-items: center; + justify-content: left; + margin: 0.25rem 0; +} +#base-url { + font-family: var(--cflems-ff-text-mono); + font-weight: 200; + font-size: 14pt; + margin: 0 0.25rem 0 0; +} +#slug { + width: 4.5rem; +} +body.dark #shortenButton { + background-color: #7550a6; + color: #fdfbf9; + border: none; + box-shadow: none; +} +body.dark #shortenButton:hover { + background-color: #6f4c9d; +} +body.dark #shortenButton:active { + background-color: #68369b; +} +body.light #shortenButton { + background-color: #6a8fd4; + color: #fdfbf9; + border: none; + box-shadow: none; +} +body.light #shortenButton:hover { + background-color: #6487c9; +} +body.light #shortenButton:active { + background-color: #5f80be; +} +.form-element p .fullsize { + flex-grow: 1; +} +.form-element input, .form-element button { + font-size: 14pt; + border-radius: 0.5rem; + border-style: solid; + border-width: 1px; +} +.form-element input[type=text] { + font-family: var(--cflems-ff-text-mono); + font-weight: 200; + padding: 0.33rem; +} +body.light .form-element input[type=text], body.light .form-element button { + border-color: #28282b; +} +body.dark .form-element input[type=text], body.dark .form-element button { + border-color: none; + /*box-shadow: 0rem 0rem 0.5rem #fdfbf9b0;*/ +} +.form-element button { + font-family: var(--cflems-ff-text-primary); + font-weight: 400; + padding: 0.75rem; + cursor: pointer; + user-select: none; +} diff --git a/static/img/chaos.jpg b/static/img/chaos.jpg Binary files differnew file mode 100644 index 0000000..ad8c7f4 --- /dev/null +++ b/static/img/chaos.jpg diff --git a/static/img/earth.jpg b/static/img/earth.jpg Binary files differnew file mode 100644 index 0000000..e1a8200 --- /dev/null +++ b/static/img/earth.jpg diff --git a/static/img/lake.jpg b/static/img/lake.jpg Binary files differnew file mode 100644 index 0000000..1539756 --- /dev/null +++ b/static/img/lake.jpg diff --git a/static/img/logo.png b/static/img/logo.png Binary files differnew file mode 100644 index 0000000..b71c949 --- /dev/null +++ b/static/img/logo.png diff --git a/static/index.html b/static/index.html index b59e0ef..4deeefb 100644 --- a/static/index.html +++ b/static/index.html @@ -2,10 +2,38 @@ <html> <head> <meta charset="utf-8" /> + <meta name="viewport" content="width=device-width, initial-scale=1.0" /> + <link rel="canonical" href="https://fle.ms/" /> + <link rel="icon" type="image/png" href="img/logo.png" /> + <link rel="stylesheet" type="text/css" href="https://cflems.net/css/fonts.css" /> + <link rel="stylesheet" type="text/css" href="css/standard.css" /> + <link rel="stylesheet" type="text/css" href="css/mobile.css" /> <title>fle.ms</title> </head> - <body> - <h1>fle.ms</h1> - <p>URL Shortener</p> + <body class="dark"> + <div id="header"> + <h1 id="logo">fle.ms</h1> + </div> + <div id="content"> + <div id="lhs"> + <div class="form-element"> + <p><label for="url">Paste a Long URL</label></p> + <p><input id="url" type="text" placeholder="https://docs.google.com/spreadsheets/d/1SIXl0TxDgaTU49ZOph5s8HA5ZqtEakBCdQkqHzzfhf8/edit" class="fullsize" /></p> + </div> + <div class="form-element"> + <p><label for="slug">Customize Short URL</label></p> + <p> + <label id="base-url" for="slug">fle.ms/</label> + <input id="slug" type="text" /> + </p> + </div> + <div class="form-element"> + <p><button id="shortenButton" class="fullsize">Shorten URL</button></p> + </div> + </div> + <div id="rhs"> + <p>A URL shortener is a thing that does blah blah blah.</p> + </div> + </div> </body> </html> @@ -2,11 +2,25 @@ const path = require('path'); const config = require('./config.js'); const helperFunctions = { + sendFile : function (res, fileName) { + res.sendFile(fileName, { + root: path.join(__dirname) + }, err => { + if (!err) return; + utils.sendNotFoundError(res) + }); + }, sendNotFoundError : function (res) { - res.status(404).sendFile('static/notfound.html', {root: path.join(__dirname)}, - err => res.json( - {status: "ERROR", statusCode: 404, errorType: "NOT FOUND", errorMessage: "Not Found"} - )); + if (!res.headersSent) res.status(404); + const statusJson = {status: "ERROR", statusCode: 404, errorType: "NOT FOUND", errorMessage: "Not Found"}; + res.sendFile('static/notfound.html', {root: path.join(__dirname)}, + err => { + if (!err) return; + + console.error('[express] Encountered an error:', err); + if (!res.headersSent) res.json(statusJson); + else res.send(JSON.stringify(statusJson)); + }); }, sendBadRequestError : function (res, errorMessage) { res.status(400).json({status: "ERROR", statusCode: 400, errorType: "BAD REQUEST", errorMessage}); |
