Merge pull request #397 from PretendoNetwork/nuxt-refactor-blog
Nuxt refactor blog
17
content.config.ts
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
import { defineContentConfig, defineCollection, z } from '@nuxt/content';
|
||||
|
||||
export default defineContentConfig({
|
||||
collections: {
|
||||
blog: defineCollection({
|
||||
type: 'page',
|
||||
source: 'blog/*.md',
|
||||
schema: z.object({
|
||||
author: z.string(),
|
||||
author_image: z.string(),
|
||||
date: z.string(),
|
||||
caption: z.string(),
|
||||
cover_image: z.string()
|
||||
})
|
||||
})
|
||||
}
|
||||
});
|
||||
|
|
@ -83,7 +83,8 @@ In the latest version of the Cemu 2.0 experimental builds, support for Pretendo
|
|||
|
||||
If you haven't yet seen this video by Good Vibes Gaming, go check it out! I won't go anywhere...
|
||||
|
||||
[yt-iframe](Xtc9DJ6LYas)
|
||||
::md-iframe{video-id="Xtc9DJ6LYas"}
|
||||
::
|
||||
|
||||
All done? Welcome back! Yes, you aren't dreaming - Wii U Chat is finally here! The journey leading up to this point has been an adventurous one, so grab your popcorn as we go back to the beginning.
|
||||
|
||||
|
|
@ -33,19 +33,22 @@ Both Mario Kart 7 and Mario Kart 8 have started going online and can play matche
|
|||
|
||||

|
||||
|
||||
[yt-iframe](W974FEDIoAA)
|
||||
::md-iframe{video-id="W974FEDIoAA"}
|
||||
::
|
||||
|
||||
## Hello YouTube!
|
||||
|
||||
An unintended side effect of working on Miiverse support in Mario Kart 8 was YouTube uploading being re-enabled! You can now upload race clips from Mario Kart 8 to YouTube again. Patrons who run the Miiverse patch can try this feature out right now
|
||||
|
||||
[yt-iframe](d3Bq7auupV0)
|
||||
::md-iframe{video-id="d3Bq7auupV0"}
|
||||
::
|
||||
|
||||
## Squid Game
|
||||
|
||||
Splatoon multiplayer battles now works! As of now only private friend battles have been tested, but they seem to be working without issue
|
||||
|
||||
[yt-iframe](d_qFnXrP7a4)
|
||||
::md-iframe{video-id="d_qFnXrP7a4"}
|
||||
::
|
||||
|
||||
## Friendship is magic
|
||||
|
||||
|
|
@ -32,7 +32,8 @@ Juxt started out before I actually even joined the Pretendo Network development
|
|||
|
||||
From there we quickly realized that the scope of this project was going to be much larger than we though, and moved on to experimenting with the Miiverse Applet itself
|
||||
|
||||
[yt-iframe](d9VAr9sEvCo)
|
||||
::md-iframe{video-id="d9VAr9sEvCo"}
|
||||
::
|
||||
|
||||
> Check out this ancient video of the first demo website that was running in the Miiverse Applet.
|
||||
|
||||
|
|
@ -40,11 +41,13 @@ Shortly after this the project was absorbed into the Pretendo Network, and our f
|
|||
|
||||
2020 was a big year for Juxt, going from the simple api server before, to rapidly building out its web interface and features across both the 3DS and Wii u
|
||||
|
||||
[yt-iframe](NrfaOx5xcJY)
|
||||
::md-iframe{video-id="NrfaOx5xcJY"}
|
||||
::
|
||||
|
||||
> First attempt at an interface for the 3DS
|
||||
|
||||
[yt-iframe](IXnJOacx_gE)
|
||||
::md-iframe{video-id="IXnJOacx_gE"}
|
||||
::
|
||||
|
||||
> Community page Demo on the Wii U
|
||||
|
||||
|
|
@ -1,13 +1,13 @@
|
|||
---
|
||||
title: "Test"
|
||||
author: "pinklimes"
|
||||
author_image: "https://github.com/pinklimes.png"
|
||||
author: "limes.pink"
|
||||
author_image: "https://github.com/gitlimes.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)"
|
||||
caption: "A post to test the styling of the various elements we might use"
|
||||
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)
|
||||
A post to test the styling of the various elements we might use
|
||||
|
||||
**bold**
|
||||
|
||||
|
|
@ -126,14 +126,22 @@ console.log(trueOrFalseJSON);
|
|||
|
||||
<cite>Adapted from [blockquote: The Block Quotation element, from MDN Web Docs](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/blockquote)</cite>
|
||||
|
||||
[yt-iframe](djV11Xbc914)
|
||||
::md-iframe{video-id="djV11Xbc914"}
|
||||
::
|
||||
|
||||
```[yt-iframe](djV11Xbc914)```
|
||||
```
|
||||
::md-iframe{video-id="djV11Xbc914"}
|
||||
::
|
||||
```
|
||||
|
||||

