diff --git a/gulpfile.js b/gulpfile.js
index 64d5e1f..4c0f9b1 100644
--- a/gulpfile.js
+++ b/gulpfile.js
@@ -31,7 +31,7 @@ gulp.task("serve_dev", (cb) => {
gulp.task("serve", (cb) => {
console.log('Launching node...');
- spawn('node', [, 'index.js'], {stdio: 'inherit'})
+ spawn('node', ['index.js'], {stdio: 'inherit'})
cb();
});
diff --git a/helpers/view_loader.js b/helpers/view_loader.js
index d1ef5c2..64c128f 100644
--- a/helpers/view_loader.js
+++ b/helpers/view_loader.js
@@ -1,6 +1,7 @@
const pug = require('pug');
-const fs = require('fs/promises');
+const fs = require('fs');
const glob = require('glob');
+const path = require('path');
const cwd = process.cwd();
const layoutdir = cwd + '/view';
@@ -14,17 +15,26 @@ async function loadFile(file) {
}
async function load(name, data) {
+ if (!(await exists(name)))
+ throw new Error("This view does not exist.");
return (await loadFile(layoutdir + '/' + name))(data);
}
+async function exists(name) {
+ return fs.promises.access(layoutdir + '/' + name, fs.constants.R_OK)
+ .then(() => true)
+ .catch(() => false);
+}
+
async function preload() {
- await glob(layoutdir + '/**/*', (err, files) => {
+ await glob(layoutdir + '/**/*.pug', (err, files) => {
files.filter(file => {
- return !file.startsWith('.');
+ return !file.startsWith('.') &&
+ (!fs.lstatSync(file).isDirectory())
}).forEach(file => {
loadFile(file);
});
});
}
-module.exports = { load, loadFile, preload }
\ No newline at end of file
+module.exports = { load, loadFile, preload, exists }
\ No newline at end of file
diff --git a/index.js b/index.js
index d4ef49a..7021bed 100644
--- a/index.js
+++ b/index.js
@@ -8,6 +8,7 @@ const app = express();
const { APP_PORT } = process.env;
app.use(require('./routes'));
+app.use(express.static('public'))
const server = app.listen(APP_PORT, () => {
console.log("Listening on port " + APP_PORT);
diff --git a/install b/install
index 61e6333..3798f39 100755
--- a/install
+++ b/install
@@ -1,6 +1,6 @@
#!/bin/bash
-PACKAGES="gulp-cli"
+PACKAGES="gulp-cli gulper gulp"
if [[ $APP_DEBUG == 'true' ]]; then
npm i
diff --git a/package.json b/package.json
index 266fe56..d1aa79b 100644
--- a/package.json
+++ b/package.json
@@ -15,9 +15,9 @@
"dotenv": "^16.0.3",
"express": "^4.18.2",
"glob": "^8.1.0",
- "pug": "^3.0.2"
+ "pug": "^3.0.2",
+ "gulp": "^4.0.2"
},
"devDependencies": {
- "gulp": "^4.0.2"
}
}
diff --git a/public/content/cuteschedule.png b/public/content/cuteschedule.png
new file mode 100644
index 0000000..89c3cef
Binary files /dev/null and b/public/content/cuteschedule.png differ
diff --git a/public/content/vrplauncher.png b/public/content/vrplauncher.png
new file mode 100644
index 0000000..b60cca0
Binary files /dev/null and b/public/content/vrplauncher.png differ
diff --git a/public/content/winterredit.png b/public/content/winterredit.png
new file mode 100644
index 0000000..1fd168b
Binary files /dev/null and b/public/content/winterredit.png differ
diff --git a/public/static/image/ui/back_button_1.png b/public/static/image/ui/back_button_1.png
new file mode 100644
index 0000000..dfba1fb
Binary files /dev/null and b/public/static/image/ui/back_button_1.png differ
diff --git a/public/static/image/ui/back_button_2.png b/public/static/image/ui/back_button_2.png
new file mode 100644
index 0000000..0f014a4
Binary files /dev/null and b/public/static/image/ui/back_button_2.png differ
diff --git a/public/static/image/ui/back_button_3.png b/public/static/image/ui/back_button_3.png
new file mode 100644
index 0000000..7a05f9d
Binary files /dev/null and b/public/static/image/ui/back_button_3.png differ
diff --git a/public/static/main.css b/public/static/main.css
new file mode 100644
index 0000000..dece447
--- /dev/null
+++ b/public/static/main.css
@@ -0,0 +1,65 @@
+html {
+ background-color: #f2faea;
+}
+
+body {
+ padding:0;
+ margin:0;
+ height:100%;
+ width:100%;
+ position:fixed;
+ top:0;
+ left:0;
+ font-family: 'Open Sans', 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
+}
+table.body_table, table.body_table th, table.body_table tr {
+ border: 1px solid gray
+}
+table.body_table {
+ width:100%;
+ border-collapse: collapse;
+}
+tr {
+ vertical-align: top;
+}
+
+.side_menu {
+ width: 200px;
+ border-right: 1px solid #c2c4c2;
+ padding: 16px 12px;
+}
+.side_menu h1 {
+ font-size: 1.25em;
+ font-weight: 500;
+ padding-left: 3px;
+}
+a {
+ color: rgb(70, 92, 133)
+}
+a:visited {
+ color: rgb(55, 84, 138)
+}
+.side_menu ul {
+ list-style: none;
+ padding: 0;
+ font-size: 11pt;
+ padding-top: 32px;
+}
+.main_contents {
+ padding: 16px 12px;
+}
+
+.flag_hr {
+ background: linear-gradient(0,#5BCEFA 20%,#F5A9B8 20%,40%,#FFFFFF 40%,60%,#F5A9B8 60%,80%,#5BCEFA 80%);
+ position: absolute;
+ left: 0px;
+ width: 226px;
+ height: 24px;
+ padding: 0;
+ margin: 0;
+}
+
+hr {
+ border: 0;
+ border-bottom: 1px solid #C2C4C2;
+}
\ No newline at end of file
diff --git a/public/static/ui/back_button.css b/public/static/ui/back_button.css
new file mode 100644
index 0000000..07993d4
--- /dev/null
+++ b/public/static/ui/back_button.css
@@ -0,0 +1,30 @@
+
+.back_button_1 {
+ box-shadow:inset 0px 1px 0px 0px #bee2f9;
+ background:linear-gradient(to bottom, #63b8ee 5%, #468ccf 100%);
+ background-color:#63b8ee;
+ border-radius:5px;
+ border:1px solid #3866a3;
+ display:inline-block;
+ cursor:pointer;
+ color:#14396a;
+ font-family:Arial;
+ font-size:11px;
+ font-weight:bold;
+ padding:3px 7px;
+ text-decoration:none;
+ text-shadow:0px 1px 0px #7cacde;
+ box-shadow: 1px 1px 2px #30303030;
+ margin:0
+}
+.back_button_1:hover {
+ background:linear-gradient(to bottom, #468ccf 5%, #63b8ee 100%);
+ background-color:#468ccf;
+}
+.back_button_1:active {
+ position:relative;
+ top:1px;
+}
+.back_button_1::before {
+ content: '← go back'
+}
\ No newline at end of file
diff --git a/routes/homepage.js b/routes/homepage.js
index 52bd6d0..0749702 100644
--- a/routes/homepage.js
+++ b/routes/homepage.js
@@ -1,7 +1,15 @@
const Helpers = require('../helpers');
async function handler(req, res) {
- res.send(await Helpers.ViewLoader.load('hi.pug'));
+ res.send(
+ await Helpers.ViewLoader.load(
+ 'main.pug',
+ {
+ current_route: '/'
+ }
+ )
+ );
+ return;
}
module.exports = (router) => {
diff --git a/routes/proj.js b/routes/proj.js
new file mode 100644
index 0000000..84da5ff
--- /dev/null
+++ b/routes/proj.js
@@ -0,0 +1,44 @@
+const Helpers = require('../helpers');
+
+async function handler(req, res) {
+ res.send(
+ await Helpers.ViewLoader.load(
+ 'project.pug',
+ {
+ current_route: '/'
+ }
+ )
+ );
+ return;
+}
+
+async function viewer(req, res) {
+ const id = req.params.id;
+ const view = 'projects/' + id + '.pug';
+ if (!(await Helpers.ViewLoader.exists(view))) {
+ res.status(404).send(
+ await Helpers.ViewLoader.load(
+ 'error.pug',
+ {
+ current_route: req.originalUrl,
+ error: '404 Not Found',
+ message: 'Requested project does not exists. Are you sure this is the valid link?'
+ }
+ )
+ );
+ return;
+ }
+ res.send(
+ await Helpers.ViewLoader.load(
+ view,
+ {
+ current_route: req.originalUrl
+ }
+ )
+ )
+}
+
+module.exports = (router) => {
+ router.get('/project', handler);
+ router.get('/project/:id', viewer);
+}
\ No newline at end of file
diff --git a/startup.js b/startup.js
index ad58bd6..4fd6976 100644
--- a/startup.js
+++ b/startup.js
@@ -1,5 +1,9 @@
console.log('Executing startup jobs...');
+if (process.env.APP_DEBUG) {
+ process.env.DEBUG = '*/*';
+}
+
const fs = require('fs');
const hrt = () => {
diff --git a/view/error.pug b/view/error.pug
new file mode 100644
index 0000000..3dbcfbc
--- /dev/null
+++ b/view/error.pug
@@ -0,0 +1,7 @@
+extends layout/main.pug
+block root
+ - var title = error
+
+block content
+ h1(align='center')= error
+ p(align='center')= message
\ No newline at end of file
diff --git a/view/hi.pug b/view/hi.pug
deleted file mode 100644
index 2dd9f5a..0000000
--- a/view/hi.pug
+++ /dev/null
@@ -1 +0,0 @@
-p hi
\ No newline at end of file
diff --git a/view/layout/main.pug b/view/layout/main.pug
new file mode 100644
index 0000000..15ed973
--- /dev/null
+++ b/view/layout/main.pug
@@ -0,0 +1,36 @@
+block root
+
+-
+ let routes = {
+ "Main page": '/',
+ "Projects": "/project",
+ "About me": "/about"
+ }
+
+doctype html
+html
+ head
+ title blek! Site #{title ? "- " + title : ""}
+
+ link(rel='stylesheet' href='/static/main.css')
+
+ block head
+ body
+ table(width='100%' height='100%' class='body_table')
+ tr
+ td(class='side_menu')
+ h1
+ a(href='/') blek! Site
+ hr(class='flag_hr')
+ ul
+ each route, name in routes
+ li
+ if current_route == route
+ | > #{name}
+ else
+ a(href=route) #{name}
+ td(class='main_contents')
+ block content
+ block foot
+ block scripts
+
\ No newline at end of file
diff --git a/view/layout/project.pug b/view/layout/project.pug
new file mode 100644
index 0000000..f6e4578
--- /dev/null
+++ b/view/layout/project.pug
@@ -0,0 +1,9 @@
+extends main.pug
+
+block append head
+
+
+block content
+ p(style='margin:0')
+ a(href='/project' title='go back to projects page' class='back_button_1')
+ hr
\ No newline at end of file
diff --git a/view/main.pug b/view/main.pug
new file mode 100644
index 0000000..e4a045a
--- /dev/null
+++ b/view/main.pug
@@ -0,0 +1,45 @@
+extends layout/main.pug
+block root
+ - var title = 'Main page'
+block content
+ //
+ h1(align='center') Welcome on my website!
+ p
+ | Hi there! My name is Alice and I like to build software.
+ hr
+ p
+ | Currently I am working on a college project (which is going to air in june)
+ br
+ | This website was built using Express.js
+ p
+ | Check out my
+ a(href='https://github.com/b1ek') GitHub page
+ | and my
+ a(href='/resume') resume
+ table(width='100%')
+ tr
+ td(width='20%')
+ h4 Guest book
+ | (
+ a(href='/guestbook.rss') RSS
+ | )
+ ul
+ li entry
+ li entry
+ li entry
+ li entry
+ li entry
+ a(href='/guestbook') Write something in my guestbook!
+ td(width='60%' style='border-left:1px solid #c2c4c2;border-right:1px solid #c2c4c2;padding:0 1%')
+ h3 Blog
+ ul
+ each i in [0,0,0,0,0]
+ li(style='font-size:16pt')
+ | entry
+ ul
+ li data
+
+ td(width='20%')
+ h4 Links
+ a(href='https://cameronsworld.net') cameronsworld.net
+ a(href='https://')
\ No newline at end of file
diff --git a/view/project.pug b/view/project.pug
new file mode 100644
index 0000000..d8130ac
--- /dev/null
+++ b/view/project.pug
@@ -0,0 +1,27 @@
+extends layout/main.pug
+block root
+ - var title = 'Projects'
+block content
+ h2 My projects
+
+ ul
+ li
+ a(href='/project/blek_sail') blek! Sail
+ li
+ a(href='/project/blek_id') blek! ID
+ li
+ a(href='/project/cuteschedule') CuteSchedule
+ li
+ a(href='/project/vrplauncher') VRPLauncher
+
+ h2 Projects I participated in
+
+ ul
+ li
+ a(href='/project/winterredit') WinTerrEdit
+
+ h2 Planned projects
+
+ ul
+ li blek! Analytics
+ li blek! Launcher
\ No newline at end of file
diff --git a/view/projects/blek_id.pug b/view/projects/blek_id.pug
new file mode 100644
index 0000000..b97980e
--- /dev/null
+++ b/view/projects/blek_id.pug
@@ -0,0 +1,10 @@
+extends ../layout/project.pug
+block root
+ - var title = 'blek! Sail'
+
+block append content
+ h2 blek! ID
+ p
+ | blek! ID provides authentication functionality for all blek! Services.
+ br
+ | It was supposed to be something like OpenID Connect server, and perhaps you should use a production-ready implementation of this (like ory hydra)
\ No newline at end of file
diff --git a/view/projects/blek_sail.pug b/view/projects/blek_sail.pug
new file mode 100644
index 0000000..e7ace68
--- /dev/null
+++ b/view/projects/blek_sail.pug
@@ -0,0 +1,16 @@
+extends ../layout/project.pug
+block root
+ - var title = 'blek! Sail'
+
+block append content
+ h2 blek! Sail
+ p
+ | blek! Sail is a production-ready alternative to Laravel Sail.
+ br
+ | It runs on nginx + php-fpm on alpine linux
+ p
+ | Read the github
+ a(href='https://github.com/b1ek/sail') page
+ | for more info.
+ p
+ a(href='https://hub.docker.com/r/blekii/sail') Docker hub repo
\ No newline at end of file
diff --git a/view/projects/cuteschedule.pug b/view/projects/cuteschedule.pug
new file mode 100644
index 0000000..cc1bf67
--- /dev/null
+++ b/view/projects/cuteschedule.pug
@@ -0,0 +1,23 @@
+extends ../layout/project.pug
+block root
+ - var title = 'CuteSchedule'
+
+block append content
+ p(align='center')
+ img(src='/content/cuteschedule.png' height=128)
+
+ | CuteSchedule is an interactive menu with a school schedule.
+ br
+ hr
+ p.
+ The idea is that the user comes to a big touchscreen TV, selects their class and sees the schedule for the week.
+ p.
+ The whole thing was made for a school project and the code is not very good.
+ I am planning to re write it to electron+vue sometime to have better UI/UX
+ p.
+ Also, the original task requested a feature to track a teacher by schedule (to see the cabinet the teacher is in),
+ but i never got around to implementing it.
+ p.
+ It loads the config from a YAML file with
+ yaml-cpp
+ Funny part: it is stored in git as precompiled binary.
\ No newline at end of file
diff --git a/view/projects/vrplauncher.pug b/view/projects/vrplauncher.pug
new file mode 100644
index 0000000..bab1330
--- /dev/null
+++ b/view/projects/vrplauncher.pug
@@ -0,0 +1,22 @@
+extends ../layout/project.pug
+block root
+ - var title = 'VRPLauncher'
+
+block append content
+ h2 VRPLauncher
+ p.
+ VRPLauncher is a custom minecraft launcher for another project (a minecraft server with mods).
+ It is written in C# with WinForms and is made to keep only specific mods in mods folder (it reports any modifications to the server).
+ p(align='center')
+ img(src='/content/vrplauncher.png' height=351)
+
+ | I have bothered to download the archive with this
+ | and run it with Wine (unfourtunately, i dont run windows)
+ hr
+ p.
+ The interface is written and hardcoded in Russian because the server was made for russians.
+ It was, though planned to implement localization but the project was shut down before i ever got to this.
+ p.
+ The design is not very good, but its as good as it gets with WinForms (i guess?)
+ Perhaps it could be better, but that's the best i could do at the time.
+ Should've made the thing with WPF
\ No newline at end of file
diff --git a/view/projects/winterredit.pug b/view/projects/winterredit.pug
new file mode 100644
index 0000000..f175c7d
--- /dev/null
+++ b/view/projects/winterredit.pug
@@ -0,0 +1,16 @@
+extends ../layout/project.pug
+block root
+ - var title = 'WinTerrEdit'
+
+block append content
+ p(align='center')
+ a(href='https://github.com/nymda/WinTerrEdit' target='_blank')
+ img(src='/content/winterredit.png' height=100)
+
+ p.
+ WinTerrEdit is a GUI based terraria inventory/player editor.
+ My affilation with the project was adding a couple of things and refactoring the code to make it more readable
+ The thing was a complete mess before i refactored it. (although it still needs some work)
+
+ p.
+ See the github page.
\ No newline at end of file