46 Commits
Author SHA1 Message Date
raymon ac5a1fa803 Keep sentence spacing in RSS feed article 2025-10-18 17:32:22 +02:00
raymon 8c005c889c Title post years per holocene calendar 2025-06-27 20:44:30 +02:00
raymon eceb031fe6 Fix minor styling issues
- Fix overflow for code blocks
- Fix navbar width
2024-12-29 22:26:54 +01:00
raymon 6f4e386e72 Provide CSS template from the website itself 2024-10-01 22:08:14 +02:00
raymon 0c2ffb4311 Cleanup main pages 2023-12-27 15:42:18 +01:00
raymon 71e0772682 Group posts by year 2023-12-27 15:25:38 +01:00
raymon 2c1a718d5c Remove custom post format 2023-12-27 14:18:23 +01:00
raymon a798f58c7d Add styling that improves readability
- article content with a max-width
- index and post index page now contain articles
- code sections are bordered, indented and padded
- figure captions are centered along with the images
- h2 margin is only removed on the post index page; page-link's
- main with extra space at the bottom to allow scolling past content
2022-12-11 16:27:01 +01:00
raymon 703de1a894 Sync assets/images used for posts 2022-09-28 18:35:45 +02:00
raymon 50fb6bee51 Remove JavaScript turn off prompt on posts page
- the joke is getting pretty old
2022-04-29 22:19:11 +02:00
raymon 9b2fd9104d Remove sorting of RSS entrees
- As RSS readers already sort by pubDate
2022-04-03 18:23:47 +02:00
raymon ff984c7046 Sort index entrees per month, by day number; descending 2022-04-03 18:16:54 +02:00
raymon f5b7a30306 Remove old #app divs
Signed-off-by: Raymonzut <me@raymon.dev>
2022-03-18 22:50:41 +01:00
raymon 65faa97ba1 Prepend title of blog post in page title
Signed-off-by: Raymonzut <me@raymon.dev>
2022-03-18 22:50:37 +01:00
raymon 9c01bc5677 Use paragraphs on qa page
Signed-off-by: Raymonzut <me@raymon.dev>
2022-03-18 22:50:32 +01:00
raymon d744073420 Ignore generated html for VC
Signed-off-by: Raymonzut <me@raymon.dev>
2022-03-18 22:49:50 +01:00
raymon f164d510d8 Allow multiple handlebars on one line
- As the HyperLisp will put most on the same line

Signed-off-by: Raymonzut <me@raymon.dev>
2022-03-18 22:49:43 +01:00
raymon 24a9a34a73 Use the HyperLisp preprocessor for all html
:D

Signed-off-by: Raymonzut <me@raymon.dev>
2022-03-18 22:49:39 +01:00
raymon bfcd3f9c8f Prompt user to turn off JavaScript on posts page
- Credits to Heydon Pickering
  - From the talk "State of the browser 2021; Please Disable JavaScript To View This Site"

