diff --git a/src/app.py b/src/app.py index 800d588..1adc39b 100755 --- a/src/app.py +++ b/src/app.py @@ -2,23 +2,44 @@ import flask from flask_minify import Minify import json import werkzeug.exceptions as HTTPerror -import requests from config import * -import os + +app = flask.Flask(__name__) + +# Add security and caching headers +@app.after_request +def add_security_headers(response): + """Add security and performance headers to all responses""" + # Security headers + response.headers['X-Content-Type-Options'] = 'nosniff' + response.headers['X-Frame-Options'] = 'SAMEORIGIN' + response.headers['X-XSS-Protection'] = '1; mode=block' + response.headers['Referrer-Policy'] = 'strict-origin-when-cross-origin' + + # Cache control for static assets + if flask.request.path.startswith('/static/'): + response.headers['Cache-Control'] = 'public, max-age=31536000, immutable' + elif flask.request.path in ['/sitemap.xml', '/robots.txt']: + response.headers['Cache-Control'] = 'public, max-age=86400' + else: + response.headers['Cache-Control'] = 'no-cache, must-revalidate' + + return response + + proj = json.load(open("./static/json/projects.json", "r")) books = json.load(open("./static/json/books.json", "r")) skillList = json.load(open("./static/json/skills.json", "r")) timeline = json.load(open("./static/json/timeline.json", "r")) pages = json.load(open("./static/json/pages.json", "r")) + pages['projects']['skillList'] = skillList # pages['about']['timeline'] = timeline pages['projects']['projects'] = proj pages['home']['books'] = books pages['books']['books'] = books -app = flask.Flask(__name__) - @app.route('/api/goto/') @app.route('/api/goto/') def goto(location='home'): @@ -87,6 +108,6 @@ if __name__ == "__main__": # import sass # sass.compile(dirname=("static/scss", "static/css"), output_style="compressed") - app.run() + app.run(debug=False) else: Minify(app=app, html=True, js=True, cssless=True) diff --git a/src/static/css/App.css b/src/static/css/App.css index 43761b3..2274632 100755 --- a/src/static/css/App.css +++ b/src/static/css/App.css @@ -687,7 +687,6 @@ tr { margin: 2em; box-shadow: 0 0 0.2rem #fff, 0 0 0.2rem #fff, 0 0 2rem #5271ff, 0 0 0.8rem #5271ff, 0 0 2.8rem #5271ff, inset 0 0 1.3rem #5271ff; - background-image: url('https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Fwww.thedermacompany.co.uk%2Fwp-content%2Fuploads%2F2020%2F11%2Fblack-brick-scaled.jpg&f=1&nofb=1&ipt=d10be6df79141da1b4ec0c725575cef0f7b67e957e391662226d66cff02d25e6&ipo=images'); /* background-blend-mode: ; */ text-align: center; } diff --git a/src/static/js/idler.js b/src/static/js/idler.js index 3c4e75f..ffc30a0 100755 --- a/src/static/js/idler.js +++ b/src/static/js/idler.js @@ -69,23 +69,39 @@ function windowResized() { function draw() { background(24); + // Update all balls for (let i = 0; i < balls.length; i++) { balls[i].update(); } + + // Optimize line drawing with early distance checks + const maxDist = 150; + const maxDistSquared = maxDist * maxDist; // Avoid sqrt in distance calculation + for (let i = 0; i < balls.length - 1; i++) { + const ball1 = balls[i]; for (let j = i + 1; j < balls.length; j++) { - let distance = dist(balls[i].x, balls[i].y, balls[j].x, balls[j].y); - if (distance < 100){ - stroke(150); - line(balls[i].x, balls[i].y, balls[j].x, balls[j].y); - } - else if (distance < 150) { - stroke(100); - let chance = 0.3 ** (((random(0.2) + 0.8) * distance) / 150); - if (chance < 0.5) { - stroke(50); + const ball2 = balls[j]; + + // Quick rejection test using squared distance (faster than sqrt) + const dx = ball2.x - ball1.x; + const dy = ball2.y - ball1.y; + const distSquared = dx * dx + dy * dy; + + if (distSquared < maxDistSquared) { + const distance = Math.sqrt(distSquared); // Only calculate sqrt if needed + + if (distance < 100) { + stroke(150); + line(ball1.x, ball1.y, ball2.x, ball2.y); + } else { + stroke(100); + const chance = 0.3 ** (((random(0.2) + 0.8) * distance) / 150); + if (chance < 0.5) { + stroke(50); + } + line(ball1.x, ball1.y, ball2.x, ball2.y); } - line(balls[i].x, balls[i].y, balls[j].x, balls[j].y); } } } diff --git a/src/static/js/responsive.js b/src/static/js/responsive.js index 2202f76..71d5d66 100755 --- a/src/static/js/responsive.js +++ b/src/static/js/responsive.js @@ -29,9 +29,14 @@ async function goto(location, { push = true } = {}) { const content = response[1]; let root = document.getElementById("root"); root.innerHTML = content; - root.querySelectorAll("script").forEach((x) => { - eval(x.innerHTML); - }); + root.querySelectorAll("script").forEach((oldScript) => { + const newScript = document.createElement("script"); + Array.from(oldScript.attributes).forEach(attr => { + newScript.setAttribute(attr.name, attr.value); + }); + newScript.textContent = oldScript.textContent; + oldScript.parentNode.replaceChild(newScript, oldScript); + }); toggleMenu(collapse=true); document.querySelector("title").textContent = metadata["title"]; if (push) { diff --git a/src/templates/header.html b/src/templates/header.html index d06e70c..7f860ba 100755 --- a/src/templates/header.html +++ b/src/templates/header.html @@ -8,6 +8,10 @@ /> + + + + @@ -28,9 +32,10 @@ - + - - - - + + - - + + {{ var['title'] }} {% block header %} diff --git a/src/templates/home.html b/src/templates/home.html index 8f24796..bbb66af 100755 --- a/src/templates/home.html +++ b/src/templates/home.html @@ -20,12 +20,12 @@
- My Brain is Glowing - Pepsi Addict - I Fear No Beer - Secret Message - They took my blood but it wasn't DNA, it was USA - Bob the Builder gif + My Brain is Glowing + Pepsi Addict + I Fear No Beer + Secret Message + They took my blood but it wasn't DNA, it was USA + Bob the Builder gif

You've reached the website for Andrew Simonson's personal online shenanigans. @@ -42,30 +42,6 @@

- {#
-
- duck spinning -
-
- memes, idk. -
-
- memes, idk. -
-
#} -
{% from 'partials/chess.html' import chess %} {{ @@ -73,19 +49,7 @@

- {# {% from 'partials/bookshelf.html' import bookshelf %} {{ - bookshelf(var.books) }} #} -
-
-
- + stabby