|
||||

|
||||
|
||||
<a href="https://commons.wikimedia.org/wiki/File:View_of_the_Turin_Metro_tracks_from_Fermi_terminal.jpg">Wikilimes</a> (that's me!), <a href="https://creativecommons.org/licenses/by-sa/4.0">CC BY-SA 4.0</a>, via Wikimedia Commons
|
||||
|
||||
***
|
||||
|
||||
<video controls>
|
||||
<source src="https://cdn.discordapp.com/attachments/413884110667251722/878216238940160040/video0.mov">
|
||||
<source src="https://upload.wikimedia.org/wikipedia/commons/transcoded/5/5f/Steamboat_Willie_%281928%29_by_Walt_Disney.webm/Steamboat_Willie_%281928%29_by_Walt_Disney.webm.720p.vp9.webm">
|
||||
</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).
|
||||
Blogposts with filename starting with \_ will not show up on the /blogs page, but will still be accessible via the url.
|
||||
|
|
@ -3,6 +3,12 @@ export default defineNuxtConfig({
|
|||
devtools: { enabled: true },
|
||||
srcDir: './src',
|
||||
|
||||
nitro: {
|
||||
prerender: {
|
||||
routes: ['/blog/feed.xml']
|
||||
}
|
||||
},
|
||||
|
||||
modules: [
|
||||
'@nuxt/eslint',
|
||||
'@nuxt/fonts',
|
||||
|
|
@ -26,6 +32,16 @@ export default defineNuxtConfig({
|
|||
}
|
||||
},
|
||||
|
||||
content: {
|
||||
build: {
|
||||
markdown: {
|
||||
highlight: {
|
||||
theme: 'github-dark'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
i18n: {
|
||||
compilation: {
|
||||
strictMessage: false
|
||||
|
|
|
|||
31
package-lock.json
generated
|
|
@ -15,6 +15,7 @@
|
|||
"@nuxt/icon": "^1.11.0",
|
||||
"@nuxtjs/i18n": "^9.5.3",
|
||||
"eslint": "^9.24.0",
|
||||
"feed": "^4.2.2",
|
||||
"nuxt": "^3.16.2",
|
||||
"vue": "^3.5.13",
|
||||
"vue-router": "^4.5.0"
|
||||
|
|
@ -7642,6 +7643,18 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"node_modules/feed": {
|
||||
"version": "4.2.2",
|
||||
"resolved": "https://registry.npmjs.org/feed/-/feed-4.2.2.tgz",
|
||||
"integrity": "sha512-u5/sxGfiMfZNtJ3OvQpXcvotFpYkL0n9u9mM2vkui2nGo8b4wvDkJ8gAkYqbA8QpGyFCv3RK0Z+Iv+9veCS9bQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"xml-js": "^1.6.11"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/file-entry-cache": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
|
||||
|
|
@ -13507,6 +13520,12 @@
|
|||
"url": "https://github.com/chalk/supports-color?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/sax": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz",
|
||||
"integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/scslre": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/scslre/-/scslre-0.3.0.tgz",
|
||||
|
|
@ -16167,6 +16186,18 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"node_modules/xml-js": {
|
||||
"version": "1.6.11",
|
||||
"resolved": "https://registry.npmjs.org/xml-js/-/xml-js-1.6.11.tgz",
|
||||
"integrity": "sha512-7rVi2KMfwfWFl+GpPg6m80IVMWXLRjO+PxTq7V2CDhoGak0wzYzFgUY2m4XJ47OGdXd8eLE8EmwfAmdjw7lC1g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"sax": "^1.2.4"
|
||||
},
|
||||
"bin": {
|
||||
"xml-js": "bin/cli.js"
|
||||
}
|
||||
},
|
||||
"node_modules/xml-name-validator": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz",
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
"@nuxt/icon": "^1.11.0",
|
||||
"@nuxtjs/i18n": "^9.5.3",
|
||||
"eslint": "^9.24.0",
|
||||
"feed": "^4.2.2",
|
||||
"nuxt": "^3.16.2",
|
||||
"vue": "^3.5.13",
|
||||
"vue-router": "^4.5.0"
|
||||
|
|
|
|||
|
|
@ -50,7 +50,8 @@ body,
|
|||
}
|
||||
|
||||
code {
|
||||
background-color: var(--bg-shade-0);
|
||||
display: inline-block;
|
||||
background-color: #191919;
|
||||
padding: 4px;
|
||||
border-radius: 4px;
|
||||
font-family: Consolas, Monaco, "Andale Mono", monospace;
|
||||
|
|
@ -58,6 +59,20 @@ code {
|
|||
color: var(--text-shade-2);
|
||||
}
|
||||
|
||||
h1.dot:not([data-title-suffix]):after,
|
||||
h2.dot:not([data-title-suffix]):after {
|
||||
content: ".";
|
||||
display: inline-block;
|
||||
color: var(--accent-shade-1);
|
||||
}
|
||||
|
||||
h1.dot[data-title-suffix]:after,
|
||||
h2.dot[data-title-suffix]:after {
|
||||
content: attr(data-title-suffix);
|
||||
display: inline-block;
|
||||
color: var(--accent-shade-1);
|
||||
}
|
||||
|
||||
/* BUTTONS */
|
||||
|
||||
button,
|
||||
|
|
@ -186,7 +201,7 @@ input[type="checkbox"] {
|
|||
cursor: pointer;
|
||||
}
|
||||
input[type="checkbox"]:checked {
|
||||
background: no-repeat center/contain url(../images/check.svg), var(--accent-shade-0);
|
||||
background: no-repeat center/contain url(/assets/images/check.svg), var(--accent-shade-0);
|
||||
}
|
||||
|
||||
input {
|
||||
|
|
|
|||
18
src/components/MdIframe/MdIframe.vue
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
<script lang="ts" setup>
|
||||
const props = defineProps<{
|
||||
videoId: string;
|
||||
}>();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<iframe
|
||||
width="560"
|
||||
height="315"
|
||||
:src="`https://www.youtube-nocookie.com/embed/${props.videoId}`"
|
||||
title="YouTube video player"
|
||||
frameborder="0"
|
||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
|
||||
referrerpolicy="strict-origin-when-cross-origin"
|
||||
allowfullscreen
|
||||
/>
|
||||
</template>
|
||||
313
src/pages/blog/[slug].vue
Normal file
|
|
@ -0,0 +1,313 @@
|
|||
<script setup>
|
||||
const slug = useRoute().params.slug;
|
||||
const { data: post } = await useAsyncData(`blog-${slug}`, () => {
|
||||
return queryCollection('blog').path(`/blog/${slug}`).first();
|
||||
});
|
||||
|
||||
if (!post.value) {
|
||||
throw createError({ statusCode: 404, statusMessage: 'Page Not Found' });
|
||||
}
|
||||
|
||||
useHead({
|
||||
title: `${post.value.title} | Pretendo Network Blog`,
|
||||
meta: [
|
||||
{ property: 'description', content: post.value.caption },
|
||||
{ property: 'og:title', content: `${post.value.title} | Pretendo Network Blog` },
|
||||
{ property: 'og:description', content: post.value.caption },
|
||||
{ property: 'og:type', content: 'website' },
|
||||
{ property: 'og:url', content: 'https://pretendo.network/' },
|
||||
{ property: 'og:image', content: post.value.cover_image },
|
||||
{ property: 'og:image:alt', content: 'Pretendo Network' },
|
||||
{ property: 'og:site_name', content: 'Pretendo Network' },
|
||||
{ name: 'twitter:url', content: 'https://pretendo.network/' },
|
||||
{ name: 'twitter:card', content: 'summary_large_image' },
|
||||
{ name: 'twitter:site', content: '@PretendoNetwork' },
|
||||
{ name: 'twitter:title', content: `${post.value.title} | Pretendo Network Blog` },
|
||||
{ name: 'twitter:description', content: post.value.caption },
|
||||
{ name: 'twitter:image', content: post.value.cover_image }
|
||||
]
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="card-wrap">
|
||||
<div class="blog-card">
|
||||
<h1 class="title">
|
||||
{{ post.title }}
|
||||
</h1>
|
||||
|
||||
<div class="pub-info">
|
||||
<span>{{ $t('blogPage.published') }}</span>
|
||||
<div class="profile">
|
||||
<img
|
||||
class="profile-picture"
|
||||
:src="post.author_image"
|
||||
alt=""
|
||||
>
|
||||
<span>{{ post.author }}</span>
|
||||
</div>
|
||||
<span>{{ $t('blogPage.publishedOn') }}
|
||||
<span class="date">{{ post.date }}</span>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<ContentRenderer :value="post" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.card-wrap {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-flow: column nowrap;
|
||||
align-items: center;
|
||||
margin: 8rem 0;
|
||||
}
|
||||
|
||||
.blog-card {
|
||||
padding: 60px;
|
||||
border-radius: 10px;
|
||||
background: var(--bg-shade-0);
|
||||
max-width: 1100px;
|
||||
color: var(--text-shade-1);
|
||||
}
|
||||
|
||||
.blog-card :deep(h1),
|
||||
.blog-card :deep(h2),
|
||||
.blog-card :deep(h3),
|
||||
.blog-card :deep(h4),
|
||||
.blog-card :deep(h5),
|
||||
.blog-card :deep(h6) {
|
||||
margin: 40px 0 10px;
|
||||
color: var(--text-shade-3) !important;
|
||||
}
|
||||
|
||||
.blog-card :deep(strong) {
|
||||
color: var(--text-shade-3);
|
||||
}
|
||||
|
||||
.blog-card :deep(a), .blog-card :deep(a) * {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.blog-card :deep(a:hover), .blog-card :deep(a:hover) * {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.blog-card :deep(*:not(h1, h2, h3, h4, h5, h6) > a),
|
||||
.blog-card :deep(*:not(h1, h2, h3, h4, h5, h6) > a) * {
|
||||
color: var(--accent-shade-1);
|
||||
text-decoration: none;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.blog-card :deep(*:not(h1, h2, h3, h4, h5, h6) > a):hover,
|
||||
.blog-card :deep(*:not(h1, h2, h3, h4, h5, h6) > a):hover * {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.blog-card .title {
|
||||
margin: 0;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.blog-card .pub-info {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
justify-content: left;
|
||||
margin-top: auto;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.blog-card .pub-info .date {
|
||||
font-weight: bold;
|
||||
color: var(--text-shade-3);
|
||||
}
|
||||
|
||||
.blog-card .pub-info>* {
|
||||
margin-right: 0.5em;
|
||||
margin-top: 0.2em;
|
||||
}
|
||||
|
||||
.blog-card .profile {
|
||||
display: inline-grid;
|
||||
grid-template-columns: 30px auto;
|
||||
grid-gap: 10px;
|
||||
font-weight: bold;
|
||||
color: var(--text-shade-3);
|
||||
align-items: center;
|
||||
height: 32px;
|
||||
margin-right: 0.3em;
|
||||
}
|
||||
|
||||
.blog-card .profile img {
|
||||
margin: 0;
|
||||
border-radius: 4px;
|
||||
border: 1px solid var(--border);
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.blog-card p,
|
||||
.post-info {
|
||||
color: var(--text-shade-1);
|
||||
}
|
||||
|
||||
.blog-card :deep(img) {
|
||||
max-width: 100%;
|
||||
max-height: 800px;
|
||||
margin: 10px auto;
|
||||
display: block;
|
||||
border-radius: 4px;
|
||||
border: 1px solid var(--border);
|
||||
}
|
||||
|
||||
.blog-card img.emoji {
|
||||
display: inline;
|
||||
margin: 0;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.blog-card :deep(video) {
|
||||
width: 100%;
|
||||
border-radius: 4px;
|
||||
border: 1px solid var(--border);
|
||||
}
|
||||
|
||||
.blog-card :deep(iframe) {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
aspect-ratio: 16/9;
|
||||
border-radius: 4px;
|
||||
border: 1px solid var(--border);
|
||||
}
|
||||
|
||||
/* Some twitter iframe specific stuff */
|
||||
.blog-card .twitter-tweet {
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.blog-card .twitter-tweet iframe {
|
||||
border: none;
|
||||
/* Fixes the double border */
|
||||
}
|
||||
|
||||
.blog-card :deep(table) {
|
||||
border-radius: 4px;
|
||||
border-collapse: collapse;
|
||||
background: var(--bg-shade-3);
|
||||
margin-bottom: 30px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.blog-card :deep(table) th {
|
||||
padding: 8px 12px;
|
||||
background: var(--bg-shade-4);
|
||||
color: var(--text-shade-3);
|
||||
}
|
||||
|
||||
.blog-card :deep(table) td {
|
||||
padding: 8px 12px;
|
||||
vertical-align: top;
|
||||
border-radius: inherit;
|
||||
}
|
||||
|
||||
.blog-card :deep(table) tr:nth-child(even) {
|
||||
background: var(--bg-shade-2);
|
||||
}
|
||||
|
||||
.blog-card :deep(pre code) {
|
||||
border-radius: 4px;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.blog-card :deep(input[type="checkbox"]) {
|
||||
appearance: none;
|
||||
-webkit-appearance: none;
|
||||
display: inline-block;
|
||||
background: var(--bg-shade-3);
|
||||
padding: 12px;
|
||||
margin: 4px;
|
||||
border-radius: 4px;
|
||||
vertical-align: -60%;
|
||||
}
|
||||
|
||||
.blog-card :deep(input[type="checkbox"]):checked {
|
||||
content: "checkboxtest";
|
||||
background: no-repeat center/contain url(/assets/images/check.svg),
|
||||
var(--accent-shade-0);
|
||||
}
|
||||
|
||||
.blog-card :deep(hr) {
|
||||
border: 1px solid var(--text-shade-1);
|
||||
margin: 30px 0;
|
||||
}
|
||||
|
||||
.blog-card :deep(blockquote) {
|
||||
border-left: 2px solid var(--text-shade-1);
|
||||
padding: 8px 24px;
|
||||
margin: 0;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.blog-card :deep(del) {
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
.blog-card :deep(a > del) {
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
.blog-card :deep(a:hover > del) {
|
||||
text-decoration: line-through underline;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss">
|
||||
@media screen and (min-width: 901px) {
|
||||
#root {
|
||||
.blog-card :deep(h1),
|
||||
.blog-card :deep(h2),
|
||||
.blog-card :deep(h3),
|
||||
.blog-card :deep(h4),
|
||||
.blog-card :deep(h5),
|
||||
.blog-card :deep(h6) {
|
||||
scroll-margin-top: 110px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 800px) {
|
||||
#root {
|
||||
.blog-card {
|
||||
padding: 40px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 600px) {
|
||||
#root {
|
||||
.wrapper {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
header {
|
||||
width: 90%;
|
||||
margin: 35px auto;
|
||||
}
|
||||
|
||||
.blog-card {
|
||||
padding: 40px 5vw;
|
||||
border-radius: 0;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
footer {
|
||||
width: 95%;
|
||||
margin: auto auto 40px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
270
src/pages/blog/index.vue
Normal file
|
|
@ -0,0 +1,270 @@
|
|||
<script setup lang="ts">
|
||||
/* eslint-disable vue/no-v-html -- we might wanna avoid this by rewriting the locales to use variables */
|
||||
const { data: allPosts } = await useAsyncData('blog', () => queryCollection('blog').all());
|
||||
|
||||
const posts = computed(() => allPosts.value?.filter(p => !p.path.startsWith('/blog/_')).sort((a, b) => {
|
||||
return new Date(b.date).getTime() - new Date(a.date).getTime();
|
||||
}));
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="blog">
|
||||
<div class="progress-hero">
|
||||
<div class="hero-meta reduced-margin">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="48.87"
|
||||
height="71.093"
|
||||
viewBox="0 0 48.87 71.093"
|
||||
>
|
||||
<g
|
||||
id="XMLID_6_"
|
||||
transform="translate(0)"
|
||||
>
|
||||
<path
|
||||
id="XMLID_15_"
|
||||
d="M69.581,29.593c-2.029,1.068-.249,4.129,1.78,3.061,5.162-2.67,11.463-2.6,16.981-1.1,4.735,1.282,9.5,3.845,12.246,8.045,1.246,1.922,4.307.142,3.061-1.78C96.921,27.386,80.3,24.04,69.581,29.593Z"
|
||||
transform="translate(-60.112 -20.086)"
|
||||
fill="#9d6ff3"
|
||||
/>
|
||||
<path
|
||||
id="XMLID_14_"
|
||||
d="M103.359,21.045c-3.951-6.159-10.751-10-17.657-11.89C77.763,6.948,68.721,7.019,61.281,10.9c-2.029,1.068-.249,4.129,1.78,3.061,6.586-3.453,14.667-3.311,21.644-1.388,5.981,1.638,12.1,4.913,15.521,10.252C101.507,24.783,104.569,23,103.359,21.045Z"
|
||||
transform="translate(-54.766 -7.693)"
|
||||
fill="#9d6ff3"
|
||||
/>
|
||||
<path
|
||||
id="XMLID_9_"
|
||||
d="M65.995,47.8a20.7,20.7,0,0,0-12.958,4.45H47.27a2.579,2.579,0,0,0-2.67,2.456v47.239a2.763,2.763,0,0,0,2.67,2.67h5.838a2.639,2.639,0,0,0,2.528-2.67V87.564A21.228,21.228,0,1,0,65.995,47.8Zm0,33.178a12,12,0,1,1,12-12A12,12,0,0,1,65.995,80.978Z"
|
||||
transform="translate(-44.6 -33.522)"
|
||||
fill="#9d6ff3"
|
||||
/>
|
||||
</g>
|
||||
</svg>
|
||||
<h1 class="title dot">
|
||||
{{ $t('blogPage.title') }}
|
||||
</h1>
|
||||
<p
|
||||
class="text"
|
||||
v-html="$t('blogPage.description')"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<a
|
||||
v-for="post in posts"
|
||||
:key="post.id"
|
||||
:href="post.path"
|
||||
class="purple-card blog-card"
|
||||
>
|
||||
<div class="post-info">
|
||||
<h2 class="title">{{ post.title }}</h2>
|
||||
<p class="caption">{{ post.caption }}</p>
|
||||
<div class="pub-info">
|
||||
<span>{{ $t('blogPage.published') }}</span>
|
||||
<div class="profile">
|
||||
<img
|
||||
class="profile-picture"
|
||||
:src="post.author_image"
|
||||
alt=""
|
||||
>
|
||||
<span>{{ post.author }}</span>
|
||||
</div>
|
||||
<span>{{ $t('blogPage.publishedOn') }}
|
||||
<span class="date">{{ post.date }}</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="cover"
|
||||
:style="{ 'background': `no-repeat center/cover url(${post.cover_image})` }"
|
||||
/>
|
||||
</a>
|
||||
|
||||
<div class="buttons">
|
||||
<!-- TODO: implement pagination -->
|
||||
<a
|
||||
href="/blog/feed.xml"
|
||||
target="_blank"
|
||||
title="RSS feed"
|
||||
>
|
||||
<button class="button secondary icon-btn">
|
||||
<Icon
|
||||
name="ph:rss"
|
||||
size="36"
|
||||
/>
|
||||
</button>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.progress-hero {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-items: center;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
}
|
||||
.progress-hero svg {
|
||||
width: 3rem;
|
||||
height: 3rem;
|
||||
}
|
||||
.progress-hero .text {
|
||||
max-width: 423px;
|
||||
color: var(--text-shade-1);
|
||||
line-height: 1.8;
|
||||
}
|
||||
.progress-hero .text :deep(a) {
|
||||
color: var(--accent-shade-1);
|
||||
text-decoration: none;
|
||||
font-weight: bold;
|
||||
}
|
||||
.progress-hero .text :deep(a):hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.hero-meta.reduced-margin {
|
||||
margin: 10vh 0;
|
||||
width: 100%;
|
||||
}
|
||||
.hero-meta.reduced-margin h1 {
|
||||
width: 100%;
|
||||
}
|
||||
.hero-meta.reduced-margin p {
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.blog-card {
|
||||
display: flex;
|
||||
flex-flow: row nowrap;
|
||||
padding: 0;
|
||||
margin: 0 auto;
|
||||
max-width: 1000px;
|
||||
margin-bottom: 30px;
|
||||
text-decoration: none;
|
||||
position: relative;
|
||||
border-radius: 10px;
|
||||
overflow: hidden;
|
||||
background: var(--bg-shade-0);
|
||||
}
|
||||
|
||||
.blog-card .post-info {
|
||||
flex: 50%;
|
||||
padding: 40px;
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
color: var(--text-shade-1);
|
||||
}
|
||||
|
||||
.blog-card .post-info .title {
|
||||
color: var(--text-shade-3);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.blog-card .post-info .caption {
|
||||
margin: 4px 0 32px 0;
|
||||
}
|
||||
|
||||
.blog-card .pub-info {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
justify-content: left;
|
||||
margin-top: auto;
|
||||
}
|
||||
|
||||
.blog-card .pub-info .date {
|
||||
font-weight: bold;
|
||||
color: var(--text-shade-3);
|
||||
}
|
||||
|
||||
.blog-card .pub-info>* {
|
||||
margin-right: 0.5em;
|
||||
margin-top: 0.2em;
|
||||
}
|
||||
|
||||
.blog-card .profile {
|
||||
display: inline-grid;
|
||||
grid-template-columns: 30px auto;
|
||||
grid-gap: 10px;
|
||||
font-weight: bold;
|
||||
color: var(--text-shade-3);
|
||||
align-items: center;
|
||||
height: 32px;
|
||||
margin-right: 0.3em;
|
||||
}
|
||||
|
||||
.blog-card .profile img {
|
||||
border-radius: 4px;
|
||||
border: 1px solid var(--border);
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.blog-card .cover {
|
||||
flex: 50%;
|
||||
border: 3px solid var(--bg-shade-0);
|
||||
border-radius: 0 10px 10px 0;
|
||||
}
|
||||
|
||||
.progress-hero a,
|
||||
.progress-hero a * {
|
||||
color: var(--accent-shade-1);
|
||||
text-decoration: none;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.progress-hero a:hover,
|
||||
.progress-hero a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.buttons {
|
||||
margin: 10vh auto;
|
||||
width: min-content;
|
||||
}
|
||||
|
||||
.buttons button.secondary.icon-btn {
|
||||
cursor: pointer;
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
footer {
|
||||
margin-top: 160px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss">
|
||||
@media screen and (max-width: 900px) {
|
||||
#root {
|
||||
.blog-card {
|
||||
flex-flow: column;
|
||||
}
|
||||
|
||||
.blog-card .post-info {
|
||||
padding: 30px;
|
||||
}
|
||||
|
||||
.blog-card .cover {
|
||||
order: -1;
|
||||
min-height: 250px;
|
||||
border-radius: 10px 10px 0 0;
|
||||
}
|
||||
|
||||
footer {
|
||||
margin-top: 100px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 450px) {
|
||||
#root {
|
||||
.blog-card .cover {
|
||||
min-height: 200px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -411,20 +411,6 @@ function titleSuffixHandler(path: string) {
|
|||
margin: 48px auto 0;
|
||||
}
|
||||
|
||||
h1.dot:not([data-title-suffix]):after,
|
||||
h2.dot:not([data-title-suffix]):after {
|
||||
content: ".";
|
||||
display: inline-block;
|
||||
color: var(--accent-shade-1);
|
||||
}
|
||||
|
||||
h1.dot[data-title-suffix]:after,
|
||||
h2.dot[data-title-suffix]:after {
|
||||
content: attr(data-title-suffix);
|
||||
display: inline-block;
|
||||
color: var(--accent-shade-1);
|
||||
}
|
||||
|
||||
/* Misc */
|
||||
.purple-circle {
|
||||
position: absolute;
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 78 KiB After Width: | Height: | Size: 78 KiB |
|
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 40 KiB |
|
Before Width: | Height: | Size: 497 KiB After Width: | Height: | Size: 497 KiB |
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 90 KiB After Width: | Height: | Size: 90 KiB |
|
Before Width: | Height: | Size: 71 KiB After Width: | Height: | Size: 71 KiB |
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 29 KiB |
|
Before Width: | Height: | Size: 9.7 KiB After Width: | Height: | Size: 9.7 KiB |
|
Before Width: | Height: | Size: 285 KiB After Width: | Height: | Size: 285 KiB |
|
Before Width: | Height: | Size: 56 KiB After Width: | Height: | Size: 56 KiB |
|
Before Width: | Height: | Size: 77 KiB After Width: | Height: | Size: 77 KiB |
|
Before Width: | Height: | Size: 9.2 KiB After Width: | Height: | Size: 9.2 KiB |
|
Before Width: | Height: | Size: 5.5 KiB After Width: | Height: | Size: 5.5 KiB |
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 1.8 MiB After Width: | Height: | Size: 1.8 MiB |
|
Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 114 KiB After Width: | Height: | Size: 114 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 118 KiB After Width: | Height: | Size: 118 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 145 KiB After Width: | Height: | Size: 145 KiB |
|
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 46 KiB |
|
Before Width: | Height: | Size: 434 KiB After Width: | Height: | Size: 434 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 407 KiB After Width: | Height: | Size: 407 KiB |
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 60 KiB After Width: | Height: | Size: 60 KiB |
|
Before Width: | Height: | Size: 9.3 KiB After Width: | Height: | Size: 9.3 KiB |
|
Before Width: | Height: | Size: 118 KiB After Width: | Height: | Size: 118 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 2.1 MiB After Width: | Height: | Size: 2.1 MiB |
|
Before Width: | Height: | Size: 106 KiB After Width: | Height: | Size: 106 KiB |
|
Before Width: | Height: | Size: 1.3 MiB After Width: | Height: | Size: 1.3 MiB |
|
Before Width: | Height: | Size: 101 KiB After Width: | Height: | Size: 101 KiB |
|
Before Width: | Height: | Size: 2.7 MiB After Width: | Height: | Size: 2.7 MiB |
|
Before Width: | Height: | Size: 167 KiB After Width: | Height: | Size: 167 KiB |
|
Before Width: | Height: | Size: 173 KiB After Width: | Height: | Size: 173 KiB |
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 61 KiB After Width: | Height: | Size: 61 KiB |
|
Before Width: | Height: | Size: 9.5 KiB After Width: | Height: | Size: 9.5 KiB |
|
Before Width: | Height: | Size: 693 KiB After Width: | Height: | Size: 693 KiB |
|
Before Width: | Height: | Size: 96 KiB After Width: | Height: | Size: 96 KiB |
|
Before Width: | Height: | Size: 53 KiB After Width: | Height: | Size: 53 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 45 KiB |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 727 KiB After Width: | Height: | Size: 727 KiB |
|
Before Width: | Height: | Size: 67 KiB After Width: | Height: | Size: 67 KiB |
|
Before Width: | Height: | Size: 623 KiB After Width: | Height: | Size: 623 KiB |
|
Before Width: | Height: | Size: 96 KiB After Width: | Height: | Size: 96 KiB |
|
Before Width: | Height: | Size: 410 KiB After Width: | Height: | Size: 410 KiB |
|
Before Width: | Height: | Size: 106 KiB After Width: | Height: | Size: 106 KiB |
|
Before Width: | Height: | Size: 43 KiB After Width: | Height: | Size: 43 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 35 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 741 KiB After Width: | Height: | Size: 741 KiB |
|
Before Width: | Height: | Size: 86 KiB After Width: | Height: | Size: 86 KiB |
|
Before Width: | Height: | Size: 688 KiB After Width: | Height: | Size: 688 KiB |
|
Before Width: | Height: | Size: 56 KiB After Width: | Height: | Size: 56 KiB |
|
Before Width: | Height: | Size: 78 KiB After Width: | Height: | Size: 78 KiB |
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 86 KiB After Width: | Height: | Size: 86 KiB |
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 211 KiB After Width: | Height: | Size: 211 KiB |
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 29 KiB |
|
Before Width: | Height: | Size: 220 KiB After Width: | Height: | Size: 220 KiB |
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 135 KiB After Width: | Height: | Size: 135 KiB |
|
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 36 KiB |
|
Before Width: | Height: | Size: 255 B After Width: | Height: | Size: 255 B |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
45
src/server/routes/blog/feed.xml.ts
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
import { Feed } from 'feed';
|
||||
|
||||
export default defineEventHandler(async (event) => {
|
||||
const allPosts = await queryCollection(event, 'blog').all();
|
||||
|
||||
const posts = allPosts.filter(p => !p.path.startsWith('/blog/_')).sort((a, b) => {
|
||||
return new Date(b.date).getTime() - new Date(a.date).getTime();
|
||||
});
|
||||
|
||||
const feed = new Feed({
|
||||
title: 'Pretendo Network Blog',
|
||||
description: 'The latest updates in condensed chunks',
|
||||
updated: new Date(posts[0].date),
|
||||
id: 'http://pretendo.network/',
|
||||
link: 'https://pretendo.network/blog/',
|
||||
image: 'https://pretendo.network/assets/images/opengraph/opengraph-image.png',
|
||||
favicon: 'http://pretendo.network/favicon.ico',
|
||||
copyright: 'Pretendo Network',
|
||||
feedLinks: {
|
||||
atom: 'https://pretendo.network/blog/rss.xml'
|
||||
}
|
||||
});
|
||||
|
||||
posts.forEach((post) => {
|
||||
feed.addItem({
|
||||
title: post.title,
|
||||
id: post.path,
|
||||
link: `https://pretendo.network${post.path}`,
|
||||
description: post.caption,
|
||||
author: [
|
||||
{
|
||||
name: post.author
|
||||
}
|
||||
],
|
||||
date: new Date(post.date),
|
||||
image: `https://pretendo.network${post.cover_image}`
|
||||
});
|
||||
});
|
||||
|
||||
feed.addCategory('Technology');
|
||||
|
||||
event.res.setHeader('content-type', 'text/xml');
|
||||
|
||||
return feed.rss2();
|
||||
});
|
||||