added reading mode for blog posts

This commit is contained in:
Ellpeck 2019-10-09 15:51:43 +02:00
parent 71916a7f6f
commit 30b3dec0fa
7 changed files with 185 additions and 80 deletions

7
.gitignore vendored
View File

@ -1,2 +1,7 @@
node_modules
package-lock.json
package-lock.json
sitemap.xml
feed.json
rss.xml
atom.xml
blog-*.html

View File

@ -51,7 +51,7 @@
<!-- Navbar content -->
<div class="collapse navbar-collapse" id="navbar-content">
<div class="navbar-nav mr-auto">
<div class="navbar-nav mr-auto" id="nav-items">
<a class="nav-item nav-link" href="#projects">Projects</a>
<a class="nav-item nav-link" href="#social">Social</a>
<a class="nav-item nav-link" href="#about">About</a>
@ -68,92 +68,94 @@
<!-- Content -->
<div class="container main">
<!-- Home -->
<div class="jumbotron">
<div class="container">
<div class="row">
<div class="col-md-auto">
<img src="res/me.png" class="rounded-circle" width="200" height="200" id="navbar-image">
</div>
<div class="col">
<h1 class="display-4" id="intro-text"></h1>
<script src="scripts/greet.js"></script>
<p class="lead">Welcome to my little website! I'm Ellpeck, a student and programmer from Germany. I do a lot of stuff, actually. My life is pretty busy.</p>
<p>Look around this website to find out more about my projects and other places you can find me!</p>
</div>
</div>
</div>
</div>
<!-- Cookie notification -->
<script src="scripts/cookies.js"></script>
<!-- Projects -->
<a class="anchor" id="projects"></a>
<div class="list-display rounded">
<h1>Projects</h1>
<p>
Here is a list of some of the things that you might know me from. If you want to have a more in-depth look at everything I do, check out some of the sites linked in the <a href="#social">Social</a> section.
</p>
<div id="project-list">
<em>The content that should be here is dynamically generated. Please enable JavaScript if you see this.</em>
</div>
<script src="scripts/projects.js"></script>
</div>
<!-- Social -->
<a class="anchor" id="social"></a>
<div class="list-display rounded">
<h1>Social</h1>
<p>
These are other websites where you can find me and the things I do, including the pages where I publish my code and games and where I sometimes stream and upload videos. This list also includes a lot of ways to reach me.
</p>
<div class="row">
<div class="col">
<div id="social-list">
<em>The content that should be here is dynamically generated. Please enable JavaScript if you see this.</em>
<div id="main">
<!-- Home -->
<div class="jumbotron">
<div class="container">
<div class="row">
<div class="col-md-auto">
<img src="res/me.png" class="rounded-circle" width="200" height="200" id="navbar-image">
</div>
<div class="col">
<h1 class="display-4" id="intro-text"></h1>
<script src="scripts/greet.js"></script>
<p class="lead">Welcome to my little website! I'm Ellpeck, a student and programmer from Germany. I do a lot of stuff, actually. My life is pretty busy.</p>
<p>Look around this website to find out more about my projects and other places you can find me!</p>
</div>
</div>
Additionally, here are some miscellaneous platforms:
<ul>
<li>My Nintendo Switch friend code is <strong>SW-5281-8834-6801</strong></li>
<li>If you want to play my Mario Maker 2 levels, my ID is <strong>8BH-566-4WF</strong></li>
<li>If you play The Sims 4, you can check out my builds on the gallery by searching for <strong>Ellpeck</strong></li>
</ul>
</div>
<div class="col-md-auto" id="discord-div">
</div>
<!-- Projects -->
<a class="anchor" id="projects"></a>
<div class="list-display rounded">
<h1>Projects</h1>
<p>
Here is a list of some of the things that you might know me from. If you want to have a more in-depth look at everything I do, check out some of the sites linked in the <a href="#social">Social</a> section.
</p>
<div id="project-list">
<em>The content that should be here is dynamically generated. Please enable JavaScript if you see this.</em>
</div>
<script src="scripts/projects.js"></script>
</div>
<script src="scripts/social.js"></script>
</div>
<!-- Social -->
<a class="anchor" id="social"></a>
<div class="list-display rounded">
<h1>Social</h1>
<p>
These are other websites where you can find me and the things I do, including the pages where I publish my code and games and where I sometimes stream and upload videos. This list also includes a lot of ways to reach me.
</p>
<div class="row">
<div class="col">
<div id="social-list">
<em>The content that should be here is dynamically generated. Please enable JavaScript if you see this.</em>
</div>
<!-- About -->
<a class="anchor" id="about"></a>
<div class="list-display rounded">
<h1>About</h1>
<p>
Sometimes, some people ask me some questions about myself or my projects, so I decided to compile a list of some of the answers in a Q&A-like fashion so that I don't have to keep repeating them. If you're curious about me, this might be interesting to you!
</p>
<div id="about-list">
<em>The content that should be here is dynamically generated. Please enable JavaScript if you see this.</em>
Additionally, here are some miscellaneous platforms:
<ul>
<li>My Nintendo Switch friend code is <strong>SW-5281-8834-6801</strong></li>
<li>If you want to play my Mario Maker 2 levels, my ID is <strong>8BH-566-4WF</strong></li>
<li>If you play The Sims 4, you can check out my builds on the gallery by searching for <strong>Ellpeck</strong></li>
</ul>
</div>
<div class="col-md-auto" id="discord-div">
<em>The content that should be here is dynamically generated. Please enable JavaScript if you see this.</em>
</div>
</div>
<script src="scripts/social.js"></script>
</div>
<script src="scripts/about.js"></script>
</div>
<!-- Blog -->
<a class="anchor" id="blog"></a>
<div class="list-display rounded">
<h1>Blog</h1>
<p>
Occasionally I enjoy writing stuff. So here's some of the stuff I've written. Just click on any of the headers to expand the post. Alternatively, you can subscribe to this blog using <a href="/rss.xml">RSS</a>, <a href="/atom.xml">Atom</a> or <a href="/feed.json">JSON</a>.
</p>
<div id="blog-list">
<em>The content that should be here is dynamically generated. Please enable JavaScript if you see this.</em>
<!-- About -->
<a class="anchor" id="about"></a>
<div class="list-display rounded">
<h1>About</h1>
<p>
Sometimes, some people ask me some questions about myself or my projects, so I decided to compile a list of some of the answers in a Q&A-like fashion so that I don't have to keep repeating them. If you're curious about me, this might be interesting to you!
</p>
<div id="about-list">
<em>The content that should be here is dynamically generated. Please enable JavaScript if you see this.</em>
</div>
<script src="scripts/about.js"></script>
</div>
<!-- Blog -->
<a class="anchor" id="blog"></a>
<div class="list-display rounded">
<h1>Blog</h1>
<p>
Occasionally I enjoy writing stuff. So here's some of the stuff I've written. Just click on any of the headers to expand the post. Alternatively, you can subscribe to this blog using <a href="/rss.xml">RSS</a>, <a href="/atom.xml">Atom</a> or <a href="/feed.json">JSON</a>.
</p>
<div id="blog-list">
<em>The content that should be here is dynamically generated. Please enable JavaScript if you see this.</em>
</div>
<script src="scripts/blog.js"></script>
</div>
<script src="scripts/blog.js"></script>
</div>
</div>

