[blog]: Add syntax highlighting, styling for all elements, mobile support

This commit is contained in:
Monty 2021-09-18 18:25:28 +02:00
parent 7f1f293f0d
commit f554a4c6a2
No known key found for this signature in database
GPG Key ID: 78B405B6520E1012
12 changed files with 458 additions and 91 deletions

137
blogposts/test.md Normal file
View File

@ -0,0 +1,137 @@
---
title: "Test"
author: "Monty"
author_image: "https://www.github.com/montylion.png"
date: "January 20, 2038"
caption: "A post to test the styling of the various elements we might use (rename to _test.md before deploying the blog section)"
cover_image: "https://media.discordapp.net/attachments/413884110667251722/886474243662037062/image1.jpg"
---
A post to test the styling of the various elements we might use (rename to _test.md before deploying the blog section)
**bold**
[**bold url**](https://www.youtube.com/watch?v=HGoCNOFpWpo)
_italic_
[_italic url_](https://www.youtube.com/watch?v=HGoCNOFpWpo)
~strikethrough~
[~strikethrough url~](https://www.youtube.com/watch?v=HGoCNOFpWpo)
# h1
## h2
### h3
#### h4
##### h5
###### h6
---
| Element | Description |
| :----------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| table | The table HTML element represents tabular data — that is, information presented in a two-dimensional table comprised of rows and columns of cells containing data. |
| tuble | The tuble HTML element represents tubular data — that is, information presented in a totally gnarly and radical way. |
| table | A table is an item of furniture with a flat top and one or more legs, used as a surface for working at, eating from or on which to place things. |
| Element | Description |
| ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| table | The table HTML element represents tabular data — that is, information presented in a two-dimensional table comprised of rows and columns of cells containing data. |
| tuble | The tuble HTML element represents tubular data — that is, information presented in a totally gnarly and radical way. |
| table | A table is an item of furniture with a flat top and one or more legs, used as a surface for working at, eating from or on which to place things. |
| Element | Description |
| -----------: | -----------------------------------------------------------------------------------------------------------------------------------------------------------------: |
| table | The table HTML element represents tabular data — that is, information presented in a two-dimensional table comprised of rows and columns of cells containing data. |
| tuble | The tuble HTML element represents tubular data — that is, information presented in a totally gnarly and radical way. |
| table | A table is an item of furniture with a flat top and one or more legs, used as a surface for working at, eating from or on which to place things. |
Yee haw 🤠
- list
- list
- list
- list
- list
69. list
1. list
1. list
1. list
1. list
- [ ] Unchecked checkbox
- [x] Checked checkbox
```js
class trueOrFalseObject {
constructor(trueOrFalse) {
this.trueOrFalse = trueOrFalse;
}
get trueOrFalse() {
return this.trueOrFalse();
}
trueOrFalse() {
return this.trueOrFalse;
}
}
let objectWhichWeKnowIsTrue = new trueOrFalseObject(true);
function checkIfTrueOrFalse(objectToCheckIfTrueOrFalse) {
if (objectToCheckIfTrueOrFalse === objectWhichWeKnowIsTrue.trueOrFalse) {
return objectWhichWeKnowIsTrue.trueOrFalse;
console.log(
"Successfully checked if the object is true or false. Result: the object is true."
);
// For whatever reason this doesn't log, can't figure out why /s
} else {
objectWhichWeKnowIsTrue = new trueOrFalseObject(false);
if (objectToCheckIfTrueOrFalse === objectWhichWeKnowIsTrue.trueOrFalse) {
return objectWhichWeKnowIsTrue.trueOrFalse;
console.log(
"Successfully checked if the object is true or false. Result: the object is false."
);
// For whatever reason this doesn't log either, will probably ask on StackOverflow or something /s
} else {
// something went horribly wrong
}
objectWhichWeKnowIsTrue = new trueOrFalseObject(true);
}
}
const isTrueTrueOrFalse = checkIfTrueOrFalse(true);
const isfalseTrueOrFalse = checkIfTrueOrFalse(false);
const trueOrFalseJSON = {
true: isTrueTrueOrFalse,
false: isfalseTrueOrFalse,
};
console.log(trueOrFalseJSON);
// Ok but seriously don't run this for the love of god I feel sorry for writing this even as a joke
```
> The blockquote HTML element indicates that the enclosed text is an extended quotation. Usually, this is rendered visually by indentation. A URL for the source of the quotation may be given using the cite attribute, while a text representation of the source can be given using the cite element.
> > The blockquote HTML element indicates that the enclosed text is an extended quotation. Usually, this is rendered visually by indentation. A URL for the source of the quotation may be given using the cite attribute, while a text representation of the source can be given using the cite element.
> > > The blockquote HTML element indicates that the enclosed text is an extended quotation. Usually, this is rendered visually by indentation. A URL for the source of the quotation may be given using the cite attribute, while a text representation of the source can be given using the cite element.
<cite>Adapted from [blockquote: The Block Quotation element, from MDN Web Docs](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/blockquote)</cite>
<iframe src="https://www.youtube.com/embed/HGoCNOFpWpo" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
![test](https://media.discordapp.net/attachments/413884110667251722/886474243662037062/image1.jpg)
<video controls>
<source src="https://cdn.discordapp.com/attachments/413884110667251722/878216238940160040/video0.mov">
</video>
Blogposts whose filename starts with a \_ will not show up on the /blogs page, but will still be accessible from the url (keep in mind that the file is still going to be publicly accessible on GitHub).

View File

@ -2,14 +2,13 @@
title: "Todo"
author: "Monty"
author_image: "https://www.github.com/montylion.png"
date: "19 January 2038"
caption: "A todo list"
date: "January 19, 2038"
caption: "A todo list (delete file when done)"
cover_image: "https://i.imgur.com/sOWLwO5.png"
---
- <input type="checkbox" onclick="return false;">
Redesign by the one true design god jvs, then
- <input type="checkbox" onclick="return false;">
Add mobile support
- <input type="checkbox" onclick="return false;">
Add custom opengraph for each post
A todo list (delete file when done)
- [ ] Redesign by the one true design god jvs
- [x] Add mobile support
- [x] Add css styling for all elements supported by markdown
- [ ] Fix navbar

View File

@ -3,7 +3,8 @@
"about": "About",
"faq": "FAQ",
"credits": "Credits",
"progress": "Progress"
"progress": "Progress",
"blog": "Blog"
},
"hero": {
"subtitle": "Game servers",

View File

@ -1,61 +1,51 @@
.blog-card {
display: flex;
flex-flow: row nowrap;
padding: 0;
margin: 0 auto;
max-width: 1100px;
margin-top: 30px;
margin-bottom: 30px;
text-decoration: none;
display: flex;
flex-flow: row nowrap;
position: relative;
border-radius: 10px;
overflow: hidden;
}
.blog-card .left {
flex: 2 0 55%;
.blog-card .post-info {
flex: 2 0 45%;
padding: 40px;
}
.blog-card .right {
display: flex;
border-radius: 0 10px 10px 0;
height: 260px;
width: 45%;
}
.blog-card .right img {
width: 100%;
height: 100%;
object-fit: cover;
border-radius: 0 10px 10px 0;
}
.blog-card h2 {
color: white;
margin-top: 0;
}
.blog-card p, .post-info {
flex-flow: column;
color: var(--text-secondary);
}
.blog-card .date {
margin-bottom: 0;
font-weight: bold;
color: var(--text);
.blog-card .post-info .title {
color: white;
margin: 0;
}
.blog-card img {
border-radius: 4px;
.blog-card .post-info .caption {
margin: 4px 0 32px 0;
}
.blog-card .post-info {
.blog-card .pub-info {
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: left;
position: absolute;
bottom: 40px;
margin-top: auto;
}
.blog-card .post-info > * + * {
margin-left: .5em;
.blog-card .pub-info .date {
font-weight: bold;
color: var(--text);
}
.blog-card .pub-info > * {
margin-right: .5em;
margin-top: .2em;
}
.blog-card .profile {
display: inline-grid;
grid-template-columns: 30px auto;
@ -63,9 +53,44 @@
font-weight: bold;
color: var(--text);
align-items: center;
height: 32px; /* So the post doesn't shift when the image gets loaded */
height: 32px;
}
.blog-card .profile img {
border-radius: 4px;
border: 1px solid rgba(255, 255, 255, 0.1);
max-width: 100%;
}
.blog-card .cover {
flex: 45%;
}
@media screen and (max-width: 600px) {
.blog-card {
flex-flow: column;
}
.blog-card .post-info {
padding: 30px;
}
.blog-card .cover {
order: -1;
min-height: 200px;
}
}
@media screen and (max-width: 400px) {
.blog-card {
max-width: none;
border-radius: 0;
}
.wrapper {
width: 100%;
}
header {
width: 90%;
margin: 35px auto;
}
}

View File

@ -1,58 +1,160 @@
.blog-card {
padding: 60px;
margin: 0 auto;
max-width: 1100px;
margin-top: 50px;
padding: 60px;
margin: 0 auto;
max-width: 1100px;
margin-top: 50px;
color: var(--text-secondary);
}
.blog-card h1,
.blog-card h2,
.blog-card h3,
.blog-card h4,
.blog-card h5,
.blog-card h6,
.blog-card strong,
.blog-card a,
.blog-card a * {
color: white;
}
.blog-card .title {
margin: 0;
margin: 0;
}
.blog-card p, .post-info {
color: var(--text-secondary);
margin-bottom: 30px;
.blog-card p,
.post-info {
color: var(--text-secondary);
margin-bottom: 30px;
}
.blog a {
color: var(--text-secondary);
color: var(--text-secondary);
}
.blog-card .date {
margin-bottom: 0;
font-weight: bold;
color: var(--text);
}
.blog-card iframe {
width: 100%;
aspect-ratio: 16/9;
border-radius: 4px;
border: 1px solid rgba(255, 255, 255, 0.1);
margin-bottom: 0;
font-weight: bold;
color: var(--text);
}
.blog-card img {
max-width: 100%;
margin: 10px auto;
display: block;
max-width: 100%;
max-height: 800px;
margin: 10px auto;
display: block;
border-radius: 4px;
border: 1px solid rgba(255, 255, 255, 0.1);
}
.blog-card img.emoji {
display: inline;
margin: 0;
border: none;
}
.blog-card video {
width: 100%;
border-radius: 4px;
border: 1px solid rgba(255, 255, 255, 0.1);
}
.blog-card iframe {
width: 100%;
aspect-ratio: 16/9;
border-radius: 4px;
border: 1px solid rgba(255, 255, 255, 0.1);
}
.blog-card table {
border-radius: 4px;
border-collapse: collapse;
background: #31375E;
margin-bottom: 30px;
overflow: hidden;
color: var(--text-secondary);
}
.blog-card table th {
padding: 8px 12px;
background: #3F4778;
color: white;
}
.blog-card table td {
padding: 8px 12px;
vertical-align: top;
border-radius: inherit;
}
.blog-card table tr:nth-child(even) {
background: #2A2F50;
}
.blog-card pre code {
border-radius: 4px;
margin-bottom: 30px;
}
.blog-card input[type="checkbox"] {
appearance: none;
-webkit-appearance: none;
display: inline-block;
background: var(--btn-secondary);
padding: 12px;
margin: 4px;
border-radius: 4px;
border: 1px solid rgba(255, 255, 255, 0.1);
vertical-align: -60%;
}
.blog-card input[type="checkbox"]:checked {
content: 'checkboxtest';
background: no-repeat center/contain url(../images/check.svg), var(--btn-secondary);
}
.blog-card hr {
border: 1px solid var(--text-secondary);
margin: 30px 0;
}
.blog-card blockquote {
border-left: 2px solid var(--text-secondary);
padding: 8px 24px;
margin: 0;
margin-bottom: 30px;
}
.blog-card .post-info {
display: flex;
flex-wrap: wrap;
align-items: center;
display: flex;
flex-wrap: wrap;
align-items: center;
}
.blog-card .post-info > * + * {
margin-left: .5em;
margin-left: 0.5em;
}
.blog-card .profile {
display: inline-grid;
grid-template-columns: 30px auto;
grid-gap: 10px;
font-weight: bold;
color: var(--text);
align-items: center;
height: 52px; /* So the post doesn't shift when the image gets loaded */
display: inline-grid;
grid-template-columns: 30px auto;
grid-gap: 10px;
font-weight: bold;
color: var(--text);
align-items: center;
height: 52px;
}
footer {
margin-top: 80px;
@media screen and (max-width: 800px) {
.blog-card {
padding: 60px;
margin: 0;
max-width: none;
border-radius: 0;
}
.wrapper {
width: 100%;
}
header {
width: 90%;
margin: 35px auto;
}
}
@media screen and (max-width: 600px) {
.blog-card {
padding: 40px 5vw;
}
}

View File

@ -0,0 +1,91 @@
/**
* Adapted from Shades of Purple Theme for Highlightjs.
*
* @author (c) Ahmad Awais <https://twitter.com/mrahmadawais/>
* @link GitHub Repo https://github.com/ahmadawais/Shades-of-Purple-HighlightJS
* @version 1.5.0
*/
.hljs {
background: var(--btn-secondary);
color: #e3dfff;
font-weight: normal;
}
.hljs-subst {
color: #e3dfff;
}
.hljs-title {
color: #fad000;
font-weight: normal;
}
.hljs-name {
color: #a1feff;
}
.hljs-tag {
color: #ffffff;
}
.hljs-attr {
color: #f8d000;
font-style: italic;
}
.hljs-built_in,
.hljs-selector-tag,
.hljs-section {
color: #fb9e00;
}
.hljs-keyword {
color: #fb9e00;
}
.hljs-string,
.hljs-attribute,
.hljs-symbol,
.hljs-bullet,
.hljs-addition,
.hljs-code,
.hljs-regexp,
.hljs-selector-class,
.hljs-selector-attr,
.hljs-selector-pseudo,
.hljs-template-tag,
.hljs-quote,
.hljs-deletion {
color: #4cd213;
}
.hljs-meta,
.hljs-meta .hljs-string {
color: #fb9e00;
}
.hljs-comment {
color: #ac65ff;
}
.hljs-keyword,
.hljs-selector-tag,
.hljs-literal,
.hljs-name,
.hljs-strong {
font-weight: normal;
}
.hljs-literal,
.hljs-number {
color: #fa658d;
}
.hljs-emphasis {
font-style: italic;
}
.hljs-strong {
font-weight: bold;
}

View File

@ -659,7 +659,7 @@ footer {
}
@media screen and (max-width: 500px) {
@media screen and (max-width: 550px) {
.selected-locale .locale-names {
display: none;
}
@ -670,6 +670,10 @@ footer {
margin-right: 12px;
}
.locale-dropdown {
width: fit-content;
}
}
@media screen and (max-width: 400px) {

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#fff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-check"><polyline points="20 6 9 17 4 12"></polyline></svg>

After

Width:  |  Height:  |  Size: 254 B

View File

@ -20,6 +20,7 @@ router.get('/', async (request, response) => {
// We get the info for each blogpost, ignoring the ones starting with _
const postList = fileList
.filter(filename => !filename.startsWith('_'))
.filter(filename => filename.endsWith('.md')) //Ignores other files/folders
.map((filename) => {
const slug = filename.replace('.md', '');
const rawPost = fs.readFileSync(path.join('blogposts', `${filename}`), 'utf-8');
@ -28,6 +29,7 @@ router.get('/', async (request, response) => {
slug, postInfo
};
});
postList.sort((a, b) => {
return new Date(b.postInfo.date) - new Date(a.postInfo.date);
});

View File

@ -14,10 +14,10 @@
{{#each postList }}
<a href="/blog/{{this.slug}}" class="purple-card blog-card">
<div class="left">
<h2>{{{ this.postInfo.title }}}</h2>
<p>{{{ this.postInfo.caption }}}</p>
<div class="post-info">
<div class="post-info">
<h2 class="title">{{{ this.postInfo.title }}}</h2>
<p class="caption">{{{ this.postInfo.caption }}}</p>
<div class="pub-info">
<span>Published by</span>
<div class="profile">
<img class="profile-picture" src="{{{ this.postInfo.author_image }}}" alt>
@ -27,8 +27,7 @@
<span class="date">{{{ this.postInfo.date }}}</span>
</div>
</div>
<div class="right">
<img src="{{this.postInfo.cover_image}}" class="cover" />
<div class="cover" style="background: no-repeat center/cover url({{this.postInfo.cover_image}}">
</div>
</a>
{{/each}}

View File

@ -23,4 +23,9 @@
{{> footer }}
</div>
</div>
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/11.2.0/styles/default.min.css">
<link rel="stylesheet" href="/assets/css/highlightjs.css">
<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/11.2.0/highlight.min.js"></script>
<script>hljs.highlightAll();</script>

View File

@ -29,6 +29,7 @@
<a href="/#faq">{{ locale.nav.faq }}</a>
<a href="/#credits">{{ locale.nav.credits }}</a>
<a href="/progress" class="keep-on-mobile">{{ locale.nav.progress }}</a>
<a href="/blog" class="keep-on-mobile">{{ locale.nav.blog }}</a>
</nav>
<!-- Ordered the locales in the same way YouTube's language selector orders them -->