60 Commits
Author SHA1 Message Date
Raymonzut 25b90a3432 Merge branch 'beta' into 'master' 2020-06-16 22:29:25 +02:00
Raymonzut 0cab1479f2 Sync server package(-lock).json to 1.3.0 2020-06-16 22:29:06 +02:00
Raymonzut 8acedc284b Merge branch 'simplify/front-end' into beta
- Ditched node_modules aka the blackhole in the client
2020-06-16 22:20:15 +02:00
Raymonzut ec8bc54437 Remove vue remnants 2020-06-16 22:17:54 +02:00
Raymonzut 1904301eae Make posts links to the post content 2020-06-16 22:15:36 +02:00
Raymonzut b879a4d400 Remove unneeded script imports 2020-06-16 21:39:44 +02:00
Raymonzut c096acdf7d Add dynamic post loading 2020-06-16 21:37:05 +02:00
Raymonzut b0cd041fd9 Readd remote 2020-06-16 21:30:50 +02:00
Raymonzut df3ff8f27c Add questions and answers on qa page 2020-06-16 19:20:21 +02:00
Raymonzut bb7e8f9c89 Fix newline in nginx.conf 2020-06-16 19:11:03 +02:00
Raymonzut 04957ad2fc Add empty posts and qa pages 2020-06-16 19:10:10 +02:00
Raymonzut 914e700056 Remove noscript warning for index.html 2020-06-16 19:09:45 +02:00
Raymonzut 777339c3e1 Allow requesting without .html 2020-06-16 19:07:02 +02:00
Raymonzut 62128bd65b Rename index.css to general.css 2020-06-16 19:01:03 +02:00
Raymonzut d23db35657 Remove old me.js node module 2020-06-16 18:53:22 +02:00
Raymonzut d966729f7e Defer stylesheets 2020-06-16 18:51:57 +02:00
Raymonzut 1a42c6ef77 Add deferred scripts for dynamic age 2020-06-16 18:51:45 +02:00
Raymonzut 318ab4c6ca Fill homepage 2020-06-16 18:49:00 +02:00
Raymonzut 2c7f327892 Add me.mjs with age() 2020-06-16 18:48:26 +02:00
Raymonzut 7506909670 Add /js location nginx 2020-06-16 18:45:46 +02:00
Raymonzut 037c638427 Add mjs mime type 2020-06-16 18:45:16 +02:00
Raymonzut 78c7ef8809 Remove all testing (yes, all) 2020-06-16 18:44:01 +02:00
Raymonzut a93722a356 Style with dragondesign (thx @jelle619) 2020-06-16 17:35:00 +02:00
Raymonzut a6bf99c945 Position the navbar 2020-06-16 17:13:47 +02:00
Raymonzut a910feda62 Reroute /api route to the back-end 2020-06-16 17:13:47 +02:00
Raymonzut cf1ef4257c Add basic 404 page 2020-06-16 17:13:47 +02:00
Raymonzut fb5fc2ede2 Move styling into assets/styling as /css 2020-06-16 17:13:46 +02:00
Raymonzut ce4d17974b Add navbar 2020-06-16 17:13:46 +02:00
Raymonzut 0c566af9a7 Clean index.html 2020-06-16 14:14:26 +02:00
Raymonzut d6c920bf86 Remove redundant babel.config.js 2020-06-16 13:56:31 +02:00
Raymonzut f9f9f7010c Simplify docker to only use nginx 2020-06-16 13:52:44 +02:00
Raymonzut fd991f3dcc Remove all client npm dependencies 2020-06-16 13:52:44 +02:00
Raymonzut 89e22861af Merge branch 'beta' into 'master' 2020-06-16 12:29:09 +02:00
raymonanddependabot[bot] 3d93b6ddb8 Bump websocket-extensions from 0.1.3 to 0.1.4 in /client (#7)
Bumps [websocket-extensions](https://github.com/faye/websocket-extensions-node) from 0.1.3 to 0.1.4.
- [Release notes](https://github.com/faye/websocket-extensions-node/releases)
- [Changelog](https://github.com/faye/websocket-extensions-node/blob/master/CHANGELOG.md)
- [Commits](https://github.com/faye/websocket-extensions-node/compare/0.1.3...0.1.4)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-06-08 21:46:12 +02:00
raymon 418fc1fad4 Merge pull request #6 from Raymonzut/dependabot/npm_and_yarn/client/websocket-extensions-0.1.4
Bump websocket-extensions from 0.1.3 to 0.1.4 in /client
2020-06-08 20:09:41 +02:00
dependabot[bot] 7f0d95b870 Bump websocket-extensions from 0.1.3 to 0.1.4 in /client
Bumps [websocket-extensions](https://github.com/faye/websocket-extensions-node) from 0.1.3 to 0.1.4.
- [Release notes](https://github.com/faye/websocket-extensions-node/releases)
- [Changelog](https://github.com/faye/websocket-extensions-node/blob/master/CHANGELOG.md)
- [Commits](https://github.com/faye/websocket-extensions-node/compare/0.1.3...0.1.4)

Signed-off-by: dependabot[bot] <support@github.com>
2020-06-08 06:47:52 +00:00
Raymonzut a8736826bf Respond status 200 application/xml /api/posts/urls 2020-06-02 21:14:06 +02:00
Raymonzut 1a76d0d426 Merge branch 'beta' into 'master' 2020-06-02 16:21:29 +02:00
Raymonzut 09a5a7438c Merge branch 'release/c1.1.0-s1.2.0' into beta 2020-06-02 16:20:48 +02:00
Raymonzut f948e833e9 Bump version: c1.1.0-s1.2.0 2020-06-02 16:20:25 +02:00
Raymonzut 494f5b5c07 Fix #5 2020-06-02 15:55:50 +02:00
Raymonzut 760677ce90 Add paragraphs in AboutMe 2020-06-01 17:30:10 +02:00
Raymonzut ffe62b6380 Merge branch 'feat/themes' into beta 2020-06-01 16:55:34 +02:00
Raymonzut dd4e2ca9fb Style theme switching button 2020-06-01 16:53:53 +02:00
Raymonzut aab9885242 Add theme switching button 2020-05-31 22:42:14 +02:00
Raymonzut d8b038dc9c Reset padding, margin and width for entire bg 2020-05-31 22:32:58 +02:00
Raymonzut 43d28f7f6b Configure line-endings as LF 2020-05-31 22:09:01 +02:00
Raymonzut 4324e569ca Merge branch 'SEO/sitemap-posts' into beta 2020-05-19 20:28:33 +02:00
Raymonzut 56fffda0fe Route /urls: returns xml for posts 2020-05-19 20:27:32 +02:00
Raymonzut 9fdbd1b6a1 Route posts without interesting queries to posts 2020-05-15 13:11:15 +02:00
Raymonzut cb3f9b60b9 Merge branch 'beta' 2020-05-14 21:06:37 +02:00
Raymonzut eec3738464 Merge branch 'release/c1.0.0-s1.1.0' into beta 2020-05-14 21:05:53 +02:00
Raymonzut 43482fcb2e Bump server version to 1.1.0 2020-05-14 21:05:04 +02:00
Raymonzut 69eff0ae21 Update client version in package-lock 2020-05-14 20:18:53 +02:00
Raymonzut e8139ef878 Remove unused function readPostsDelayed 2020-05-14 20:18:22 +02:00
Raymonzut 1ed4ba3a4a Allow all IPv4 interfaces (for docker) 2020-05-14 20:16:26 +02:00
Raymonzut 64148746f1 Merge branch 'dep-swap/express-to-fastify' into beta 2020-05-14 20:08:24 +02:00
Raymonzut e9b9f01101 Convert express logic to fastify logic 2020-05-14 20:07:43 +02:00
Raymonzut 0dd0ac74e1 Swap express + cors with fastify + fastify-cors 2020-05-14 20:01:24 +02:00
Raymonzut 4ef296269c Merge branch 'release/v1.0.0' into beta
- Add descriptions for package.json's
- Bump versions to 1.0.0
2020-05-11 22:20:51 +02:00
37 changed files with 1548 additions and 13864 deletions
+3
View File
@@ -0,0 +1,3 @@
* text=auto
eol=lf
-32
View File
@@ -1,32 +0,0 @@
name: Node.js CI
on:
push:
branches: [ master, beta ]
pull_request:
branches: [ master ]
jobs:
build:
env:
CLIENT_DIR: ./client
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [10.x, 12.x, 13.x]
steps:
- uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- run: npm ci
working-directory: ${{env.CLIENT_DIR}}
- run: npm run build --if-present
working-directory: ${{env.CLIENT_DIR}}
- run: npm test
working-directory: ${{env.CLIENT_DIR}}
env:
CI: true
-1
View File
@@ -1,2 +1 @@
**/node_modules **/node_modules
**/dist
+1 -8
View File
@@ -1,11 +1,4 @@
FROM node:latest as build-stage
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY ./ .
RUN npm run build
FROM nginx as production-stage FROM nginx as production-stage
RUN mkdir /app RUN mkdir /app
COPY --from=build-stage /app/dist /app COPY /public /app
COPY nginx.conf /etc/nginx/nginx.conf COPY nginx.conf /etc/nginx/nginx.conf
-3
View File
@@ -1,3 +0,0 @@
module.exports = {
presets: ['@vue/cli-plugin-babel/preset'],
}
+23 -2
View File
@@ -7,7 +7,10 @@ events {
} }
http { http {
include /etc/nginx/mime.types; include /etc/nginx/mime.types;
default_type application/octet-stream; types {
application/javascript mjs;
}
log_format main '$remote_addr - $remote_user [$time_local] "$request" ' log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" ' '$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"'; '"$http_user_agent" "$http_x_forwarded_for"';
@@ -20,8 +23,26 @@ http {
location / { location / {
root /app; root /app;
index index.html; index index.html;
try_files $uri $uri/ /index.html; try_files $uri $uri/ $uri.html $uri/index.html =404;
} }
location /css {
alias /app/assets/styling;
}
location /js {
alias /app/lib;
}
location /api {
proxy_pass https://raymon.dev/api;
proxy_buffering on;
}
error_page 404 /404.html;
location = /404.html {
root /app/error;
}
error_page 500 502 503 504 /50x.html; error_page 500 502 503 504 /50x.html;
location = /50x.html { location = /50x.html {
root /usr/share/nginx/html; root /usr/share/nginx/html;
-13023
View File
File diff suppressed because it is too large Load Diff
-56
View File
@@ -1,56 +0,0 @@
{
"name": "personal-website",
"version": "1.0.0",
"private": true,
"description": "A nice introduction to my chaos",
"main": "src/main.js",
"scripts": {
"build": "vue-cli-service build",
"lint": "vue-cli-service lint",
"serve": "vue-cli-service serve",
"test": "node test_runner"
},
"repository": {
"type": "git",
"url": "git+https://github.com/Raymonzut/Personal-Website.git"
},
"author": "Raymonzut",
"license": "ISC",
"bugs": {
"url": "https://github.com/Raymonzut/Personal-Website/issues"
},
"homepage": "https://github.com/Raymonzut/Personal-Website#readme",
"dependencies": {
"core-js": "^3.6.5",
"vue": "^2.6.11",
"vue-resource": "^1.5.1",
"vue-router": "^3.1.6"
},
"devDependencies": {
"babel-eslint": "^10.0.3",
"eslint": "^6.7.2",
"eslint-plugin-vue": "^6.1.2",
"@vue/cli-plugin-babel": "~4.2.0",
"@vue/cli-plugin-eslint": "~4.2.0",
"@vue/cli-service": "~4.2.0",
"vue-template-compiler": "^2.6.11"
},
"eslintConfig": {
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/essential",
"eslint:recommended"
],
"parserOptions": {
"parser": "babel-eslint"
},
"rules": {}
},
"browserslist": [
"> 1%",
"last 2 versions"
]
}
+15
View File
@@ -0,0 +1,15 @@
nav {
border-bottom-left-radius: 5px;
border-bottom-right-radius: 5px;
}
@media (max-width: 420px) {
#app {
margin-left: 0vw;
margin-right: 0vw;
}
}
.question {
font-style: italic;
}
+18
View File
@@ -0,0 +1,18 @@
:root {
--primary-color: #272736;
--text-color: #ffffeb;
/* Overriding DP DS */
--body-background: var(--primary-color);
--body-color: var(--text-color);
--nav-color: var(--primary-color);
--nav-background: var(--text-color);
}
@media (prefers-color-scheme: light) {
:root {
--primary-color: #ffffeb;
--text-color: #272736;
}
}
+10
View File
@@ -0,0 +1,10 @@
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>404</title>
</head>
<body>
This page could not be found, sorry for the inconvenience
</body>
</html>
+40 -9
View File
@@ -1,18 +1,49 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE-edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Personal Website</title> <title>Raymon Zutekouw</title>
<link defer
rel="stylesheet"
href="https://cdn.statically.io/gh/dragonprojects/dragondesign/master/main.min.css"
media="all"
>
<link defer rel="stylesheet" href="css/themes.css" media="all">
<link defer rel="stylesheet" href="css/general.css" media="all">
<script defer type="module" src="index.mjs"></script>
</head> </head>
<body> <body>
<noscript> <div id="app">
<strong>This site doesn't work properly without JavaScript enabled. Please enable to continue.</strong> <nav>
</noscript> <a href="/">Home</a>|
<div id="app"></div> <a href="/posts">Posts</a>|
</body> <a href="/qa">QA</a>
</nav>
<h1>Home</h1>
<div>
<h2>Who am I?</h2>
<p>
Hi there, good to see you on my website.
My name is Raymon Zutekouw (<span id="age">born on 29-08-2002</span>)
</p>
<p>
Building software and exploring the wide variety of tools (or making them) is my passion.
To see it in action, checkout the stuff I make on
<a href='https://github.com/Raymonzut'>GitHub</a>.
</p>
<p>
The projects that may be useful to others are open source; for inspiring others and improving each others work.
That is why I am a huge fan of
<a href='https://www.gnu.org/philosophy/free-sw.en.html'>free software</a>.
</p>
</div>
</div>
</body>
</html> </html>
+4
View File
@@ -0,0 +1,4 @@
import { age } from "./lib/me.mjs"
const age_span = document.getElementById("age")
age_span.textContent = age().toString()
@@ -1,8 +1,4 @@
module.exports = { export function age() {
age: age,
}
function age() {
let birthdate = new Date(2002, 8, 29) let birthdate = new Date(2002, 8, 29)
let now = new Date() let now = new Date()
+24
View File
@@ -0,0 +1,24 @@
export async function getPosts(id) {
const BASE_URL = 'https://raymon.dev'
const BASE_ENDPOINT = '/api/posts'
const URL = BASE_URL + BASE_ENDPOINT + (id ? `/${id}` : '?sort=-1')
let posts = []
return await fetch(URL)
.then(res => res.json())
.then(res => {
if (id !== undefined) {
if (res === undefined) {
throw Error("Response body empty")
}
return [res]
}
else {
return res
}
})
.catch(err => {
console.log(`Error: ${err}`)
})
}
+37
View File
@@ -0,0 +1,37 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Raymon Zutekouw</title>
<link defer
rel="stylesheet"
href="https://cdn.statically.io/gh/dragonprojects/dragondesign/master/main.min.css"
media="all"
>
<link defer rel="stylesheet" href="css/themes.css" media="all">
<link defer rel="stylesheet" href="css/general.css" media="all">
<script defer type="module" src="posts.mjs"></script>
</head>
<body>
<noscript>
<p>
This page isn't as fancy without JavaScript.
Some parts will not load, but this will be minimal.
</p>
</noscript>
<div id="app">
<nav>
<a href="/">Home</a>|
<a href="/posts">Posts</a>|
<a href="/qa">QA</a>
</nav>
<!-- Placeholder for posts -->
<div id="posts"></div>
</div>
</body>
</html>
+61
View File
@@ -0,0 +1,61 @@
import { getPosts } from "./lib/remote.mjs"
function toMonthYearString(str) {
const date = new Date(str)
return `${date.toLocaleString('default', { month: 'long' })} ${date.getFullYear()}`
}
async function showPost(id) {
const post_list = await getPosts(id)
const post = post_list[0]
const title = document.createElement("h1")
title.textContent = post.title
const postsDOM = document.getElementById("posts")
postsDOM.appendChild(title)
post.content.split('\n').forEach(paragraph => {
const p = document.createElement("p")
p.textContent = paragraph
postsDOM.appendChild(p)
});
}
async function updatePosts() {
const posts = await getPosts()
const months = posts.map(post => toMonthYearString(post.date))
const uniques = Array.from(new Set(posts.map(post => toMonthYearString(post.date))))
const month_lists = uniques.map(month =>
posts.filter(
post => toMonthYearString(post.date) === month
)
)
const postsDOM = document.getElementById("posts")
uniques.forEach((month, i) => {
const month_DOM = document.createElement("h1")
month_DOM.textContent = month
month_lists[i].forEach((post, i) => {
const post_DOM = document.createElement("h6")
post_DOM.textContent = `${post.date.substring(0, 10)} - `
const post_link = document.createElement("a")
post_link.href = 'posts?post=' + post._id
post_link.textContent = post.title
post_DOM.appendChild(post_link)
month_DOM.appendChild(post_DOM)
})
postsDOM.appendChild(month_DOM)
})
}
// Check if a specific post is requested
let url = new URL(document.location.href);
url.searchParams.sort();
let post_id = url.searchParams.values().next().value;
const reg = /([0-9]|[a-f]){24}/
if (post_id && reg.test(post_id)) showPost(post_id)
else updatePosts()
+33
View File
@@ -0,0 +1,33 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Raymon Zutekouw</title>
<link defer
rel="stylesheet"
href="https://cdn.statically.io/gh/dragonprojects/dragondesign/master/main.min.css"
media="all"
>
<link defer rel="stylesheet" href="css/themes.css" media="all">
<link defer rel="stylesheet" href="css/general.css" media="all">
</head>
<body>
<div id="app">
<nav>
<a href="/">Home</a>|
<a href="/posts">Posts</a>|
<a href="/qa">QA</a>
</nav>
<div>
<h4 class="question">What is this site about?</h4>
<h4>This site is about me and the stuff I make</h4>
<h4 class="question">Why is it still so empty?</h4>
<h4>Because I am framework hopping and now ditching frameworks all together</h4>
</div>
</div>
</body>
</html>
-28
View File
@@ -1,28 +0,0 @@
<template>
<div id="app">
<div id="nav">
<router-link to="/">Home</router-link> |
<router-link to="/posts">Posts</router-link> |
<router-link to="/qa">QA</router-link>
</div>
<router-view />
</div>
</template>
<script>
export default {
name: 'App',
}
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

-34
View File
@@ -1,34 +0,0 @@
<template>
<div>
<h2>Who am I?</h2>
<p>
Hi there, good to see you on my website.
My name is Raymon Zutekouw({{ age }}).
Building software and exploring the wide variety of tools (or making them) is my passion.
To see it in action, checkout the stuff I make on
<a href='https://github.com/Raymonzut'>GitHub</a>.
The projects that may be useful to others are open source; for inspiring others and improving each others work.
That is why I am a huge fan of
<a href='https://www.gnu.org/philosophy/free-sw.en.html'>free software</a>.
</p>
</div>
</template>
<script>
import me from '../me.js'
export default {
name: 'AboutMe',
computed: {
age: me.age
}
};
</script>
<style scoped>
p {
--margin-side: 12vw;
margin-left: var(--margin-side);
margin-right: var(--margin-side);
}
</style>
-18
View File
@@ -1,18 +0,0 @@
<template>
<div>
{{ a }}
</div>
</template>
<script>
export default {
name: 'Answer',
props: {
a: {
type: String,
required: true,
}
}
}
</script>
-38
View File
@@ -1,38 +0,0 @@
<template>
<div id='qa'>
<Question :q='q'></Question>
<Answer :a='a'></Answer>
</div>
</template>
<script>
import Question from './Question.vue'
import Answer from './Answer.vue'
export default {
name: 'QA',
components: {
Question,
Answer,
},
props: {
q: {
type: String,
required: true,
},
a: {
type: String,
required: true,
}
}
}
</script>
<style scoped>
#qa {
--block-spacing: 7.5em;
margin-top: var(--block-spacing);
margin-bottom: var(--block-spacing);
}
</style>
-27
View File
@@ -1,27 +0,0 @@
<template>
<div id='question_box'>
{{ q }}
</div>
</template>
<script>
export default {
name: 'Question',
props: {
q: {
type: String,
required: true,
}
}
}
</script>
<style scoped>
#question_box {
--text-spacing: 0.75em;
font-style: italic;
margin-top: var(--text-spacing);
margin-bottom: var(--text-spacing);
}
</style>
-14
View File
@@ -1,14 +0,0 @@
import Vue from 'vue'
import VueResource from 'vue-resource'
import App from './App.vue'
import router from './router'
Vue.config.productionTip = false
Vue.use(VueResource)
new Vue({
render: h => h(App),
router,
}).$mount('#app')
-23
View File
@@ -1,23 +0,0 @@
module.exports = {
getPosts: function(id) {
const BASE_URL = '/api/posts'
const URL = BASE_URL + (id ? `/${id}` : '?sort=-1')
this.$http
.get(URL)
.then(res => {
if (id) {
if (res.body.length === 0) {
throw Error("Response body empty")
}
this.post = res.body
}
else {
this.posts = res.body
}
})
.catch(err => {
console.log(`Error: ${err}`)
})
},
}
-46
View File
@@ -1,46 +0,0 @@
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'
import Posts from '../views/Posts.vue'
import Post from '../views/Post.vue'
import QAPage from '../views/QAPage'
Vue.use(VueRouter)
const routes = [
{
path: "/",
name: "Home",
component: Home,
},
{
path: "/posts",
name: "Posts",
component: Posts,
},
{
path: "/posts/:id",
name: "Post",
component: Post,
props: true,
},
{
path: "/qa",
name: "QA",
component: QAPage
},
]
const exclude_routes = [
{
path: "/api"
}
]
const router = new VueRouter({
mode: "history",
base: process.env.BASE_URL,
routes: routes.concat(exclude_routes),
})
export default router
-19
View File
@@ -1,19 +0,0 @@
<template>
<div id="home">
<h1>Home</h1>
<AboutMe></AboutMe>
</div>
</template>
<script>
import AboutMe from '@/components/AboutMe'
export default {
name: "Home",
components: {
AboutMe
},
}
</script>
<style scoped></style>
-45
View File
@@ -1,45 +0,0 @@
<template>
<div id="Post">
<div v-if="Object.keys(post).length">
<h1>{{ post.title }}</h1>
<h5>Written on {{ post.date.substring(0,10)}}</h5>
<p v-for="(p, i) in post.content.split('\n')" :key="i">{{ p }}</p>
</div>
<h2 v-else>Waiting for post</h2>
<br>
Read other <a href="/posts">posts</a>
<br>
</div>
</template>
<script>
import { getPosts } from '../remote'
export default {
name: "Post",
data() {
return {
post: {},
}
},
methods: {
getPosts
},
mounted() {
getPosts.call(this, this._props.id)
},
props: {
id: {
type: String,
name: "id",
validator: val => {
const reg = /([0-9]|[a-f]){24}/
return reg.test(val)
},
}
}
}
</script>
<style scoped></style>
-68
View File
@@ -1,68 +0,0 @@
<template>
<div id="posts" v-if="months.length >= 0">
<h3 class="month" v-for="(month, i) in months" :key="i">
{{ month }}
<div>
<ul>
<li v-for="(postItem, j) in getPostItems(month)" :key="j">
{{ getPostItemDate(postItem) }} –
<a :href="/posts/ + postItem._id">{{ postItem.title }}</a>
</li>
</ul>
</div>
<br>
</h3>
</div>
<h2 v-else>There are no posts yet, but don't worry they will be added soon</h2>
</template>
<script>
import { getPosts } from '../remote'
export default {
name: "Posts",
computed: {
months: function () {
const dates = this.posts.map(post => new Date(post.date))
// Contains the month followed by the year
const months = dates.map(date => `${date.toLocaleString('default', { month: 'long' })} ${date.getFullYear()}`)
const uniques = Array.from(new Set(months))
return uniques
}
},
data() {
return {
posts: []
}
},
methods: {
getPosts,
getPostItems: function (month) {
const month_index = new Date(`1 ${month}`).getMonth()
return this.posts.filter((post) => (new Date(post.date)).getMonth() === month_index)
},
getPostItemDate: function (postItem) {
const date = new Date(postItem.date)
return `${date.getFullYear()} ${date.toLocaleString('default', { month: 'short' })} ${date.getDate()}`
}
},
mounted() {
getPosts.call(this)
},
}
</script>
<style scoped>
ul {
text-align: left;
}
@media (min-width: 420px) {
.month {
text-indent: 1em;
text-align: left;
}
}
</style>
-25
View File
@@ -1,25 +0,0 @@
<template>
<div id="QAPage">
<QA
q="What is this site about? "
a="This site is about me and the stuff I make "
></QA>
<QA
q="Why is it still so empty?"
a="Because I am framework hopping "
></QA>
</div>
</template>
<script>
import QA from '@/components/QA'
export default {
name: "QAPAge",
components: { QA }
}
</script>
<style scoped></style>
-4
View File
@@ -1,4 +0,0 @@
const assert = require('assert').strict
const me = require('../src/me')
assert(me.age() > 0, 'age should return a positive number')
-22
View File
@@ -1,22 +0,0 @@
const { spawn } = require('child_process')
const fs = require('fs')
const dirs = ['./test', './tests']
if (!dirs.some(fs.existsSync)) {
throw Error("Could not find any test directories, looked for: " + dirs)
}
const test_dirs = dirs.filter(fs.existsSync)
test_dirs.forEach(test_dir => {
const files = fs.readdirSync(test_dir)
if (files.length === 0) {
throw Error("Could not find test files in " + test_dir)
}
const childs = files.map(file =>
spawn('node', [`${test_dir}/${file}`], { stdio: 'inherit' })
)
})
+16 -7
View File
@@ -1,14 +1,23 @@
const express = require('express') const fastify = require('fastify')()
const cors = require('cors')
const app = express() fastify.register(require('fastify-cors'))
app.use(cors())
const posts = require('./routes/api/posts') const posts = require('./routes/api/posts')
app.use('/posts', posts) // Assuming they are all get requests
for (let [route, resolver] of posts.entries()) {
fastify.get('/posts' + route, resolver)
}
const port = process.env.PORT || 5000 const port = process.env.PORT || 5000
app.listen(port, () => console.log(`Server started on port ${port}`)) const start = async () => {
try {
await fastify.listen(port, '0.0.0.0')
console.log(`Launched on port ${port} 🚀`)
} catch (err) {
fastify.log.error(err)
process.exit(1)
}
}
start()
+1217 -290
View File
File diff suppressed because it is too large Load Diff
+7 -4
View File
@@ -1,6 +1,6 @@
{ {
"name": "server", "name": "server",
"version": "1.0.0", "version": "1.3.0",
"description": "The API for the website", "description": "The API for the website",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {
@@ -8,10 +8,13 @@
"dev": "nodemon server/index.js" "dev": "nodemon server/index.js"
}, },
"keywords": [], "keywords": [],
"author": "", "author": "Raymonzut",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"cors": "^2.8.5", "fastify": "^2.14.1",
"express": "^4.17.1" "fastify-cors": "^3.0.3"
},
"devDependencies": {
"nodemon": "^2.0.4"
} }
} }
+35 -10
View File
@@ -1,20 +1,15 @@
const express = require('express')
const fs = require('fs') const fs = require('fs')
const router = express.Router()
const posts_dir = 'posts/' const posts_dir = 'posts/'
const routes = new Map();
if (!fs.existsSync(posts_dir)) throw Error(`Missing ${posts_dir}`) if (!fs.existsSync(posts_dir)) throw Error(`Missing ${posts_dir}`)
let posts = readPosts(); let posts = readPosts();
setInterval(() => posts = readPosts(), 1000 * 60 * 60) setInterval(() => posts = readPosts(), 1000 * 60 * 60)
function readPostsDelayed() {
return new Promise(setTimeout, 1000).then(posts = readPosts())
}
function readPosts() { function readPosts() {
console.warn("reading all posts") console.warn("reading all posts")
const files = fs.readdirSync(posts_dir) const files = fs.readdirSync(posts_dir)
@@ -34,7 +29,7 @@ function notFoundResponse(res) {
res.status(404).send('Sorry, can not find that') res.status(404).send('Sorry, can not find that')
} }
router.get('/', async (req, res) => { routes.set('', async (req, res) => {
if (req.query.sort === '-1' || req.query.sort === '1') { if (req.query.sort === '-1' || req.query.sort === '1') {
const posts_sorted = posts.sort((a, b) => { const posts_sorted = posts.sort((a, b) => {
return new Date(a.date).getTime() - new Date(b.date).getTime() return new Date(a.date).getTime() - new Date(b.date).getTime()
@@ -42,10 +37,13 @@ router.get('/', async (req, res) => {
if (req.query.sort === '1') res.send(posts_sorted) if (req.query.sort === '1') res.send(posts_sorted)
else res.send(posts_sorted.reverse()) else res.send(posts_sorted.reverse())
return
} }
// Default response when there are no interesting queries
res.send(posts)
}) })
router.get('/:id', async (req, res) => { routes.set('/:id', async (req, res) => {
const re = /[0-9A-Fa-f]{24}/g const re = /[0-9A-Fa-f]{24}/g
if (!re.test(req.params.id)) { if (!re.test(req.params.id)) {
@@ -58,4 +56,31 @@ router.get('/:id', async (req, res) => {
else res.send(results[0]) else res.send(results[0])
}) })
module.exports = router // For the sitemap.xml, will be listed in the XML Sitemap Index
routes.set('/urls', async (req, res) => {
const re = /(\/api\/)?(.*)\/urls/g
const result = [...req.raw.originalUrl.matchAll(re)]
if (!result) {
notFoundResponse(res)
return
}
const endpoint = result [1] ? result[1][2] : result[0][2]
// Assumes https
const BASE_URL = 'https://' + req.raw.hostname + endpoint
const urls = posts.map(post =>
`\n <url>
<loc>${BASE_URL}/${post._id}</loc>
<lastmod>${post.date}</lastmod>
<changefreq>never</changefreq>
<priority>0.9</priority>
</url>`
).join("\n")
const xml = `<?xml version="1.0" encoding="UTF-8"?>\r<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
${urls}\n\r</urlset>`
res.header('Content-Type', 'application/xml')
res.status(200).send(xml)
})
module.exports = routes