62
node/blog.js Normal file
View File

@ -0,0 +1,62 @@
const {
JSDOM
} = require("jsdom");
const fs = require("fs");
require("showdown-prettify");
const showdown = require("showdown");
const converter = new showdown.Converter({
parseImgDimensions: true,
headerLevelStart: 3,
extensions: ["prettify"]
});
module.exports = function () {
let folder = __dirname + "/../";
fs.watchFile(folder + "blog/posts.json", function (curr, prev) {
if (curr.mtime == prev.mtime)
return;
console.log("Refreshing blog sub-sites...");
fs.readFile(folder + "index.html", function (_, data) {
// set up the template
let templateDom = new JSDOM(data);
var templateDoc = templateDom.window.document;
templateDoc.getElementById("main").innerHTML = "";
let template = templateDom.serialize();
fs.readFile(folder + "blog/posts.json", function (_, data) {
let json = JSON.parse(data);
for (let post of json) {
let id = post["id"];
fs.readFile(folder + "blog/" + id + ".md", function (_, content) {
let dom = new JSDOM(template);
var document = dom.window.document;
document.title += " - " + post["name"];
document.querySelector('meta[property="og:title"]').setAttribute("content", post["name"]);
document.querySelector('meta[name="description"]').setAttribute("content", post["summary"]);
document.querySelector('meta[property="og:description"]').setAttribute("content", post["summary"]);
document.getElementById("nav-items").innerHTML = '<a class="nav-item nav-link" href="/#blog-' + id + '">Back to Main Page</a>'
var c = "";
c += '<div class="list-display rounded">';
c += '<div class="blog-isolated">'
c += '<h2 class="card-title">' + post["name"] + '</h2>';
c += '<div class="card-text" id="blog-post-' + id + '">'
c += converter.makeHtml(content.toString());
c += '</div>';
c += '<span class="text-muted project-status blog-isolated-status">' + post["date"] + "</span>";
var discussLink = post["discuss"];
if (discussLink)
c += '<a href="' + discussLink + '" class="blog-discuss" id="blog-discuss-' + id + '">Discuss this post</a>'
c += '</div></div>';
document.getElementById("main").innerHTML = c;
let html = dom.serialize();
fs.writeFile(folder + "blog-" + id + ".html", html, function (_, _) {});
});
}
});
});
});
}

