Compare commits

..

11 Commits

Author SHA1 Message Date
snyk-bot
7ff9f6f361 fix: package.json & package-lock.json to reduce vulnerabilities
The following vulnerabilities are fixed with an upgrade:
- https://snyk.io/vuln/SNYK-JS-SEMVER-3247795
2024-04-29 12:21:39 +00:00
E
8449b30401 Add linting, formatting and pre-commit (#53)
* Add dev-dependancies

* Security update npm packages

* Force audit fix

* Add linting, formatting and precommit

* Format files
2024-04-29 13:21:31 +01:00
E
80813d48e3 Fix UI issues on desktop and mobile (#31) 2021-09-12 11:48:35 +01:00
Snyk bot
96d69992a0 fix: package.json & package-lock.json to reduce vulnerabilities (#29)
The following vulnerabilities are fixed with an upgrade:
- https://snyk.io/vuln/SNYK-JS-AXIOS-1579269
2021-09-12 08:54:00 +01:00
Snyk bot
138a8de86c fix: package.json & package-lock.json to reduce vulnerabilities (#28)
The following vulnerabilities are fixed with an upgrade:
- https://snyk.io/vuln/SNYK-JS-NODEMAILER-1296415
2021-09-12 08:51:36 +01:00
Snyk bot
7d230410f1 fix: package.json & package-lock.json to reduce vulnerabilities (#27)
The following vulnerabilities are fixed with an upgrade:
- https://snyk.io/vuln/SNYK-JS-AXIOS-1579269
2021-09-12 08:49:42 +01:00
Snyk bot
6850b3152e fix: package.json & package-lock.json to reduce vulnerabilities (#25)
The following vulnerabilities are fixed with an upgrade:
- https://snyk.io/vuln/SNYK-JS-NODEMAILER-1296415
2021-09-12 08:48:17 +01:00
Snyk bot
fc85964ed9 fix: Dockerfile to reduce vulnerabilities (#26)
The following vulnerabilities are fixed with an upgrade:
- https://snyk.io/vuln/SNYK-DEBIAN10-GLIBC-1315333
- https://snyk.io/vuln/SNYK-DEBIAN10-PYTHON27-1063178
- https://snyk.io/vuln/SNYK-DEBIAN10-PYTHON27-1063178
- https://snyk.io/vuln/SNYK-DEBIAN10-PYTHON27-1063178
- https://snyk.io/vuln/SNYK-DEBIAN10-PYTHON27-1063178
2021-09-12 08:48:01 +01:00
E
de6ab6277b Fix incorrect command and split into several runs (#19)
* Change node version in Dockerfile and steps

* Change name of scripts in package.json
2021-09-11 22:07:23 +01:00
E
61a0713ad5 Switch to tailwind (#16)
* Add tailwind to project
* Adapt previous design into tailwind
* Remove bootstrap
* Fix docker steps
2021-09-11 21:32:23 +01:00
E
f475c89e27 Create codeql-analysis.yml 2021-09-10 22:50:59 +01:00
36 changed files with 4300 additions and 13890 deletions

15
.editorconfig Normal file
View File

@@ -0,0 +1,15 @@
# EditorConfig is awesome: https://EditorConfig.org
# top-most EditorConfig file
root = true
[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = false
insert_final_newline = false
[pug.ts]
indent_size = 4

3
.eslintrc.json Normal file
View File

@@ -0,0 +1,3 @@
{
"extends": ["prettier"]
}

71
.github/workflows/codeql-analysis.yml vendored Normal file
View File

@@ -0,0 +1,71 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
on:
push:
branches: [ master ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ master ]
schedule:
- cron: '38 12 * * 3'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'javascript' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
# Learn more:
# https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
steps:
- name: Checkout repository
uses: actions/checkout@v2
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v1
# Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1

2
.gitignore vendored
View File

@@ -199,3 +199,5 @@ notes
.secrets .secrets
public/stylesheets/style.css public/stylesheets/style.css
ngrok
.dccache

1
.husky/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
_

4
.husky/pre-commit Executable file
View File

@@ -0,0 +1,4 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
npx lint-staged

8
.prettierrc.json Normal file
View File

@@ -0,0 +1,8 @@
{
"trailingComma": "es5",
"semi": true,
"tabWidth": 2,
"singleQuote": true,
"jsxSingleQuote": true,
"plugins": ["prettier-plugin-tailwindcss"]
}

View File

@@ -1,11 +1,13 @@
FROM node:10.19.0 FROM node:16-bullseye-slim
ENV IS_DOCKER=true ENV IS_DOCKER=true
ENV NODE_ENV=production ENV NODE_ENV=production
WORKDIR /app WORKDIR /app
COPY ["package.json", "package-lock.json*", "./"] COPY ["package.json", "package-lock.json*", "./"]
RUN npm install && npm install nodemon RUN npm install
RUN npm install nodemon
COPY . . COPY . .
RUN npm run build-tailwind
CMD [ "npm", "start" ] CMD [ "npm", "start" ]

View File

@@ -1,5 +1,5 @@
# pastel.codes # pastel.codes
My portfolio website written in node.js, pug and sass My portfolio website written in node.js, pug and tailwind
Docker image: https://hub.docker.com/r/auroradot/pastel.codes Docker image: https://hub.docker.com/r/auroradot/pastel.codes

70
app.js
View File

@@ -4,7 +4,7 @@ var path = require('path');
var cookieParser = require('cookie-parser'); var cookieParser = require('cookie-parser');
var mLogger = require('morgan'); var mLogger = require('morgan');
var logger = require('./config/winston'); var logger = require('./config/winston');
const helmet = require("helmet"); const helmet = require('helmet');
var indexRouter = require('./routes/index'); var indexRouter = require('./routes/index');
var aboutRouter = require('./routes/about'); var aboutRouter = require('./routes/about');
@@ -12,7 +12,8 @@ var contactRouter = require('./routes/contact');
var app = express(); 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'); app.disable('x-powered-by');
// view engine setup // view engine setup
@@ -20,26 +21,43 @@ app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug'); app.set('view engine', 'pug');
if (process.env.NODE_ENV === 'production') { if (process.env.NODE_ENV === 'production') {
app.use(mLogger("common", { "stream": logger.stream })); app.use(mLogger('common', { stream: logger.stream }));
} else { } else {
app.use(mLogger('dev')); app.use(mLogger('dev'));
} }
app.use(helmet()); app.use(helmet());
app.use( app.use(
helmet.contentSecurityPolicy({ helmet.contentSecurityPolicy({
directives: { directives: {
defaultSrc: ["'self'"], defaultSrc: ["'self'"],
scriptSrc: ["'self'", "'unsafe-inline'", "'unsafe-eval'", "https://hcaptcha.com", "https://*.hcaptcha.com", "https://cdn.ravenjs.com/"], scriptSrc: [
imgSrc: ["'self'", "https://blog.pastel.codes", "https://static.ghost.org", "https://secure.gravatar.com"], "'self'",
styleSrc: ["'self'", "'unsafe-inline'", "https://hcaptcha.com", "https://*.hcaptcha.com"], "'unsafe-inline'",
fontSrc: ["'self'", "data:"], "'unsafe-eval'",
frameSrc: ["https://hcaptcha.com", "https://*.hcaptcha.com"], 'https://hcaptcha.com',
objectSrc: ["'none'"], 'https://*.hcaptcha.com',
upgradeInsecureRequests: [], '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.json());
app.use(express.urlencoded({ extended: false })); app.use(express.urlencoded({ extended: false }));
@@ -51,19 +69,19 @@ app.use('/about', aboutRouter);
app.use('/contact', contactRouter); app.use('/contact', contactRouter);
// catch 404 and forward to error handler // catch 404 and forward to error handler
app.use(function(req, res, next) { app.use(function (req, res, next) {
next(createError(404)); next(createError(404));
}); });
// error handler // error handler
app.use(function(err, req, res, next) { app.use(function (err, req, res, _next) {
// set locals, only providing error in development // set locals, only providing error in development
res.locals.message = err.message; res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {}; res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page // render the error page
res.status(err.status || 500); res.status(err.status || 500);
res.render('error', { title: 'Error', description: "Error" }); res.render('error', { title: 'Error', description: 'Error' });
}); });
module.exports = app; module.exports = app;

64
bin/www
View File

@@ -35,19 +35,19 @@ server.on('listening', onListening);
*/ */
function normalizePort(val) { function normalizePort(val) {
var port = parseInt(val, 10); var port = parseInt(val, 10);
if (isNaN(port)) { if (isNaN(port)) {
// named pipe // named pipe
return val; return val;
} }
if (port >= 0) { if (port >= 0) {
// port number // port number
return port; return port;
} }
return false; return false;
} }
/** /**
@@ -55,27 +55,25 @@ function normalizePort(val) {
*/ */
function onError(error) { function onError(error) {
if (error.syscall !== 'listen') { if (error.syscall !== 'listen') {
throw error; throw error;
} }
var bind = typeof port === 'string' var bind = typeof port === 'string' ? 'Pipe ' + port : 'Port ' + port;
? 'Pipe ' + port
: 'Port ' + port;
// handle specific listen errors with friendly messages // handle specific listen errors with friendly messages
switch (error.code) { switch (error.code) {
case 'EACCES': case 'EACCES':
console.error(bind + ' requires elevated privileges'); console.error(bind + ' requires elevated privileges');
process.exit(1); process.exit(1);
break; break;
case 'EADDRINUSE': case 'EADDRINUSE':
console.error(bind + ' is already in use'); console.error(bind + ' is already in use');
process.exit(1); process.exit(1);
break; break;
default: default:
throw error; throw error;
} }
} }
/** /**
@@ -83,9 +81,7 @@ function onError(error) {
*/ */
function onListening() { function onListening() {
var addr = server.address(); var addr = server.address();
var bind = typeof addr === 'string' var bind = typeof addr === 'string' ? 'pipe ' + addr : 'port ' + addr.port;
? 'pipe ' + addr debug('Listening on ' + bind);
: 'port ' + addr.port;
debug('Listening on ' + bind);
} }

View File

@@ -2,29 +2,29 @@ var winston = require('winston');
var appRoot = require('app-root-path'); var appRoot = require('app-root-path');
var logger = new winston.createLogger({ var logger = new winston.createLogger({
transports: [ transports: [
new winston.transports.File({ new winston.transports.File({
level: 'info', level: 'info',
filename: `${appRoot}/logs/app.log`, filename: `${appRoot}/logs/app.log`,
handleExceptions: true, handleExceptions: true,
json: true, json: true,
maxsize: 5242880, //5MB maxsize: 5242880, //5MB
maxFiles: 5, maxFiles: 5,
colorize: false colorize: false,
}), }),
new winston.transports.Console({ new winston.transports.Console({
level: 'debug', level: 'debug',
handleExceptions: true, handleExceptions: true,
json: false, json: false,
colorize: true colorize: true,
}) }),
], ],
exitOnError: false exitOnError: false,
}); });
logger.stream = { logger.stream = {
write: function(message, encoding){ write: function (message, _encoding) {
logger.info(message); logger.info(message);
} },
}; };
module.exports = logger module.exports = logger;

20
eslint.config.mjs Normal file
View File

@@ -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: '^_',
},
],
},
},
];

5248
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -3,21 +3,28 @@
"version": "0.0.0", "version": "0.0.0",
"private": true, "private": true,
"watch": { "watch": {
"build-tail": { "build-tailwind": {
"patterns": ["../views"], "patterns": [
"views/"
],
"extensions": "pug" "extensions": "pug"
} }
}, },
"scripts": { "scripts": {
"test": "echo \"Error: no test specified\" && exit 1", "test": "echo \"Error: no test specified\" && exit 1",
"start": "npx nodemon ./bin/www -e js,pug,sass", "dev": "npx nodemon ./bin/www -e js,pug,sass",
"watch-tail": "npm-watch", "start": "npx ./bin/www -e js,pug,sass",
"build-tail": "postcss src/tailwind.css -o public/stylesheets/style.css" "watch-tailwind": "npx npm-watch",
"build-tailwind": "npx postcss src/tailwind.css -o public/stylesheets/style.css",
"lint": "prettier --check . && eslint .",
"format": "prettier --write --ignore-path .gitignore .",
"prepare": "husky install"
}, },
"dependencies": { "dependencies": {
"@sendgrid/mail": "^7.4.4", "@sendgrid/mail": "^8.1.3",
"app-root-path": "^3.0.0",
"autoprefixer": "^10.3.4", "autoprefixer": "^10.3.4",
"axios": "^0.21.2", "axios": "^1.6.8",
"cookie-parser": "^1.4.5", "cookie-parser": "^1.4.5",
"express": "^4.17.1", "express": "^4.17.1",
"express-rate-limit": "^5.2.6", "express-rate-limit": "^5.2.6",
@@ -25,11 +32,26 @@
"helmet": "^4.6.0", "helmet": "^4.6.0",
"http-errors": "^1.8.0", "http-errors": "^1.8.0",
"morgan": "^1.10.0", "morgan": "^1.10.0",
"nodemailer": "^6.6.0", "nodemailer": "^6.6.1",
"npm-watch": "^0.11.0", "npm-watch": "^0.12.0",
"postcss-cli": "^8.3.1", "postcss-cli": "^8.3.1",
"pug": "^3.0.2", "pug": "^3.0.2",
"tailwind-hamburgers": "^1.1.1",
"tailwindcss": "^2.2.15", "tailwindcss": "^2.2.15",
"winston": "^3.3.3" "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",
"prettier-plugin-tailwindcss": "^0.5.14"
},
"lint-staged": {
"*.js": "eslint --cache --fix",
"*.{js,css,md,pug}": "prettier --write"
} }
} }

View File

@@ -1,6 +1,3 @@
module.exports = { module.exports = {
plugins: [ plugins: [require('tailwindcss'), require('autoprefixer')],
require('tailwindcss'), };
require('autoprefixer')
]
}

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,5 +1,6 @@
$(document).ready(function () { $(document).ready(function () {
$('.ham-button').on('click', function () { $('#menu').on('click', function () {
$('.ham').toggleClass('open'); $('#menu').toggleClass('tham-active');
$('#menu-items').slideToggle(300);
}); });
}); });

View File

@@ -3,293 +3,289 @@ $black: #002234
$green: #CDE7B0 $green: #CDE7B0
@font-face @font-face
font-family: 'Titling Gothic FB' font-family: 'Titling Gothic FB'
src: url("../fonts/TITLINGGOTHICFB-WIDE.OTF") format('opentype') src: url("../fonts/TITLINGGOTHICFB-WIDE.OTF") format('opentype')
@font-face @font-face
font-family: 'Gilroy' font-family: 'Gilroy'
src: url("../fonts/Gilroy-ExtraBold.otf") format('opentype') src: url("../fonts/Gilroy-ExtraBold.otf") format('opentype')
@font-face @font-face
font-family: 'Apercu Mono' font-family: 'Apercu Mono'
src: url("../fonts/ApercuMono.ttf") format('truetype') src: url("../fonts/ApercuMono.ttf") format('truetype')
html, body html, body
width: 100% width: 100%
height: 100% height: 100%
body body
background-color: $black background-color: $black
color: $pink color: $pink
h1 h1
font-family: "Gilroy", sans-serif font-family: "Gilroy", sans-serif
h2 h2
font-weight: bold font-weight: bold
font-family: "Apercu Mono", monospace font-family: "Apercu Mono", monospace
p, label, input, textarea p, label, input, textarea
font-family: "Apercu Mono", monospace font-family: "Apercu Mono", monospace
label label
font-size: 3vh font-size: 3vh
a:hover a:hover
color: $green color: $green
article article
min-height: 100% min-height: 100%
display: grid display: grid
grid-template-rows: auto 1fr auto grid-template-rows: auto 1fr auto
grid-template-columns: 100% grid-template-columns: 100%
header header
nav nav
a a
span span
font-size: 2rem font-size: 2rem
font-family: 'Titling Gothic FB', sans-serif font-family: 'Titling Gothic FB', sans-serif
color: $pink color: $pink
#navbarSupportedContent23 #navbarSupportedContent23
ul ul
background-color: $pink background-color: $pink
li li
transition: 0.5s transition: 0.5s
background-color: $pink background-color: $pink
text-align: center text-align: center
a a
span span
transition: 0.2s transition: 0.2s
color: $black color: $black
font-family: "Apercu Mono", monospace font-family: "Apercu Mono", monospace
li:hover li:hover
background-color: $black background-color: $black
a a
span span
color: $pink color: $pink
.active .active
background-color: $black background-color: $black
a a
span span
color: $green color: $green
.active:hover .active:hover
background-color: $pink background-color: $pink
a a
span span
color: $black color: $black
main main
padding: 0.5rem padding: 0.5rem
h1 h1
padding-bottom: 1rem padding-bottom: 1rem
font-size: 4.5rem font-size: 4.5rem
span span
text-decoration: underline $pink text-decoration: underline $pink
text-decoration-style: wavy text-decoration-style: wavy
p p
font-size: 2rem font-size: 2rem
margin-bottom: 5px margin-bottom: 5px
footer footer
text-align: center text-align: center
font-size: 1rem font-size: 1rem
padding: 0.5rem padding: 0.5rem
a a
color: $pink color: $pink
text-decoration: underline $pink text-decoration: underline $pink
.ef .ef
max-height: 85vh max-height: 85vh
min-height: 85vh !important min-height: 85vh !important
.error .error
text-align: center text-align: center
.pink-block .pink-block
background-color: $pink background-color: $pink
min-height: 100vh min-height: 100vh
.center-v .center-v
min-height: 100% /* Fallback for browsers do NOT support vh unit */ min-height: 100% /* Fallback for browsers do NOT support vh unit */
min-height: 100vh /* These two lines are counted as one :-) */ min-height: 100vh /* These two lines are counted as one :-) */
display: flex display: flex
align-items: center align-items: center
.center-v-h .center-v-h
display: flex display: flex
justify-content: center justify-content: center
align-items: center align-items: center
min-height: 100vh min-height: 100vh
.logos-container .logos-container
width: 3.5rem width: 3.5rem
.logo .logo
width: auto width: auto
height: 3.5rem height: 3.5rem
fill: $black fill: $black
margin-bottom: 2.5rem margin-bottom: 2.5rem
.logo-container .logo-container
cursor: pointer cursor: pointer
.about-pos .about-pos
p p
font-size: 3vh font-size: 3vh
margin-bottom: 3vh margin-bottom: 3vh
.pr .pr
img img
width: 100% width: 100%
border: 2vh solid $pink border: 2vh solid $pink
margin-bottom: 3vh margin-bottom: 3vh
margin-top: 1vh margin-top: 1vh
.pr-text .pr-text
a a
color: $pink color: $pink
h1 h1
font-size: 4vh font-size: 4vh
margin-bottom: 0 margin-bottom: 0
padding-bottom: 0 padding-bottom: 0
a:hover a:hover
color: $green color: $green
p p
font-size: 3vh font-size: 3vh
.start .start
margin-top: 3vh margin-top: 3vh
#contact-message #contact-message
margin-top: 2vh margin-top: 2vh
p p
color: $green color: $green
span span
text-decoration: underline $green text-decoration: underline $green
.h-captcha .h-captcha
margin-bottom: 0.5vh margin-bottom: 0.5vh
.button-c .button-c
display: inline-block display: inline-block
font-weight: 400 font-weight: 400
color: #212529 color: #212529
text-align: center text-align: center
vertical-align: middle vertical-align: middle
cursor: pointer cursor: pointer
user-select: none user-select: none
border: 1px solid $black border: 1px solid $black
padding: 0.375rem 0.75rem padding: 0.375rem 0.75rem
font-size: 1rem font-size: 1rem
line-height: 1.5 line-height: 1.5
border-radius: 0.25rem 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 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" font-family: "Apercu Mono"
.button-c .button-c
background-color: $pink background-color: $pink
.button-c:hover .button-c:hover
background-color: $black background-color: $black
color: $pink color: $pink
border-color: $pink border-color: $pink
// Nav stuff // Nav stuff
.ham .ham
width: 30px width: 30px
height: 20px height: 20px
position: relative position: relative
margin: 0px margin: 0px
-webkit-transform: rotate(0deg) -webkit-transform: rotate(0deg)
-moz-transform: rotate(0deg) -moz-transform: rotate(0deg)
-o-transform: rotate(0deg) -o-transform: rotate(0deg)
transform: rotate(0deg) transform: rotate(0deg)
-webkit-transition: .5s ease-in-out -webkit-transition: .5s ease-in-out
-moz-transition: .5s ease-in-out -moz-transition: .5s ease-in-out
-o-transition: .5s ease-in-out -o-transition: .5s ease-in-out
transition: .5s ease-in-out transition: .5s ease-in-out
cursor: pointer cursor: pointer
.ham span .ham span
display: block display: block
position: absolute position: absolute
height: 3px height: 3px
width: 100% width: 100%
border-radius: 9px border-radius: 9px
opacity: 1 opacity: 1
left: 0 left: 0
-webkit-transform: rotate(0deg) -webkit-transform: rotate(0deg)
-moz-transform: rotate(0deg) -moz-transform: rotate(0deg)
-o-transform: rotate(0deg) -o-transform: rotate(0deg)
transform: rotate(0deg) transform: rotate(0deg)
-webkit-transition: .25s ease-in-out -webkit-transition: .25s ease-in-out
-moz-transition: .25s ease-in-out -moz-transition: .25s ease-in-out
-o-transition: .25s ease-in-out -o-transition: .25s ease-in-out
transition: .25s ease-in-out transition: .25s ease-in-out
background: $pink background: $pink
.ham span:nth-child(1) .ham span:nth-child(1)
top: 0 top: 0
.ham span:nth-child(2), .ham span:nth-child(3) .ham span:nth-child(2), .ham span:nth-child(3)
top: 10px top: 10px
.ham span:nth-child(4) .ham span:nth-child(4)
top: 20px top: 20px
.ham.open span:nth-child(1) .ham.open span:nth-child(1)
top: 11px top: 11px
width: 0 width: 0
left: 50% left: 50%
.ham.open span:nth-child(2) .ham.open span:nth-child(2)
-webkit-transform: rotate(45deg) -webkit-transform: rotate(45deg)
-moz-transform: rotate(45deg) -moz-transform: rotate(45deg)
-o-transform: rotate(45deg) -o-transform: rotate(45deg)
transform: rotate(45deg) transform: rotate(45deg)
.ham.open span:nth-child(3) .ham.open span:nth-child(3)
-webkit-transform: rotate(-45deg) -webkit-transform: rotate(-45deg)
-moz-transform: rotate(-45deg) -moz-transform: rotate(-45deg)
-o-transform: rotate(-45deg) -o-transform: rotate(-45deg)
transform: rotate(-45deg) transform: rotate(-45deg)
.ham.open span:nth-child(4) .ham.open span:nth-child(4)
top: 11px top: 11px
width: 0 width: 0
left: 50% left: 50%
@media only screen and (max-height: 421px) @media only screen and (max-height: 421px)
.pr-text .pr-text
margin-bottom: 5vh !important margin-bottom: 5vh !important
@media only screen and (max-width: 575px) @media only screen and (max-width: 575px)
.logo .logo
height: 5rem height: 5rem
.logos-container .logos-container
width: 5rem width: 5rem
.aaa .aaa
min-height: 40vh !important min-height: 40vh !important
.aaaa .aaaa
margin-top: 5vh !important margin-top: 5vh !important
.ef .ef
max-height: none !important max-height: none !important
min-height: 0 !important min-height: 0 !important
.ff .ff
min-height: 82.8vh !important min-height: 82.8vh !important
@media only screen and (max-height: 815px) @media only screen and (max-height: 815px)
.ef .ef
max-height: none !important max-height: none !important
min-height: 0 !important min-height: 0 !important

View File

@@ -3,25 +3,35 @@ const axios = require('axios');
var router = express.Router(); var router = express.Router();
/* GET home page. */ /* GET home page. */
router.get('/', function(req, res, next) { router.get('/', function (req, res, _next) {
const GHOST_KEY = process.env.GHOST_KEY const GHOST_KEY = process.env.GHOST_KEY;
const base_url = `https://blog.pastel.codes/ghost/api/v3/content/posts/?key=${GHOST_KEY}` const base_url = `https://blog.pastel.codes/ghost/api/v3/content/posts/?key=${GHOST_KEY}`;
axios.all([ axios
axios.get(`${base_url}&limit=3`), .all([
axios.get(`${base_url}&limit=3&filter=tag:project`), axios.get(`${base_url}&limit=3`),
axios.get(`${base_url}&limit=3&filter=tag:project`),
]) ])
.then(axios.spread((response1, response2) => { .then(
var base = { title: 'About', description: 'Who??? What??? AAAAaaa, about me.'}; axios.spread((response1, response2) => {
var blog = JSON.parse(JSON.stringify(response1.data).split('"posts":').join('"blog":')); var base = {
var projects = JSON.parse(JSON.stringify(response2.data).split('"posts":').join('"project":')); title: 'About',
var out = Object.assign(base, blog, projects); 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); res.render('about', out);
})) })
.catch(error => { )
console.log(error); .catch((error) => {
}); console.log(error);
});
}); });
module.exports = router; module.exports = router;

View File

@@ -1,73 +1,80 @@
var express = require('express'); var express = require('express');
var rate_limit = require("express-rate-limit") var rate_limit = require('express-rate-limit');
const {verify} = require('hcaptcha'); const { verify } = require('hcaptcha');
const nodemailer = require('nodemailer')
var router = express.Router(); var router = express.Router();
const sgMail = require('@sendgrid/mail'); const sgMail = require('@sendgrid/mail');
sgMail.setApiKey(process.env.SENDGRID_API_KEY); sgMail.setApiKey(process.env.SENDGRID_API_KEY);
const contact_rate_limit = rate_limit({ const contact_rate_limit = rate_limit({
windowMs: 10 * 60 * 1000, // 10 minutes windowMs: 10 * 60 * 1000, // 10 minutes
max: 5, // limit each IP to 10 requests per windowMs max: 5, // limit each IP to 10 requests per windowMs
message: "Too many contact requests, try again later.", message: 'Too many contact requests, try again later.',
handler: function (req, res /*, next*/) { handler: function (req, res /*, next*/) {
res.render('error', { res.render('error', {
title: "Error", title: 'Error',
message: "Too many contact requests, try again later.", message: 'Too many contact requests, try again later.',
error: {status: null} error: { status: null },
}) });
}, },
}); });
// POST route from contact form // POST route from contact form
router.post('/', contact_rate_limit, (req, res) => { router.post('/', contact_rate_limit, (req, res) => {
const TO_MAIL_USER = process.env.TO_MAIL_USER const TO_MAIL_USER = process.env.TO_MAIL_USER;
const FROM_MAIL_USER = process.env.FROM_MAIL_USER const FROM_MAIL_USER = process.env.FROM_MAIL_USER;
const HCAPTCHA_KEY = process.env.HCAPTCHA_KEY const HCAPTCHA_KEY = process.env.HCAPTCHA_KEY;
const REPLY_TO_MAIL = process.env.REPLY_TO_MAIL const REPLY_TO_MAIL = process.env.REPLY_TO_MAIL;
const token = req.body["g-recaptcha-response"]; const token = req.body['g-recaptcha-response'];
const ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress; const ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress;
verify(HCAPTCHA_KEY, token) verify(HCAPTCHA_KEY, token)
.then((data) => { .then((data) => {
if (data.success === true) { if (data.success === true) {
const msg = { const msg = {
to: TO_MAIL_USER, to: TO_MAIL_USER,
from: FROM_MAIL_USER, from: FROM_MAIL_USER,
subject: 'New message from contact form at pastel.codes', 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}` text: `${req.body.firstname} ${req.body.lastname} (${req.body.email})\nsays: ${req.body.message}\n\nip: ${ip}`,
}; };
sgMail sgMail
.send(msg) .send(msg)
.then(() => { .then(() => {
res.render('contact', { res.render('contact', {
title: 'Contact', title: 'Contact',
message: "I will get back to you soon!", message: 'I will get back to you soon!',
success: "Make sure the email is from ", success: 'Make sure the email is from ',
email: REPLY_TO_MAIL email: REPLY_TO_MAIL,
}) });
}) })
.catch(error => { .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 => {
console.log(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. */ /* GET home page. */
router.get('/', function (req, res, next) { router.get('/', function (req, res, _next) {
res.render('contact', {title: 'Contact', description: "Contact me!"}); res.render('contact', { title: 'Contact', description: 'Contact me!' });
}); });
module.exports = router; module.exports = router;

View File

@@ -2,8 +2,8 @@ var express = require('express');
var router = express.Router(); var router = express.Router();
/* GET home page. */ /* GET home page. */
router.get('/', function(req, res, next) { router.get('/', function (req, res, _next) {
res.render('index', { title: 'Home', description: "Hello, I'm E" }); res.render('index', { title: 'Home', description: "Hello, I'm E" });
}); });
module.exports = router; module.exports = router;

View File

@@ -1,3 +1,24 @@
@tailwind base; @tailwind base;
@tailwind components; @tailwind components;
@font-face {
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-face {
font-family: 'Apercu Mono';
src: url('../fonts/ApercuMono.ttf') format('truetype');
}
.wavy {
text-decoration: underline;
text-decoration-style: wavy;
}
@tailwind utilities; @tailwind utilities;

View File

@@ -1,12 +1,31 @@
module.exports = { module.exports = {
mode: "jit", mode: 'jit',
purge: ['../views/*.pug'], purge: ['views/*.pug'],
darkMode: false, // or 'media' or 'class' darkMode: false, // or 'media' or 'class'
theme: { theme: {
extend: {}, extend: {
fontFamily: {
extra: ['"Titling Gothic FB"'],
sans: ['Gilroy'],
mono: ['"Apercu Mono"'],
},
colors: {
transparent: 'transparent',
current: 'currentColor',
black: {
DEFAULT: '#002234',
},
pink: {
DEFAULT: '#CC7A98',
},
green: {
DEFAULT: '#CDE7B0',
},
},
},
}, },
variants: { variants: {
extend: {}, extend: {},
}, },
plugins: [], plugins: [require('tailwind-hamburgers')],
} };

View File

@@ -1,68 +1,62 @@
extends layout extends layout
block nav-links block nav-links
li.nav-item a(href='/')
a.nav-link(href='/') li(class="py-3 bg-pink text-black hover:bg-black hover:text-pink transition duration-500 ease-in-out")
span Home span Home
li.nav-item.active a(href='#')
a.nav-link(href='#') li(class="py-3 bg-black text-green hover:bg-pink hover:text-black transition duration-500 ease-in-out")
span About span About
li.nav-item a(href='#')
a.nav-link(href='#') li(class="py-3 bg-pink text-black hover:bg-black hover:text-pink transition duration-500 ease-in-out")
span CV span CV
li.nav-item a(href='https://github.com/aurora-dot')
a.nav-link(href='https://github.com/aurora-dot') li(class="py-3 bg-pink text-black hover:bg-black hover:text-pink transition duration-500 ease-in-out")
span Projects span Projects
li.nav-item a(href='https://blog.pastel.codes')
a.nav-link(href='https://blog.pastel.codes') li(class="py-3 bg-pink text-black hover:bg-black hover:text-pink transition duration-500 ease-in-out")
span Blog span Blog
li.nav-item a(href='/contact')
a.nav-link(href='/contact') li(class="py-3 bg-pink text-black hover:bg-black hover:text-pink transition duration-500 ease-in-out")
span Contact span Contact
block content block content
.container div.mt-5
.about-pos div.text-lg
.row h1.font-sans.text-6xl.wavy.mb-10 Hello.
.col p.mb-5 Im E, a 20 year old student in 3rd year of university, who studies computer science & artificial intelligence, somehow achieved a 1:1 for the previous two years.
h1 p.mb-5 In my free time, I create small projects to learn new skills to be helpful for others, recently i have been focusing on Django and tailwind for my job.
span Hello. p.mb-5 Graphic design is also very fun and i enjoy making small projects to post on instagram, it has helped a lot with UX/UI design for applications.
p Im E, a 20 year old student in 3rd year of university, who studies computer science & artificial intelligence. p.mb-5 Currently I am working as a freelance developer for Bounce Technologies!
p In my free time, I create small projects to learn new skills to be helpful for others, recently i have been focusing on node.js. div
p Graphic design is also very fun and i enjoy making small projects to post on instagram, it helps with programming too which is neat h1.font-sans.text-6xl.wavy.my-10 Projects.
.row
.col.start
h1
span Projects.
.row
div
each val in project each val in project
.col div(class="mb-10 text-center sm:text-left")
.pr div.contents
a(href=val.url) a(href=val.url).contents
if val.feature_image if val.feature_image
img(src=val.feature_image) img(class="sm:w-2/3 mx-auto sm:mx-0" src=val.feature_image)
else else
img(src="/images/logo.png") img(src="/images/logo.png")
.pr-text div.mt-2
a(href=val.url) a(href=val.url)
h1 #{val.title} span(class="font-sans text-2xl sm:text-3xl mt-3 mb-3") #{val.title}
p #{val.excerpt} p.text-lg #{val.excerpt}
.row div
.col.start h1.font-sans.text-6xl.wavy.my-10 Blog.
h1 div
span Blog.
.row
each val in blog each val in blog
.col div(class="mb-10 text-center sm:text-left")
.pr div.contents
a(href=val.url) a(href=val.url).contents
if val.feature_image if val.feature_image
img(src=val.feature_image) img(class="sm:w-2/3 mx-auto sm:mx-0" src=val.feature_image)
else else
img(src="/images/logo.png") img(src="/images/logo.png")
.pr-text div.mt-2
a(href=val.url) a(href=val.url)
h1 #{val.title} span(class="font-sans text-2xl sm:text-3xl mt-3 mb-3") #{val.title}
p #{val.excerpt} p.text-lg #{val.excerpt}

View File

@@ -4,57 +4,56 @@ block head
script(src='https://hcaptcha.com/1/api.js' async='' defer='defer') script(src='https://hcaptcha.com/1/api.js' async='' defer='defer')
block nav-links block nav-links
li.nav-item a(href='/')
a.nav-link(href='/') li(class="py-3 bg-pink text-black hover:bg-black hover:text-pink transition duration-500 ease-in-out")
span Home span Home
li.nav-item a(href='/about')
a.nav-link(href='/about') li(class="py-3 bg-pink text-black hover:bg-black hover:text-pink transition duration-500 ease-in-out")
span About span About
li.nav-item a(href='#')
a.nav-link(href='#') li(class="py-3 bg-pink text-black hover:bg-black hover:text-pink transition duration-500 ease-in-out")
span CV span CV
li.nav-item a(href='https://github.com/aurora-dot')
a.nav-link(href='https://github.com/aurora-dot') li(class="py-3 bg-pink text-black hover:bg-black hover:text-pink transition duration-500 ease-in-out")
span Projects span Projects
li.nav-item a(href='https://blog.pastel.codes')
a.nav-link(href='https://blog.pastel.codes') li(class="py-3 bg-pink text-black hover:bg-black hover:text-pink transition duration-500 ease-in-out")
span Blog span Blog
li.nav-item.active a(href='#')
a.nav-link(href='#') li(class="py-3 bg-black text-green hover:bg-pink hover:text-black transition duration-500 ease-in-out")
span Contact span Contact
block content block content
.container div.w-full
.row div
.col h1.font-sans.text-6xl.wavy.mb-10 Contact.
h1
span Contact.
.row
.col
form#contact-form(action='/contact' method='post' role='form')
.form-group
label Name
.form-row
.col
input#fname(name='firstname' class="form-control" type='text' placeholder='First name' required="true" pattern="^[\\w'\\-,.][^0-9_!¡?÷?¿/\\\\+=@#$%ˆ&*(){}|~<>;:[\\]]{2,}$")
.col
input#lname(name='lastname' class="form-control" type='text' placeholder='Last name' required="true" pattern="^[\\w'\\-,.][^0-9_!¡?÷?¿/\\\\+=@#$%ˆ&*(){}|~<>;:[\\]]{2,}$")
.form-group div
label(for='email') Email form#contact-form(action='/contact' method='post' role='form')
input#email(name='email' class="form-control" type='text' placeholder='Email (example@email.com)' required='true' pattern="[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,4}$") div.mb-5
.form-group label Name
label(for='message') Message div(class="sm:flex sm:flex-row")
textarea#message(name='message' class="form-control" placeholder='Enter your message here' rows='3' required='true') .flex.w-full
.form-group(style="margin-bottom: 0.5rem") input#fname(class="w-full border-2 border-pink bg-black p-2 text-base" name='firstname' class="form-control" type='text' placeholder='First name' required="true")
.h-captcha(data-sitekey='49abba50-1813-4ab3-acbf-2a8bfff1f7c3') div(class="mb-3 sm:mb-0 sm:ml-5")
button(type='submit' class="button-c") Submit .flex.w-full
input#lname(class="w-full border-2 border-pink bg-black p-2 text-base" name='lastname' class="form-control" type='text' placeholder='Last name' required="true")
.row div.mb-5
.col label(for='email') Email
if message input#email(class="w-full border-2 border-pink bg-black p-2 text-base" name='email' class="form-control" type='text' placeholder='Email (example@email.com)' required='true' pattern="[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,4}$")
div.mb-5
label(for='message') Message
textarea#message(class="w-full border-2 border-pink bg-black p-2 text-base" name='message' class="form-control" placeholder='Enter your message here' rows='3' required='true')
div(class="mb-5 justify-center sm:justify-items-start flex sm:block")
.h-captcha(data-sitekey='49abba50-1813-4ab3-acbf-2a8bfff1f7c3')
button(type='submit' class="rounded-lg px-3 py-2 bg-pink text-black text-lg hover:ring-pink hover:ring-2 hover:bg-black hover:text-pink sm:w-auto w-full sm:text-base") Submit
div
if message
div(class="mt-10 mb-6 sm:text-left text-center")
#contact-message #contact-message
p=message p=message
if success if success
p=success p=success
span#email=email span#email.text-green=email

View File

@@ -1,73 +1,69 @@
extends layout extends layout
block nav-links block nav-links
li.nav-item.active a(href='#')
a.nav-link(href='#') li(class="py-3 bg-black text-green hover:bg-pink hover:text-black transition duration-500 ease-in-out")
span Home span Home
li.nav-item a(href='/about')
a.nav-link(href='/about') li(class="py-3 bg-pink text-black hover:bg-black hover:text-pink transition duration-500 ease-in-out")
span About span About
li.nav-item a(href='#')
a.nav-link(href='#') li(class="py-3 bg-pink text-black hover:bg-black hover:text-pink transition duration-500 ease-in-out")
span CV span CV
li.nav-item a(href='https://github.com/aurora-dot')
a.nav-link(href='https://github.com/aurora-dot') li(class="py-3 bg-pink text-black hover:bg-black hover:text-pink transition duration-500 ease-in-out")
span Projects span Projects
li.nav-item a(href='https://blog.pastel.codes')
a.nav-link(href='https://blog.pastel.codes') li(class="py-3 bg-pink text-black hover:bg-black hover:text-pink transition duration-500 ease-in-out")
span Blog span Blog
li.nav-item a(href='/contact')
a.nav-link(href='/contact') li(class="py-3 bg-pink text-black hover:bg-black hover:text-pink transition duration-500 ease-in-out")
span Contact span Contact
block content block content
.container-fluid div(class="flex sm:w-2/4 items-center sm:my-0 mt-10 mb-16")
.row div.text-2xl
.col-sm-2 h1(class="font-sans text-7xl pb-5 sm:pb-10")
.center-v.col-sm-4.aaa.ef | Hello,
div br
h1 | I'm
| Hello, |
br span.wavy E
| I'm p I'm a Programmer &amp; Designer from the UK.
| p.pt-5 I like to make stuff.
span E
p I'm a Programmer & Designer from the UK.
p I like to make stuff.
.col-sm-2.aaaa
.col-sm.pink-block.ef
.center-v-h.ef
.logos-container
a(class="logo-container" id="email" target="_blank")
svg(class="logo" role='img' style="margin-top: 2.5rem;" viewbox='0 0 24 24' xmlns='http://www.w3.org/2000/svg')
title Mail icon
path(d='M11.585 5.267c1.834 0 3.558.811 4.824 2.08v.004c0-.609.41-1.068.979-1.068h.145c.891 0 1.073.842 1.073 1.109l.005 9.475c-.063.621.64.941 1.029.543 1.521-1.564 3.342-8.038-.946-11.79-3.996-3.497-9.357-2.921-12.209-.955-3.031 2.091-4.971 6.718-3.086 11.064 2.054 4.74 7.931 6.152 11.424 4.744 1.769-.715 2.586 1.676.749 2.457-2.776 1.184-10.502 1.064-14.11-5.188C-.977 13.521-.847 6.093 5.62 2.245 10.567-.698 17.09.117 21.022 4.224c4.111 4.294 3.872 12.334-.139 15.461-1.816 1.42-4.516.037-4.498-2.031l-.019-.678c-1.265 1.256-2.948 1.988-4.782 1.988-3.625 0-6.813-3.189-6.813-6.812 0-3.659 3.189-6.885 6.814-6.885zm4.561 6.623c-.137-2.653-2.106-4.249-4.484-4.249h-.09c-2.745 0-4.268 2.159-4.268 4.61 0 2.747 1.842 4.481 4.256 4.481 2.693 0 4.464-1.973 4.592-4.306l-.006-.536z')
a(class="logo-container" href="https://github.com/aurora-dot" target="_blank")
svg(class="logo" role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg")
title GitHub icon
path(d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12")
a(class="logo-container" href="https://git.pastel.codes/Blankie" target="_blank")
svg(class="logo" role='img' viewbox='0 0 24 24' xmlns='http://www.w3.org/2000/svg')
title Gitea icon
path(d='M4.186 5.421C2.341 5.417-.13 6.59.006 9.531c.213 4.594 4.92 5.02 6.801 5.057.206.862 2.42 3.834 4.059 3.99h7.18c4.306-.286 7.53-13.022 5.14-13.07-3.953.186-6.296.28-8.305.296v3.975l-.626-.277-.004-3.696c-2.306-.001-4.336-.108-8.189-.298-.482-.003-1.154-.085-1.876-.087zm.261 1.625h.22c.262 2.355.688 3.732 1.55 5.836-2.2-.26-4.072-.899-4.416-3.285-.178-1.235.422-2.524 2.646-2.552zm8.557 2.315c.15.002.303.03.447.096l.749.323-.537.979a.672.597 0 0 0-.241.038.672.597 0 0 0-.405.764.672.597 0 0 0 .112.174l-.926 1.686a.672.597 0 0 0-.222.038.672.597 0 0 0-.405.764.672.597 0 0 0 .86.36.672.597 0 0 0 .404-.765.672.597 0 0 0-.158-.22l.902-1.642a.672.597 0 0 0 .293-.03.672.597 0 0 0 .213-.112c.348.146.633.265.838.366.308.152.417.253.45.365.033.11-.003.322-.177.694-.13.277-.345.67-.599 1.133a.672.597 0 0 0-.251.038.672.597 0 0 0-.405.764.672.597 0 0 0 .86.36.672.597 0 0 0 .404-.764.672.597 0 0 0-.137-.202c.251-.458.467-.852.606-1.148.188-.402.286-.701.2-.99-.086-.289-.35-.477-.7-.65-.23-.113-.517-.233-.86-.377a.672.597 0 0 0-.038-.239.672.597 0 0 0-.145-.209l.528-.963 2.924 1.263c.528.229.746.79.49 1.26l-2.01 3.68c-.257.469-.888.663-1.416.435l-4.137-1.788c-.528-.228-.747-.79-.49-1.26l2.01-3.679c.176-.323.53-.515.905-.53h.064z')
a(class="logo-container" href="https://blog.pastel.codes" target="_blank")
svg(class="logo" role='img' viewbox='0 0 24 24' xmlns='http://www.w3.org/2000/svg')
title Ghost icon
path(d='M9.604 19.199H.008V24h9.597v-4.801zm14.39 0h-9.591V24h9.591v-4.801zm.003-9.599H0v4.8h23.997V9.6zM24 0h-4.801v4.801H24V0zm-9.596 0H.008v4.801h14.396V0z')
a(class="logo-container" href="https://matrix.to/#/@blankie:matrix.pastel.codes" target="_blank")
svg(class="logo" role='img' viewbox='0 0 24 24' xmlns='http://www.w3.org/2000/svg')
title Matrix icon
path(d='M.632.55v22.9H2.28V24H0V0h2.28v.55zm7.043 7.26v1.157h.033c.309-.443.683-.784 1.117-1.024.433-.245.936-.365 1.5-.365.54 0 1.033.107 1.481.314.448.208.785.582 1.02 1.108.254-.374.6-.706 1.034-.992.434-.287.95-.43 1.546-.43.453 0 .872.056 1.26.167.388.11.716.286.993.53.276.245.489.559.646.951.152.392.23.863.23 1.417v5.728h-2.349V11.52c0-.286-.01-.559-.032-.812a1.755 1.755 0 0 0-.18-.66 1.106 1.106 0 0 0-.438-.448c-.194-.11-.457-.166-.785-.166-.332 0-.6.064-.803.189a1.38 1.38 0 0 0-.48.499 1.946 1.946 0 0 0-.231.696 5.56 5.56 0 0 0-.06.785v4.768h-2.35v-4.8c0-.254-.004-.503-.018-.752a2.074 2.074 0 0 0-.143-.688 1.052 1.052 0 0 0-.415-.503c-.194-.125-.476-.19-.854-.19-.111 0-.259.024-.439.074-.18.051-.36.143-.53.282-.171.138-.319.337-.439.595-.12.259-.18.6-.18 1.02v4.966H5.46V7.81zm15.693 15.64V.55H21.72V0H24v24h-2.28v-.55z')
a(class="logo-container" href="https://twitter.com/ErrorFacade" target="_blank")
svg(class="logo" role='img' viewbox='0 0 24 24' xmlns='http://www.w3.org/2000/svg')
title Twitter icon
path(d='M23.954 4.569c-.885.389-1.83.654-2.825.775 1.014-.611 1.794-1.574 2.163-2.723-.951.555-2.005.959-3.127 1.184-.896-.959-2.173-1.559-3.591-1.559-2.717 0-4.92 2.203-4.92 4.917 0 .39.045.765.127 1.124C7.691 8.094 4.066 6.13 1.64 3.161c-.427.722-.666 1.561-.666 2.475 0 1.71.87 3.213 2.188 4.096-.807-.026-1.566-.248-2.228-.616v.061c0 2.385 1.693 4.374 3.946 4.827-.413.111-.849.171-1.296.171-.314 0-.615-.03-.916-.086.631 1.953 2.445 3.377 4.604 3.417-1.68 1.319-3.809 2.105-6.102 2.105-.39 0-.779-.023-1.17-.067 2.189 1.394 4.768 2.209 7.557 2.209 9.054 0 13.999-7.496 13.999-13.986 0-.209 0-.42-.015-.63.961-.689 1.8-1.56 2.46-2.548l-.047-.02z')
a(class="logo-container" href="https://instagram.com/_e.psd" target="_blank")
svg(class="logo" role='img' viewbox='0 0 24 24' xmlns='http://www.w3.org/2000/svg')
title Instagram icon
path(d='M12 0C8.74 0 8.333.015 7.053.072 5.775.132 4.905.333 4.14.63c-.789.306-1.459.717-2.126 1.384S.935 3.35.63 4.14C.333 4.905.131 5.775.072 7.053.012 8.333 0 8.74 0 12s.015 3.667.072 4.947c.06 1.277.261 2.148.558 2.913.306.788.717 1.459 1.384 2.126.667.666 1.336 1.079 2.126 1.384.766.296 1.636.499 2.913.558C8.333 23.988 8.74 24 12 24s3.667-.015 4.947-.072c1.277-.06 2.148-.262 2.913-.558.788-.306 1.459-.718 2.126-1.384.666-.667 1.079-1.335 1.384-2.126.296-.765.499-1.636.558-2.913.06-1.28.072-1.687.072-4.947s-.015-3.667-.072-4.947c-.06-1.277-.262-2.149-.558-2.913-.306-.789-.718-1.459-1.384-2.126C21.319 1.347 20.651.935 19.86.63c-.765-.297-1.636-.499-2.913-.558C15.667.012 15.26 0 12 0zm0 2.16c3.203 0 3.585.016 4.85.071 1.17.055 1.805.249 2.227.415.562.217.96.477 1.382.896.419.42.679.819.896 1.381.164.422.36 1.057.413 2.227.057 1.266.07 1.646.07 4.85s-.015 3.585-.074 4.85c-.061 1.17-.256 1.805-.421 2.227-.224.562-.479.96-.899 1.382-.419.419-.824.679-1.38.896-.42.164-1.065.36-2.235.413-1.274.057-1.649.07-4.859.07-3.211 0-3.586-.015-4.859-.074-1.171-.061-1.816-.256-2.236-.421-.569-.224-.96-.479-1.379-.899-.421-.419-.69-.824-.9-1.38-.165-.42-.359-1.065-.42-2.235-.045-1.26-.061-1.649-.061-4.844 0-3.196.016-3.586.061-4.861.061-1.17.255-1.814.42-2.234.21-.57.479-.96.9-1.381.419-.419.81-.689 1.379-.898.42-.166 1.051-.361 2.221-.421 1.275-.045 1.65-.06 4.859-.06l.045.03zm0 3.678c-3.405 0-6.162 2.76-6.162 6.162 0 3.405 2.76 6.162 6.162 6.162 3.405 0 6.162-2.76 6.162-6.162 0-3.405-2.76-6.162-6.162-6.162zM12 16c-2.21 0-4-1.79-4-4s1.79-4 4-4 4 1.79 4 4-1.79 4-4 4zm7.846-10.405c0 .795-.646 1.44-1.44 1.44-.795 0-1.44-.646-1.44-1.44 0-.794.646-1.439 1.44-1.439.793-.001 1.44.645 1.44 1.439z')
.col-sm-2 div(class="sm:w-1/4")
div(id="side-social" c class="flex bg-pink justify-center sm:w-1/4")
div(class="w-16 sm:w-14 fill-current text-black flex flex-col justify-around")
a(id="email" target="_blank")
svg.mt-5(role='img' viewbox='0 0 24 24' xmlns='http://www.w3.org/2000/svg')
title Mail icon
path(d='M11.585 5.267c1.834 0 3.558.811 4.824 2.08v.004c0-.609.41-1.068.979-1.068h.145c.891 0 1.073.842 1.073 1.109l.005 9.475c-.063.621.64.941 1.029.543 1.521-1.564 3.342-8.038-.946-11.79-3.996-3.497-9.357-2.921-12.209-.955-3.031 2.091-4.971 6.718-3.086 11.064 2.054 4.74 7.931 6.152 11.424 4.744 1.769-.715 2.586 1.676.749 2.457-2.776 1.184-10.502 1.064-14.11-5.188C-.977 13.521-.847 6.093 5.62 2.245 10.567-.698 17.09.117 21.022 4.224c4.111 4.294 3.872 12.334-.139 15.461-1.816 1.42-4.516.037-4.498-2.031l-.019-.678c-1.265 1.256-2.948 1.988-4.782 1.988-3.625 0-6.813-3.189-6.813-6.812 0-3.659 3.189-6.885 6.814-6.885zm4.561 6.623c-.137-2.653-2.106-4.249-4.484-4.249h-.09c-2.745 0-4.268 2.159-4.268 4.61 0 2.747 1.842 4.481 4.256 4.481 2.693 0 4.464-1.973 4.592-4.306l-.006-.536z')
a(href="https://github.com/aurora-dot" target="_blank")
svg.mt-5(role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg")
title GitHub icon
path(d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12")
a(href="https://git.pastel.codes/Blankie" target="_blank")
svg.mt-5(role='img' viewbox='0 0 24 24' xmlns='http://www.w3.org/2000/svg')
title Gitea icon
path(d='M4.186 5.421C2.341 5.417-.13 6.59.006 9.531c.213 4.594 4.92 5.02 6.801 5.057.206.862 2.42 3.834 4.059 3.99h7.18c4.306-.286 7.53-13.022 5.14-13.07-3.953.186-6.296.28-8.305.296v3.975l-.626-.277-.004-3.696c-2.306-.001-4.336-.108-8.189-.298-.482-.003-1.154-.085-1.876-.087zm.261 1.625h.22c.262 2.355.688 3.732 1.55 5.836-2.2-.26-4.072-.899-4.416-3.285-.178-1.235.422-2.524 2.646-2.552zm8.557 2.315c.15.002.303.03.447.096l.749.323-.537.979a.672.597 0 0 0-.241.038.672.597 0 0 0-.405.764.672.597 0 0 0 .112.174l-.926 1.686a.672.597 0 0 0-.222.038.672.597 0 0 0-.405.764.672.597 0 0 0 .86.36.672.597 0 0 0 .404-.765.672.597 0 0 0-.158-.22l.902-1.642a.672.597 0 0 0 .293-.03.672.597 0 0 0 .213-.112c.348.146.633.265.838.366.308.152.417.253.45.365.033.11-.003.322-.177.694-.13.277-.345.67-.599 1.133a.672.597 0 0 0-.251.038.672.597 0 0 0-.405.764.672.597 0 0 0 .86.36.672.597 0 0 0 .404-.764.672.597 0 0 0-.137-.202c.251-.458.467-.852.606-1.148.188-.402.286-.701.2-.99-.086-.289-.35-.477-.7-.65-.23-.113-.517-.233-.86-.377a.672.597 0 0 0-.038-.239.672.597 0 0 0-.145-.209l.528-.963 2.924 1.263c.528.229.746.79.49 1.26l-2.01 3.68c-.257.469-.888.663-1.416.435l-4.137-1.788c-.528-.228-.747-.79-.49-1.26l2.01-3.679c.176-.323.53-.515.905-.53h.064z')
a(href="https://blog.pastel.codes" target="_blank")
svg.mt-5(role='img' viewbox='0 0 24 24' xmlns='http://www.w3.org/2000/svg')
title Ghost icon
path(d='M9.604 19.199H.008V24h9.597v-4.801zm14.39 0h-9.591V24h9.591v-4.801zm.003-9.599H0v4.8h23.997V9.6zM24 0h-4.801v4.801H24V0zm-9.596 0H.008v4.801h14.396V0z')
a(href="https://matrix.to/#/@blankie:matrix.pastel.codes" target="_blank")
svg.mt-5(role='img' viewbox='0 0 24 24' xmlns='http://www.w3.org/2000/svg')
title Matrix icon
path(d='M.632.55v22.9H2.28V24H0V0h2.28v.55zm7.043 7.26v1.157h.033c.309-.443.683-.784 1.117-1.024.433-.245.936-.365 1.5-.365.54 0 1.033.107 1.481.314.448.208.785.582 1.02 1.108.254-.374.6-.706 1.034-.992.434-.287.95-.43 1.546-.43.453 0 .872.056 1.26.167.388.11.716.286.993.53.276.245.489.559.646.951.152.392.23.863.23 1.417v5.728h-2.349V11.52c0-.286-.01-.559-.032-.812a1.755 1.755 0 0 0-.18-.66 1.106 1.106 0 0 0-.438-.448c-.194-.11-.457-.166-.785-.166-.332 0-.6.064-.803.189a1.38 1.38 0 0 0-.48.499 1.946 1.946 0 0 0-.231.696 5.56 5.56 0 0 0-.06.785v4.768h-2.35v-4.8c0-.254-.004-.503-.018-.752a2.074 2.074 0 0 0-.143-.688 1.052 1.052 0 0 0-.415-.503c-.194-.125-.476-.19-.854-.19-.111 0-.259.024-.439.074-.18.051-.36.143-.53.282-.171.138-.319.337-.439.595-.12.259-.18.6-.18 1.02v4.966H5.46V7.81zm15.693 15.64V.55H21.72V0H24v24h-2.28v-.55z')
a(href="https://twitter.com/ErrorFacade" target="_blank")
svg.mt-5(role='img' viewbox='0 0 24 24' xmlns='http://www.w3.org/2000/svg')
title Twitter icon
path(d='M23.954 4.569c-.885.389-1.83.654-2.825.775 1.014-.611 1.794-1.574 2.163-2.723-.951.555-2.005.959-3.127 1.184-.896-.959-2.173-1.559-3.591-1.559-2.717 0-4.92 2.203-4.92 4.917 0 .39.045.765.127 1.124C7.691 8.094 4.066 6.13 1.64 3.161c-.427.722-.666 1.561-.666 2.475 0 1.71.87 3.213 2.188 4.096-.807-.026-1.566-.248-2.228-.616v.061c0 2.385 1.693 4.374 3.946 4.827-.413.111-.849.171-1.296.171-.314 0-.615-.03-.916-.086.631 1.953 2.445 3.377 4.604 3.417-1.68 1.319-3.809 2.105-6.102 2.105-.39 0-.779-.023-1.17-.067 2.189 1.394 4.768 2.209 7.557 2.209 9.054 0 13.999-7.496 13.999-13.986 0-.209 0-.42-.015-.63.961-.689 1.8-1.56 2.46-2.548l-.047-.02z')
a(href="https://instagram.com/_e.psd" target="_blank")
svg.my-5(role='img' viewbox='0 0 24 24' xmlns='http://www.w3.org/2000/svg')
title Instagram icon
path(d='M12 0C8.74 0 8.333.015 7.053.072 5.775.132 4.905.333 4.14.63c-.789.306-1.459.717-2.126 1.384S.935 3.35.63 4.14C.333 4.905.131 5.775.072 7.053.012 8.333 0 8.74 0 12s.015 3.667.072 4.947c.06 1.277.261 2.148.558 2.913.306.788.717 1.459 1.384 2.126.667.666 1.336 1.079 2.126 1.384.766.296 1.636.499 2.913.558C8.333 23.988 8.74 24 12 24s3.667-.015 4.947-.072c1.277-.06 2.148-.262 2.913-.558.788-.306 1.459-.718 2.126-1.384.666-.667 1.079-1.335 1.384-2.126.296-.765.499-1.636.558-2.913.06-1.28.072-1.687.072-4.947s-.015-3.667-.072-4.947c-.06-1.277-.262-2.149-.558-2.913-.306-.789-.718-1.459-1.384-2.126C21.319 1.347 20.651.935 19.86.63c-.765-.297-1.636-.499-2.913-.558C15.667.012 15.26 0 12 0zm0 2.16c3.203 0 3.585.016 4.85.071 1.17.055 1.805.249 2.227.415.562.217.96.477 1.382.896.419.42.679.819.896 1.381.164.422.36 1.057.413 2.227.057 1.266.07 1.646.07 4.85s-.015 3.585-.074 4.85c-.061 1.17-.256 1.805-.421 2.227-.224.562-.479.96-.899 1.382-.419.419-.824.679-1.38.896-.42.164-1.065.36-2.235.413-1.274.057-1.649.07-4.859.07-3.211 0-3.586-.015-4.859-.074-1.171-.061-1.816-.256-2.236-.421-.569-.224-.96-.479-1.379-.899-.421-.419-.69-.824-.9-1.38-.165-.42-.359-1.065-.42-2.235-.045-1.26-.061-1.649-.061-4.844 0-3.196.016-3.586.061-4.861.061-1.17.255-1.814.42-2.234.21-.57.479-.96.9-1.381.419-.419.81-.689 1.379-.898.42-.166 1.051-.361 2.221-.421 1.275-.045 1.65-.06 4.859-.06l.045.03zm0 3.678c-3.405 0-6.162 2.76-6.162 6.162 0 3.405 2.76 6.162 6.162 6.162 3.405 0 6.162-2.76 6.162-6.162 0-3.405-2.76-6.162-6.162-6.162zM12 16c-2.21 0-4-1.79-4-4s1.79-4 4-4 4 1.79 4 4-1.79 4-4 4zm7.846-10.405c0 .795-.646 1.44-1.44 1.44-.795 0-1.44-.646-1.44-1.44 0-.794.646-1.439 1.44-1.439.793-.001 1.44.645 1.44 1.439z')
block scripts block scripts
script(src="/javascript/index.js") script(src="/javascript/index.js")

View File

@@ -13,37 +13,34 @@ html
link(rel='stylesheet', href='/stylesheets/style.css') link(rel='stylesheet', href='/stylesheets/style.css')
block head block head
body
article
header
// Navbar
nav.navbar
// Navbar brand
a.navbar-brand(href='/')
span EEEE.
// Collapse button
button.navbar-toggler.ham-button(type='button' data-toggle='collapse' data-target='#navbarSupportedContent23' aria-controls='navbarSupportedContent23' aria-expanded='false' aria-label='Toggle navigation' style='cursor: pointer;')
.ham
span
span
span
span
// Collapsible content
#navbarSupportedContent23.collapse.navbar-collapse
// Links
ul.navbar-nav.mr-auto
block nav-links
main body.flex.flex-col.min-h-screen.bg-black.text-pink.font-mono.text-xl
nav
div(class="mx-auto px-5")
div.relative.flex.items-center.justify-between.h-16
div.flex-shrink-0.flex.items-center
p.block.text-3xl.font-extra.font
a(href="/") EEEE.
div(class="absolute inset-y-0 right-0 flex items-center")
div(id="menu").tham.tham-e-squeeze.tham-w-8
div.tham-box
div(class="tham-inner bg-pink")
div
ul(class="hidden transition duration-500 ease-in-out text-center mx-5 list-none mb-5" id="menu-items")
block nav-links
main(class="flex flex-grow sm:items-stretch")
div(class="flex flex-col sm:flex-row flex-grow max-w-4xl mx-auto px-5")
block content block content
footer footer.w-full.text-center.p-4.text-base
p &copy; 2020 | p.font-mono &copy; 2020 |
| |
| |
a(href="/") EEEE. a(href="/").underline EEEE.
script(src="/javascript/jquery-3.5.1.min.js") script(src="/javascript/jquery-3.5.1.min.js")
script(src="/javascript/bootstrap.js")
script(src="/javascript/nav.js") script(src="/javascript/nav.js")
block scripts block scripts