Signed-off-by: Raymonzut <me@raymon.dev>
2022-03-18 22:49:35 +01:00
raymon cb77ed1a2d Add upload helper script
Signed-off-by: Raymonzut <me@raymon.dev>
2022-03-18 22:48:58 +01:00
Raymon Zutekouw 4b9f9b301c Merge branch 'beta' 2021-11-24 20:29:12 +01:00
Raymon Zutekouw 61b3cb1500 Exclude already wrapped paragraphs from <p> wrapping
- Allows `paragraph \n header \n paragraph`
- Allows `paragraph \n  list  \n paragraph`
2021-11-23 12:31:58 +01:00
Raymon Zutekouw b3fe972d0e Move \n -> paragraphs out of fill_template
- As it should only be done for the custom format
2021-11-23 12:07:02 +01:00
Raymon Zutekouw 266b6e0733 Improve formatting in RSS feed, to make it valid 2021-11-23 12:06:02 +01:00
Raymon Zutekouw 6ed757b81b Keep : between hours, minutes, seconds 2021-11-23 11:09:58 +01:00
Raymon Zutekouw 12741a20c5 Remove old link remains
- id's in posts
- /api route
2021-11-23 11:00:11 +01:00
Raymon Zutekouw 4cebaf550b Folder by year/month instead of id under one folder 2021-11-18 20:41:20 +01:00
Raymon Zutekouw 04b41fa182 Fix spelling mistake 2021-11-15 18:27:07 +01:00
Raymon Zutekouw 9e0d3954d2 Swap h3 for p,strong for RSS subscribe header 2021-10-25 11:38:43 +02:00
Raymon Zutekouw 2d6e087342 Extend post format options with .org files 2021-04-28 12:34:36 +02:00
Raymonzut 8d5e9c02ad Merge branch 'beta' into master 2021-01-19 17:48:53 +01:00
Raymonzut a0eb56e115 Remove dynamic age feature 2021-01-19 17:40:48 +01:00
Raymonzut 6c31c8752d Join date sort order function to one line
- Fixes not using year in order calculation
2021-01-08 21:33:28 +01:00
Raymonzut 8e15354c2a Add ExamplePost 2020-11-26 23:08:08 +01:00
Raymonzut 3f888cbeb8 Merge branch 'beta' into master 2020-11-13 19:53:01 +01:00
Raymonzut f82b6ba8f6 Add docker-compose.yaml for client 2020-11-12 18:14:56 +01:00
Raymonzut bf0b5448b6 Fix #13 2020-11-12 17:36:40 +01:00
Raymonzut 6271fbb3b0 Rename gen.ex to gen.exs, as it is a script 2020-11-07 11:45:20 +01:00
Raymonzut eff86a1f3e Fix #12
- move pre-gen files out of public/
2020-11-07 11:43:14 +01:00
Raymonzut 403fc9d5cb Account for multiple years for sorting posts
- Prepare for 2021
2020-11-06 22:38:10 +01:00
Raymonzut 67b8a4f581 Update index gen for new date format 2020-11-06 22:18:27 +01:00
Raymonzut e9d50f1392 Extract template filling: pair usage consistant 2020-10-09 23:31:54 +02:00
Raymonzut 5d2fd6674f Merge branch 'beta' into master 2020-10-09 17:35:18 +02:00
Raymonzut 2a128f49ab Add extra experiment to README 2020-10-09 00:43:25 +02:00
Raymonzut b5403fbc0c Add README.md 2020-10-09 00:41:43 +02:00
Raymonzut 39aff9d684 Remove node ignorefile remnants 2020-10-02 16:39:42 +02:00
30 changed files with 737 additions and 308 deletions
-2
View File
@@ -1,4 +1,2 @@
**/node_modules
**/dist
.git .git
.gitignore .gitignore
-22
View File
@@ -1,22 +0,0 @@
## Node ###
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Dependency directories
node_modules/
# Build
dist/
+32
View File
@@ -0,0 +1,32 @@
# Personal-Website
[![built with HyperLisp!](https://img.shields.io/badge/built%20with-HyperLisp!-informational)](https://github.com/circl-lastname/HyperLisp)
A nice introduction to my chaos
## Backstory
Instead of calling it my Personal-Website, you could better call it my Personal-Playground.
This repo is an example of not being afraid to change a codebase around.
It shows the journey of achieving code that fits the needs.
The posts started with pure excitement from building this site.
Making my own content and having complete contol over the format thrilled me.
For me, it is about making memorable content, something I can proudly look back on.
Sarcastic, serious and suprising content.
Which becomes super silly stuff when looking back at it ;)
## Content
Once in a while you can enjoy a new post on the website.
The posts started talking about the website and all changes that came along.
As the website is quite far in development, more focus is put into making relaxing content to read through.
## Experimentations
- Swapping QA page for a podcast page
- Adding a code++ page: page with a collection of helpful code improvements I came across
- Adding a portfolio
## Thank you
Thanks for reading all of this!
If you have any questions or sugestions, feel free to send an e-mail to me@raymon.dev.
-1
View File
@@ -1 +0,0 @@
**/node_modules
+10
View File
@@ -0,0 +1,10 @@
public/*.html
public/error/*.html
templates/*.html
public/assets/images/*
posts_custom/*
!posts_custom/ExamplePostCustomFormat
posts_org/*
!posts_org/ExamplePostOrgFormat.org
-1
View File
@@ -1,4 +1,3 @@
FROM nginx as production-stage FROM nginx as production-stage
RUN mkdir /app RUN mkdir /app
COPY /public /app
COPY nginx.conf /etc/nginx/nginx.conf COPY nginx.conf /etc/nginx/nginx.conf
+129
View File
@@ -0,0 +1,129 @@
# Templates will be filled by posts
index_template = File.read!("./templates/post_index_page.html")
post_template = File.read!("./templates/post_single_page.html")
post_feed_item_template = File.read!("./templates/post_item.xml")
post_feed_template = File.read!("./templates/posts.xml")
# Converting handlebars in template to values
fill_template = fn template, pairs ->
~r/{{(.*)}}/U
|> Regex.replace(template, fn _, key -> Map.get(pairs, String.to_atom(key)) end)
end
fill_template_pretemplated = fn template -> &fill_template.(template, &1) end
filterCutFileExtension = fn files ->
fn ext ->
Enum.filter(files, &String.ends_with?(&1, "." <> ext))
|> Enum.map(&String.replace_suffix(&1, "." <> ext, ""))
|> (fn x -> %{String.to_atom(ext) => x} end).()
end
end
isMeta = &String.starts_with?(&1, "#+")
posts_org =
File.ls!("./posts_org")
|> Enum.reject(fn x -> String.starts_with?(x, ".") end)
|> (fn files -> Enum.map(["org", "html"], filterCutFileExtension.(files)) end).()
|> Enum.reduce(%{}, fn x, acc -> Map.merge(x, acc) end)
post_contents_org =
Enum.filter(Map.get(posts_org, :org), fn el -> Enum.member?(Map.get(posts_org, :html), el) end)
|> Enum.map(
&(File.read!("./posts_org/" <> &1 <> ".org")
|> (fn fileContent -> String.split(fileContent, "\n") end).()
|> Enum.take_while(isMeta)
|> Enum.map(fn metaOrg ->
[head | tail] = String.split(metaOrg, ":")
%{
(String.slice(head, 2..-1) |> String.downcase() |> String.to_atom()) =>
String.slice(Enum.join(tail, ":"), 1..-1)
}
end)
|> Enum.reduce(%{:content => File.read!("./posts_org/" <> &1 <> ".html")}, fn x, acc ->
Map.merge(x, acc)
end))
)
months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
dateFolder = fn p ->
Map.get(p, :date)
|> String.slice(8..15)
|> String.split(" ")
|> (fn ([month, year]) -> year <> "/" <> Integer.to_string(Enum.find_index(months, &(&1 == month)) + 1) <> "/" end).()
end
normalize_title = fn title -> String.replace(String.downcase(title), " ", "-") end
constructLocalPath = fn p -> dateFolder.(p) <> normalize_title.(Map.get(p, :title)) end
post_contents = post_contents_org
|> Enum.map(fn postMap -> Map.merge(postMap, %{localpath: (constructLocalPath.(postMap))}) end)
date_sort = fn post ->
date = Map.get(post, :date)
month = Enum.find_index(months, &(&1 == String.slice(date, 8..10)))
day = elem(Integer.parse(String.slice(date, 5..6)), 0)
32 * month + day
end
index_file =
post_contents
|> Enum.sort_by(
&(Map.get(&1, :date)
|> String.slice(5..6)
|> Integer.parse())
)
|> Enum.reverse()
# Group by year
|> Enum.group_by(fn m -> Map.get(m, :date) |> String.slice(12..15) end)
|> Enum.sort_by(fn {d, _c} -> Integer.parse(d) end)
|> Enum.reverse()
|> Enum.map(fn {year, posts} -> "\n<h1>" <> "12," <> (year |> String.slice(1..3)) <> "</h1>\n<ul>" <> (posts |> Enum.sort_by(date_sort) |> Enum.reverse() |>
Enum.map(fn post -> "<li class=\"post-link\">" <>
"<time datetime=\""<> Map.get(post, :date) <> "\">" <> (Map.get(post, :date) |> String.slice(0..10)) <> "</time>" <>
" - " <>
"<a href=\"" <> Map.get(post, :localpath) <> ".html\">" <> Map.get(post, :title) <> "</a>" <>
"</li>"
end) |> Enum.join("\n")) end)
|> Enum.join("\n</ul>")
|> (fn v -> %{index: v} end).()
|> fill_template_pretemplated.(index_template).()
File.open!("./public/gen/index.html", [:write])
|> IO.binwrite(index_file)
|> File.close()
prepare_path = fn path ->
File.mkdir_p!(Path.dirname(path))
path
end
post_contents
|> Enum.each(fn post -> post
|> (fn p -> "./public/gen/" <> Map.get(p, :localpath) <> ".html" end).()
|> prepare_path.()
|> File.open!([:write])
|> IO.binwrite(fill_template.(post_template, post))
|> File.close()
end)
stripForRSS = fn content -> content
|> String.replace("\n", " ")
end
post_feed =
post_contents
|> Enum.map(fn m -> Map.update!(m, :content, stripForRSS) end)
|> Enum.map(fill_template_pretemplated.(post_feed_item_template))
|> Enum.join("\n")
|> (fn v -> %{items: v} end).()
|> fill_template_pretemplated.(post_feed_template).()
File.open!("./public/gen/rss.xml", [:write])
|> IO.binwrite(post_feed)
|> File.close()
-7
View File
@@ -7,9 +7,6 @@ events {
} }
http { http {
include /etc/nginx/mime.types; include /etc/nginx/mime.types;
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" '
@@ -29,10 +26,6 @@ http {
alias /app/assets/styling; alias /app/assets/styling;
} }
location /js {
alias /app/lib;
}
location /posts { location /posts {
alias /app/gen/; alias /app/gen/;
} }
@@ -0,0 +1,3 @@
#+TITLE: Example post for my new org-gen post page!
#+DATE: Wed, 28 Apr 2021 11:25:00 GMT
My new posts page is live, this post has been generated from an org file
-1
View File
@@ -1,2 +1 @@
posts/*
gen/* gen/*
+26 -1
View File
@@ -13,10 +13,34 @@
} }
nav { nav {
width: 100vw;
border-bottom-left-radius: 5px; border-bottom-left-radius: 5px;
border-bottom-right-radius: 5px; border-bottom-right-radius: 5px;
} }
main {
padding-bottom: 12em;
}
article {
max-width: 1000px;
margin: auto;
}
pre {
padding: 1em;
padding-left: 2em;
border: solid;
border-radius: 1em;
border-width: 1px;
border-color: var(--text-color);
overflow: scroll;
}
.figure > p {
text-align: center;
}
.question { .question {
font-style: italic; font-style: italic;
} }
@@ -25,7 +49,8 @@ h1 {
font-size: 2.0em; font-size: 2.0em;
} }
h2 { .post-link {
font-family: monospace;
font-size: 1.25em; font-size: 1.25em;
margin: auto 0; margin: auto 0;
} }
+422
View File
@@ -0,0 +1,422 @@
/* Variables */
:root {
--body-color: rgb(250,250,250);
--body-background: rgb(30,40,60);
--body-font-family: 'Oxygen', sans-serif;
--body-scrollbar-color: dark;
--body-margin: 10vw;
--body-max-width: 1920px;
--body-div-margin: 0;
--body-div-padding: 0;
--body-div-max-width: none;
--a-color: white;
--a-text-decoration-color: #09c5f4;
--code-color: white;
--code-background: rgba(0,0,0,0.25);
--code-font-family: 'Oxygen Mono', monospace;
--kbd-font-family: var(--code-font-family);
--kbd-border: 1px solid white;
--var-font-family: var(--code-font-family);
--var--color: orange;
--nav-color: black;
--nav-background: rgba(255,255,255,0.75);
--nav-padding: 1em 0.5em 1em 0.5em;
--details-background: rgba(0,0,0,0.25);
--details-padding: .75em;
--mark-color: black;
--mark-background: rgb(239,219,67);
--img-margin-left: auto;
--img-margin-right: auto;
--table-max-width: 500px;
--table-border: 1px solid white;
--table-tr-even-background: rgba(255,255,255,0.1);
--select-border-color: white;
--select-glyph: url('data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22292.4%22%20height%3D%22292.4%22%3E%3Cpath%20fill%3D%22%23FFFFFF%22%20d%3D%22M287%2069.4a17.6%2017.6%200%200%200-13-5.4H18.4c-5%200-9.3%201.8-12.9%205.4A17.6%2017.6%200%200%200%200%2082.2c0%205%201.8%209.3%205.4%2012.9l128%20127.9c3.6%203.6%207.8%205.4%2012.8%205.4s9.2-1.8%2012.8-5.4L287%2095c3.5-3.5%205.4-7.8%205.4-12.8%200-5-1.9-9.2-5.5-12.8z%22%2F%3E%3C%2Fsvg%3E');
--input-border: 1px solid white;
--input-max-width: 500px;
--input-font-size: 1em;
--input-disabled-background: rgba(255,255,255,.1);
--button-background: #09c5f4;
--button-color: white;
}
/* Body */
body {
margin: 0;
margin-left: var(--body-margin);
margin-right: var(--body-margin);
max-width: var(--body-max-width);
padding: 0;
font-family: var(--body-font-family);
color: var(--body-color);
background: var(--body-background);
scrollbar-color: var(--body-scrollbar-color);
line-height: 1.5;
text-rendering: optimizeLegibility;
}
body > div {
margin-left: var(--body-div-margin);
margin-right: var(--body-div-margin);
padding-left: var(--body-div-padding);
padding-right: var(--body-div-padding);
max-width: var(--body-max-width);
}
@media (max-width: 960px) {
body {
margin-left: calc(var(--body-margin) / 2);
margin-right: calc(var(--body-margin) / 2);
}
body > div {
margin-left: calc(var(--body-div-margin) / 2);
margin-right: calc(var(--body-div-margin) / 2);
}
}
/* Text */
h1, h2, h3, h4, h5, h6 {}
pre > code {
padding: 10px;
display: block;
overflow-x: auto;
}
code {
user-select: all;
background: var(--code-background);
color: var(--code-color);
font-size: 1em;
font-family: var(--code-font-family);
padding: 0.5em;
border-radius: 5px;
display: inline-block;
}
kbd {
font-family: var(--kbd-font-family);
display: inline-block;
user-select: all;
padding: 0.5em;
border-radius: 5px;
border: var(--kbd-border);
font-family: var(--body-font-family);
}
var {
color: var(--var-color);
font-style: normal;
font-family: var(--var-font-family);
}
a {
color: var(--a-color);
scroll-behavior: smooth;
text-decoration: underline;
text-decoration-color: var(--a-text-decoration-color);
transition: color .15s ease;
text-decoration-skip: edges;
text-decoration-skip-ink: auto;
}
a:hover {
color: var(--a-text-decoration-color);
}
textarea {
resize: vertical;
}
details {
display: flex;
flex-direction: column;
align-items: flex-start;
background-color: var(--details-background);
padding: var(--details-padding) var(--details-padding) 0;
margin-top: 1em;
margin-bottom: 1em;
border-radius: 5px;
overflow: hidden;
}
details[open] {
padding: var(--details-padding)
}
details > :last-child {
margin-bottom: 0;
}
details[open] summary {
margin-bottom: 10px;
}
summary {
display: list-item;
padding: var(--details-padding);
margin: calc(-1 * var(--details-padding)) calc(-1 * var(--details-padding)) 0;
user-select: none;
}
details > :not(summary) {
margin-top: 0;
}
mark {
background: var(--mark-background);
color: var(--mark-color);
padding: 0.15em;
}
/* Navigation */
nav {
max-width: none;
margin-left: calc(var(--body-margin) * -1);
margin-right: calc(var(--body-margin) * -1);
display: flex;
flex-wrap: nowrap;
justify-content: space-around;
align-items: center;
width: 100%;
color: var(--nav-color);
background: var(--nav-background);
-webkit-backdrop-filter: blur(10px);
backdrop-filter: blur(10px);
position: sticky;
top: 0;
left: 0;
}
@media (max-width: 960px) {
nav {
margin-left: calc(var(--body-margin) * -1 / 2);
margin-right: calc(var(--body-margin) * -1 / 2);
}
}
nav * {
display: block;
padding: var(--nav-padding);
color: var(--nav-color);
}
nav a {
text-decoration: none;
font-weight: bold;
}
/* Tables */
table {
border-collapse: collapse;
display: block;
width: 100%;
max-width: var(--table-max-width);
overflow-x: auto;
}
table > tbody > tr > td, table > tbody > tr > th {
border: var(--table-border);
text-align: left;
padding: 0.5em;
}
table > tbody > tr:nth-child(even) {
background: var(--table-tr-even-background);
}
table > thead > tr > td, table > thead > tr > th, table > tfoot > tr > td, table > tfoot > tr > th {
padding: 0.5em;
border: none;
text-align: center;
}
/* Images */
img {
display: block;
max-width: 100%;
height: auto;
margin-left: var(--img-margin-left);
margin-right: var(--img-margin-right);
}
/* Forms */
fieldset {
border-radius: 5px;
border: 1px solid white;
margin-inline-start: 0;
margin-inline-end: 0;
padding-block-start: 0;
padding-block-end: 0;
padding-inline-start: 0;
padding-inline-end: 0;
padding: 1em;
}
select {
font-size: var(--input-font-size);
display: inline-block;
padding: .5em;
width: 100%;
max-width: 500px;
box-sizing: border-box;
}
select option {
background: var(--body-background);
font-weight: normal;
}
select[multiple] {
color: var(--body-color);
display: inline-block;
color: #444;
padding: 0.5em;
border-radius: 0;
width: 100%;
max-width: 250px;
box-sizing: border-box;
border: 1px solid var(--select-border-color);
background: rgba(0,0,0,.25);
}
select[multiple] > option {
color: var(--body-color);
background: rgba(0,0,0,0);
}
@supports(-webkit-appearance: none) or (-moz-appearance: none) or (appearance: none) {
input[type='checkbox'], input[type='radio'] {
appearance: none;
-webkit-appearance: none;
-moz-appearance: none;
}
select {
font-size: var(--input-font-size);
display: inline-block;
font-size: 1em;
color: var(--body-color);
padding: .5em;
width: 100%;
max-width: 500px;
box-sizing: border-box;
border: 1px solid var(--select-border-color);
box-shadow: none;
border-radius: .5em;
-moz-appearance: none;
-webkit-appearance: none;
appearance: none;
background: rgba(0,0,0,.25);
background-image: var(--select-glyph);
background-repeat: no-repeat, repeat;
background-position: right .7em top 50%, 0 0;
background-size: .65em auto, 100%;
}
select::-ms-expand {
display: none;
}
select[multiple] {
color: var(--body-color);
display: inline-block;
color: #444;
padding: 0.5em;
border-radius: 0;
width: 100%;
max-width: 250px;
box-sizing: border-box;
border: 1px solid var(--select-border-color);
background: rgba(0,0,0,.25);
}
select[multiple] > option {
color: var(--body-color);
}
}
input:not([type="submit"]):not([type="checkbox"]):not([type="radio"]):not([type="range"]), textarea {
font-size: var(--input-font-size);
color: var(--body-color);
font-family: var(--body-font-family);
background: rgba(0,0,0,.25);
padding: 0.5em;
width: 100%;
max-width: var(--input-max-width);
margin-bottom: 1em;
box-sizing: border-box;
resize: none;
border-radius: 0.5em;
border: var(--input-border);
}
input:disabled:not([type="submit"]):not([type="checkbox"]):not([type="radio"]):not([type="range"]) {
background: var(--input-disabled-background);
}
button, select, input[type='submit'], input[type='button'], input[type='checkbox'], input[type='range'], input[type='radio'] {
cursor: pointer;
}
button, .button {
display: inline-block;
border: none;
padding: 1rem 2rem;
margin: 0;
text-decoration: none;
background: var(--button-background);
color: var(--button-color);
font-size: 1em;
text-align: center;
transition: background 250ms ease-in-out,
transform 150ms ease;
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
}
button:hover, button:focus, .button:hover, .button:focus {
background: #0053ba;
}
button:focus, .button:focus {
outline: 1px solid #fff;
outline-offset: -4px;
}
button:active, .button:active {
transform: scale(0.99);
}
/* Animations */
details[open] summary ~ * {
animation: sweep 0.1s ease-in-out;
}
@keyframes sweep {
0% {opacity: 0; margin-top: -10px; margin-bottom: 10px;}
90% {opacity: 1; margin-top: -1px; margin-bottom: 1px;}
100% {opacity: 1; margin-top: 0px; margin-bottom: 0;}
}
-10
View File
@@ -1,10 +0,0 @@
<!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>
+6
View File
@@ -0,0 +1,6 @@
(html :lang 'en :dir 'ltr
(head
(meta :charset 'utf-8)
(title "404"))
(body
"This page could not be found, sorry for the inconvenience"))
-69
View File
@@ -1,69 +0,0 @@
# Templates will be filled by posts
index_template = File.read!("./templates/post_index_page.html")
post_template = File.read!("./templates/post_single_page.html")
post_feed_item_template = File.read!("./templates/post_item.xml")
post_feed_template = File.read!("./templates/posts.xml")
post_contents = File.ls!("./posts")
|> Enum.reject(fn(x) -> String.starts_with?(x, ".") end)
|> Enum.map(fn f -> File.read!("./posts/" <> f) end)
|> Enum.map(fn c -> String.split(c, "\n") end)
|> Enum.map(fn c -> Enum.reject(c, fn(x) -> x == "" end) end)
|> Enum.map(fn c -> Enum.chunk_every(c, 2) end)
|> Enum.map(fn c ->
Enum.map(c, fn [k, v] -> %{String.to_atom(k) => v} end)
|> Enum.reduce(%{}, fn(x, acc) -> Map.merge(x, acc) end)
end)
index_file = post_contents
|> Enum.sort_by(fn m -> Map.get(m, :date) end)
|> Enum.reverse()
# Group by month
|> Enum.group_by(fn m -> Map.get(m, :date) |> String.slice(0..6) end)
|> Enum.reverse()
|> Enum.map(fn {month, posts} -> "\n<h1>" <> month <> "</h1>\n" <> (posts |>
Enum.map(fn post -> "<h2>" <> (Map.get(post, :date) |> String.slice(0..9)) <>
" - <a href=\"" <> Map.get(post, :id) <> ".html\">" <> Map.get(post, :title) <> "</a></h2>"
end) |> Enum.join("\n")) end)
|> (fn template -> Regex.replace(Regex.compile!("{{index}}"), index_template, fn _, __ -> template end) end).()
File.open!("./gen/index.html", [:write])
|> IO.binwrite(index_file)
|> File.close()
post_contents
|> Enum.each(fn post ->
File.open!("./gen/" <> Map.get(post, :id) <> ".html", [:write])
|> IO.binwrite(
# Converting handlebars to values
Regex.compile!("{{(.*)}}") |>
Regex.replace(post_template, fn _, key -> if key != "content" do Map.get(post, String.to_atom(key)) else
Map.get(post, String.to_atom(key))
# Converting \n to paragraphs
|> String.split("\\n")
|> Enum.reject(fn(x) -> x == "" end)
|> Enum.map(fn paragraph -> ("<p>" <> paragraph <> "</p>\n") end)
|> Enum.join("")
end
end))
|> File.close()
end)
post_feed = post_contents
|> Enum.sort_by(fn m -> Map.get(m, :date) end)
|> Enum.reverse()
|> Enum.map(fn post ->
Regex.compile!("{{(.*)}}") |>
Regex.replace(post_feed_item_template, fn _, key -> Map.get(post, String.to_atom(key))
end)
end)
|> Enum.join("\n")
|> (fn items -> (Regex.compile!("{{items}}") |>
Regex.replace(post_feed_template, fn _, __ -> items end))
end).()
File.open!("./gen/rss.xml", [:write])
|> IO.binwrite(post_feed)
|> File.close()
-53
View File
@@ -1,53 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta
name="description"
content="Raymon's personal website about his life and projects with a blog.">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Raymon Zutekouw</title>
<link rel="preload" href="./lib/me.mjs" as="script" crossorigin="anonymous" type="application/javascript">
<link rel="preload" href="index.mjs" as="script" crossorigin="anonymous" type="application/javascript">
<link rel="dns-prefetch" href="https://cdn.statically.io">
<link defer
rel="stylesheet"
href="https://cdn.statically.io/gh/dragonprojects/dragondesign/master/main.min.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>
<h1>Home</h1>
<div>
<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>
<script async type="module" src="index.mjs"></script>
</body>
</html>
+33
View File
@@ -0,0 +1,33 @@
(html :lang 'en
(head
(meta :charset 'utf-8)
(meta :name 'description
:content "Raymon's personal website about his life and projects with a blog.")
(meta :name 'viewport :content "width=device-width, initial-scale=1.0")
(title "Raymon Zutekouw")
(link :defer '
:rel 'stylesheet
:href "/css/template.css"
:media 'all)
(link :defer '
:rel 'stylesheet
:href "/css/general.css"
:media 'all))
(body
(main
(nav
(a :href "/" "Home") "|"
(a :href "/posts" "Posts"))
(article
(header
(h1 "Home"))
(p "Hi there, good to see you on my website.
My name is Raymon Zutekouw; Self-taught programmer by heart.")
(p "Building software and exploring the wide variety of tools (or making them) is my passion.
To see it in action, "
(a :href "https://git.raymon.dev/raymon" "checkout the stuff I make here."))
(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"))))))
-4
View File
@@ -1,4 +0,0 @@
import { age } from "./lib/me.mjs"
const age_span = document.getElementById("age")
age_span.textContent = age().toString()
-17
View File
@@ -1,17 +0,0 @@
export function age() {
let birthdate = new Date("29 August 2002")
let now = new Date()
let age = now.getFullYear() - birthdate.getFullYear()
if (now.getMonth() < birthdate.getMonth())
age--
if (
birthdate.getMonth() === now.getMonth() &&
now.getDate() < birthdate.getDate()
)
age--
return age
}
View File
-35
View File
@@ -1,35 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta
name="description"
content="Raymon answering common questions">
<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/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>
@@ -1,31 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta
name="description"
content="Raymon typing nonsense on his blog">
<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/general.css" media="all">
</head>
<body>
<main>
<nav>
<a href="/">Home</a>|
<a href="/posts">Posts</a>|
<a href="/qa">QA</a>
</nav>
<header>
<h1>Post listing</h1>
</header>
{{index}}
</main>
</body>
</html>
-14
View File
@@ -1,14 +0,0 @@
<item>
<title>{{title}}</title>
<link>https://raymon.dev/posts/{{id}}.html</link>
<guid>https://raymon.dev/posts/{{id}}.html</guid>
<description>
<![CDATA[
{{content}}
]]>
</description>
<content type="html">
{{content}}
</content>
<pubDate>{{date}}</pubDate>
</item>
@@ -1,36 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta
name="description"
content="Raymon typing nonsense on his blog">
<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/general.css" media="all">
</head>
<body>
<main>
<nav>
<a href="/">Home</a>|
<a href="/posts">Posts</a>|
<a href="/qa">QA</a>
</nav>
<article>
<header>
<h1>{{title}}</h1>
<h3>For those using a RSS reader, subscribe here: <a href="/posts/rss.xml">rss.xml</a></h3>
</header>
<time datetime="{{date}}"></time>
{{content}}
</article>
</main>
</body>
</html>
+25
View File
@@ -0,0 +1,25 @@
(html :lang 'en
(head
(meta :charset 'utf-8)
(meta :name 'description
:content "Raymon typing nonsense on his blog")
(meta :name 'viewport :content "width=device-width, initial-scale=1.0")
(title "Raymon Zutekouw")
(link :defer '
:rel 'stylesheet
:href "/css/template.css"
:media 'all)
(link :defer '
:rel 'stylesheet
:href "/css/general.css"
:media 'all))
(body
(main
(nav
(a :href "/" "Home") "|"
(a :href "/posts" "Posts"))
(article
(header
(h1 "Post listing"))
"{{index}}"))))
+9
View File
@@ -0,0 +1,9 @@
<item>
<title>{{title}}</title>
<link>https://raymon.dev/posts/{{localpath}}.html</link>
<guid>https://raymon.dev/posts/{{localpath}}.html</guid>
<pubDate>{{date}}</pubDate>
<description><![CDATA[
{{content}}
]]></description>
</item>
+28
View File
@@ -0,0 +1,28 @@
(html :lang 'en
(head
(meta :charset 'utf-8)
(meta :name 'description
:content "Raymon typing nonsense on his blog")
(meta :name 'viewport :content "width=device-width, initial-scale=1.0")
(title "{{title}} :: Raymon Zutekouw")
(link :defer '
:rel 'stylesheet
:href "/css/template.css"
:media 'all)
(link :defer '
:rel 'stylesheet
:href "/css/general.css"
:media 'all))
(body
(main
(nav
(a :href "/" "Home") "|"
(a :href "/posts" "Posts"))
(article
(header
(h1 "{{title}}")
(p (strong "For those using a RSS reader, subscribe here: ")
(a :href "/posts/rss.xml" "rss.xml")))
(time :datetime "{{date}}")
"{{content}}"))))
@@ -1,12 +1,11 @@
<?xml version="1.0" encoding="UTF-8" ?> <?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"> <rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel> <channel>
<atom:link href="https://raymon.dev/api/posts/rss.xml" rel="self" type="application/rss+xml" /> <title>Raymon Zutekouw</title>
<title>Posts</title>
<link>https://raymon.dev</link>
<description>Personal blog</description> <description>Personal blog</description>
<language>en-us</language> <language>en-us</language>
<link>https://raymon.dev</link>
<atom:link href="https://raymon.dev/posts/rss.xml" rel="self" type="application/rss+xml" />
{{items}} {{items}}
</channel> </channel>
</rss> </rss>
+3
View File
@@ -0,0 +1,3 @@
rsync -avz public/assets/images/ raymon.dev:~/Personal-Website/client/public/assets/images
rsync -avz public/gen/ raymon.dev:~/Personal-Website/client/public/gen/
rsync -avz posts_org/ raymon.dev:~/Personal-Website/client/posts_org
+8
View File
@@ -0,0 +1,8 @@
version: "3.3"
services:
client:
build: client/
ports:
- "5010:80"
volumes:
- "./client/public:/app:rw"