View File

@ -1,2 +1,3 @@
require("./rss")();
require("./blog")();
require("./sitemap")();

View File

@ -41,7 +41,7 @@ module.exports = function () {
for (let post of json) {
sitemap.add({
url: "/#blog-" + post["id"],
url: "/blog-" + post["id"],
priority: 0.4
});
}

View File

@ -19,6 +19,7 @@ $.ajax({
p += '<div class="card bg-light blog-entry rounded-0">';
p += '<div class="card-body">';
p += '<a class="blog-button" id="blog-button-' + id + '"><h2 class="card-title">' + obj["name"] + '</h2></a>';
p += '<a class="reading-mode" href="/blog-' + id + '" id="reading-mode-' + id + '"></a>';
p += '<div class="card-text text-muted blog-summary" id="blog-summary-' + id + '">' + obj["summary"] + '</div>';
p += '<div class="card-text" id="blog-post-' + id + '"></div>';
p += '<span class="text-muted project-status">' + obj["date"] + "</span>";
@ -36,6 +37,7 @@ $.ajax({
if (discuss.length)
discuss.html("");
$("#blog-summary-" + id).show();
$("#reading-mode-" + id).html("");
history.pushState(null, null, "#blog");
} else {
openBlogPost(id);
@ -66,6 +68,7 @@ function openBlogPost(id, onDone) {
if (discuss.length)
discuss.html("Discuss this post");
$("#blog-summary-" + id).hide();
$("#reading-mode-" + id).html("Reading Mode");
PR.prettyPrint();
if (onDone)

View File

@ -1,8 +1,13 @@
html {
position: relative;
min-height: 100%;
}
body {
margin-top: 106px;
position: relative;
font-family: Roboto;
background-color: #404142;
margin-bottom: 100px;
}
.main {
@ -28,7 +33,8 @@ body {
}
.jumbotron {
margin-bottom: 0;
margin-bottom: 40px;
margin-top: 40px;
}
.project-image {
@ -98,11 +104,16 @@ body {
}
.footer {
position: absolute;
left: 0;
right: 0;
bottom: 0;
line-height: 30px;
background-color: #f5f5f5;
padding: 15px;
padding-left: 15px;
padding-right: 15px;
overflow: auto;
height: 60px;
line-height: 60px;
}
.impressum-data {
@ -138,6 +149,21 @@ body {
margin: auto;
}
.blog-isolated {
position: relative;
}
.blog-isolated-status {
bottom: 0 !important;
right: 0 !important;
}
.reading-mode {
position: absolute;
right: 20px;
top: 15px;
}
@media (min-width: 1200px) {
.navbar {
width: 1200px;
@ -162,6 +188,12 @@ body {
padding-left: 20px;
padding-right: 20px;
}
.reading-mode {
position: relative;
right: auto;
top: auto;
}
}
@media (max-width: 510px) {