Initial Commit
This commit is contained in:
commit
a927fefeba
28 changed files with 5805 additions and 0 deletions
49
.github/workflows/deploy.yml
vendored
Normal file
49
.github/workflows/deploy.yml
vendored
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
name: Deploy
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
name: Build
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout repo
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Setup Node
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
uses: bahmutov/npm-install@v1
|
||||||
|
|
||||||
|
- name: Generate project as a static site
|
||||||
|
run: npm run generate
|
||||||
|
|
||||||
|
- name: Upload production-ready build files
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: production-files
|
||||||
|
path: ./output/public
|
||||||
|
|
||||||
|
deploy:
|
||||||
|
name: Deploy
|
||||||
|
needs: build
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: github.ref == 'refs/heads/main'
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Download artifact
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: production-files
|
||||||
|
path: ./output/public
|
||||||
|
|
||||||
|
- name: Deploy to GitHub Pages
|
||||||
|
uses: peaceiris/actions-gh-pages@v3
|
||||||
|
with:
|
||||||
|
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
publish_dir: ./output/public
|
24
.gitignore
vendored
Normal file
24
.gitignore
vendored
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
# Nuxt dev/build outputs
|
||||||
|
.output
|
||||||
|
.data
|
||||||
|
.nuxt
|
||||||
|
.nitro
|
||||||
|
.cache
|
||||||
|
dist
|
||||||
|
|
||||||
|
# Node dependencies
|
||||||
|
node_modules
|
||||||
|
|
||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
|
||||||
|
# Misc
|
||||||
|
.DS_Store
|
||||||
|
.fleet
|
||||||
|
.idea
|
||||||
|
|
||||||
|
# Local env files
|
||||||
|
.env
|
||||||
|
.env.*
|
||||||
|
!.env.example
|
75
README.md
Normal file
75
README.md
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
# Nuxt Minimal Starter
|
||||||
|
|
||||||
|
Look at the [Nuxt documentation](https://nuxt.com/docs/getting-started/introduction) to learn more.
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
|
||||||
|
Make sure to install dependencies:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# npm
|
||||||
|
npm install
|
||||||
|
|
||||||
|
# pnpm
|
||||||
|
pnpm install
|
||||||
|
|
||||||
|
# yarn
|
||||||
|
yarn install
|
||||||
|
|
||||||
|
# bun
|
||||||
|
bun install
|
||||||
|
```
|
||||||
|
|
||||||
|
## Development Server
|
||||||
|
|
||||||
|
Start the development server on `http://localhost:3000`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# npm
|
||||||
|
npm run dev
|
||||||
|
|
||||||
|
# pnpm
|
||||||
|
pnpm dev
|
||||||
|
|
||||||
|
# yarn
|
||||||
|
yarn dev
|
||||||
|
|
||||||
|
# bun
|
||||||
|
bun run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
## Production
|
||||||
|
|
||||||
|
Build the application for production:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# npm
|
||||||
|
npm run build
|
||||||
|
|
||||||
|
# pnpm
|
||||||
|
pnpm build
|
||||||
|
|
||||||
|
# yarn
|
||||||
|
yarn build
|
||||||
|
|
||||||
|
# bun
|
||||||
|
bun run build
|
||||||
|
```
|
||||||
|
|
||||||
|
Locally preview production build:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# npm
|
||||||
|
npm run preview
|
||||||
|
|
||||||
|
# pnpm
|
||||||
|
pnpm preview
|
||||||
|
|
||||||
|
# yarn
|
||||||
|
yarn preview
|
||||||
|
|
||||||
|
# bun
|
||||||
|
bun run preview
|
||||||
|
```
|
||||||
|
|
||||||
|
Check out the [deployment documentation](https://nuxt.com/docs/getting-started/deployment) for more information.
|
17
app.vue
Normal file
17
app.vue
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { main } from "@popperjs/core";
|
||||||
|
import MainPage from "./pages/index.vue"
|
||||||
|
import backgroundCalm from "./components/BackgroundCalm.vue";
|
||||||
|
import Navbar from "./components/Navbar.vue"
|
||||||
|
import './assets/style.css'
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<Navbar/>
|
||||||
|
<NuxtLayout>
|
||||||
|
<NuxtPage/>
|
||||||
|
</NuxtLayout>
|
||||||
|
<background-calm />
|
||||||
|
</div>
|
||||||
|
</template>
|
33
assets/about_me.md
Normal file
33
assets/about_me.md
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
# Helau! :3
|
||||||
|
|
||||||
|
## 🌙 Luna - She/Her
|
||||||
|
|
||||||
|
<a href="mailto: thelunacy@proton.me">`thelunacy@proton.me`</a>
|
||||||
|
|
||||||
|
###### This is a specific email for contact.
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
###### 🏳️⚧️ I am exploring identity, so this may change or I might go by different things elsewhere.
|
||||||
|
|
||||||
|
###### Regardless, try to respect this or else. I'm not here to debate my existence.
|
||||||
|
|
||||||
|
<div style="color: pink">
|
||||||
|
|
||||||
|
*Queer rights are human rights.*
|
||||||
|
</div>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<div style="justify-content: center; display: flex; align-items: center;">
|
||||||
|
|
||||||
|
![Visitors](https://api.visitorbadge.io/api/combined?path=https%3A%2F%2Fgithub.com%2Fmisslunatic%2FMissLunatic&label=VIsitors&countColor=%23e7c4ff&style=plastic)
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
I'm a student, apprentice, hobbyist, and generally a nerd who does some coding every once and a while.
|
||||||
|
I've mainly been messing with C, C++, C# and have been learning Rust. I'm presently learning more about web development, particularly regarding frameworks and libraries.
|
||||||
|
I'm a bit shy in terms of socializing, but I'm often open to chat about most things, so long as it's respectful.
|
||||||
|
Please reach out to me first, I probably won't do so myself.
|
||||||
|
|
||||||
|
Follow if you enjoy. I'm not *too* active, but I'll try to post some things every once and a while.
|
18
assets/blog_list.json
Normal file
18
assets/blog_list.json
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
{
|
||||||
|
"posts": [
|
||||||
|
{
|
||||||
|
"metadata": {
|
||||||
|
"title": "Awesome", "description": "A curated list of awesome stuff I like", "date": "2024-11-26", "tags": ["awesome", "curated"]
|
||||||
|
},
|
||||||
|
"id": "awesome",
|
||||||
|
"url": "/blog/awesome.md"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"metadata": {
|
||||||
|
"title": "Badges!", "description": "A collection of 88x31 badges for various things", "date": "2024-12-21", "tags": ["badges", "retro", "web"]
|
||||||
|
},
|
||||||
|
"id": "badges",
|
||||||
|
"url": "/blog/badges.md"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
152
assets/style.css
Normal file
152
assets/style.css
Normal file
|
@ -0,0 +1,152 @@
|
||||||
|
@import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:ital,wght@0,100..800;1,100..800&display=swap');
|
||||||
|
@import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:ital,wght@0,100..800;1,100..800&family=Lobster&display=swap');
|
||||||
|
|
||||||
|
@tailwind base;
|
||||||
|
@tailwind components;
|
||||||
|
@tailwind utilities;
|
||||||
|
|
||||||
|
html {
|
||||||
|
@apply min-h-screen bg-slate-950;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-family: 'Lobster', cursive, 'Courier New', Courier, monospace;
|
||||||
|
@apply text-3xl font-bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
@apply text-2xl font-bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
@apply text-xl font-bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4 {
|
||||||
|
@apply text-lg font-bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
h5 {
|
||||||
|
@apply text-base font-bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
h6 {
|
||||||
|
@apply text-sm font-bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
@apply transition text-purple-400 hover:text-purple-500;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
blockquote p {
|
||||||
|
@apply border-l-4 border-purple-400 pl-2;
|
||||||
|
container: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
br {
|
||||||
|
content: '';
|
||||||
|
display: block;
|
||||||
|
margin-top: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul {
|
||||||
|
@apply list-disc list-inside;
|
||||||
|
}
|
||||||
|
|
||||||
|
ol {
|
||||||
|
@apply list-decimal list-inside;
|
||||||
|
}
|
||||||
|
|
||||||
|
li {
|
||||||
|
@apply my-2;
|
||||||
|
}
|
||||||
|
p {
|
||||||
|
line-height: normal;
|
||||||
|
}
|
||||||
|
pre code {
|
||||||
|
white-space: pre-wrap;
|
||||||
|
display: block;
|
||||||
|
padding: 1em;
|
||||||
|
background-color: #272822;
|
||||||
|
@apply border-purple-400 border rounded-lg;
|
||||||
|
}
|
||||||
|
|
||||||
|
code {
|
||||||
|
font-family: 'JetBrains Mono', monospace;
|
||||||
|
@apply bg-purple-950 subpixel-antialiased;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Code if there is no pre tag before it */
|
||||||
|
:not(pre) > code {
|
||||||
|
@apply p-1 border-purple-800 border rounded-lg;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Code theme */
|
||||||
|
|
||||||
|
.hljs {
|
||||||
|
background: #272822;
|
||||||
|
color: #ddd;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hljs-tag,
|
||||||
|
.hljs-keyword,
|
||||||
|
.hljs-selector-tag,
|
||||||
|
.hljs-literal,
|
||||||
|
.hljs-strong,
|
||||||
|
.hljs-number,
|
||||||
|
.hljs-name {
|
||||||
|
color: #f92672;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hljs-code {
|
||||||
|
color: #66d9ef;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hljs-attribute,
|
||||||
|
.hljs-attr,
|
||||||
|
.hljs-symbol,
|
||||||
|
.hljs-regexp,
|
||||||
|
.hljs-link {
|
||||||
|
color: #bf79db;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hljs-string,
|
||||||
|
.hljs-bullet,
|
||||||
|
.hljs-subst,
|
||||||
|
.hljs-title,
|
||||||
|
.hljs-section,
|
||||||
|
.hljs-emphasis,
|
||||||
|
.hljs-type,
|
||||||
|
.hljs-built_in,
|
||||||
|
.hljs-selector-attr,
|
||||||
|
.hljs-selector-pseudo,
|
||||||
|
.hljs-addition,
|
||||||
|
.hljs-variable,
|
||||||
|
.hljs-template-tag,
|
||||||
|
.hljs-template-variable {
|
||||||
|
color: #a6e22e;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hljs-title.class_,
|
||||||
|
.hljs-class .hljs-title {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hljs-comment,
|
||||||
|
.hljs-quote,
|
||||||
|
.hljs-deletion,
|
||||||
|
.hljs-meta {
|
||||||
|
color: #75715e;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hljs-keyword,
|
||||||
|
.hljs-selector-tag,
|
||||||
|
.hljs-literal,
|
||||||
|
.hljs-doctag,
|
||||||
|
.hljs-title,
|
||||||
|
.hljs-section,
|
||||||
|
.hljs-type,
|
||||||
|
.hljs-selector-id {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
1
assets/vue.svg
Normal file
1
assets/vue.svg
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="37.07" height="36" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 198"><path fill="#41B883" d="M204.8 0H256L128 220.8L0 0h97.92L128 51.2L157.44 0h47.36Z"></path><path fill="#41B883" d="m0 0l128 220.8L256 0h-51.2L128 132.48L50.56 0H0Z"></path><path fill="#35495E" d="M50.56 0L128 133.12L204.8 0h-47.36L128 51.2L97.92 0H50.56Z"></path></svg>
|
After Width: | Height: | Size: 496 B |
77
components/BackgroundCalm.vue
Normal file
77
components/BackgroundCalm.vue
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { Engine } from '@tsparticles/engine';
|
||||||
|
|
||||||
|
const onLoad = (container: Container) => {
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<NuxtParticles
|
||||||
|
class="fixed w-full h-full"
|
||||||
|
id="tsparticles"
|
||||||
|
@load="onLoad"
|
||||||
|
:particlesInit="particlesInit"
|
||||||
|
:options="{
|
||||||
|
fullScreen: {
|
||||||
|
enable: true,
|
||||||
|
zIndex: -1
|
||||||
|
},
|
||||||
|
fpsLimit: 60,
|
||||||
|
interactivity: {
|
||||||
|
detect_on: 'window',
|
||||||
|
events: {
|
||||||
|
onHover: {
|
||||||
|
enable: true,
|
||||||
|
mode: 'repulse'
|
||||||
|
},
|
||||||
|
},
|
||||||
|
modes: {
|
||||||
|
repulse: {
|
||||||
|
distance: 100,
|
||||||
|
duration: 1.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
particles: {
|
||||||
|
zIndex: -10,
|
||||||
|
color: {
|
||||||
|
value: '#A020F0'
|
||||||
|
},
|
||||||
|
links: {
|
||||||
|
color: '#B020F0',
|
||||||
|
distance: 200,
|
||||||
|
enable: true,
|
||||||
|
opacity: 0.5,
|
||||||
|
width: 1.5
|
||||||
|
},
|
||||||
|
move: {
|
||||||
|
direction: 'none',
|
||||||
|
enable: true,
|
||||||
|
outModes: 'bounce',
|
||||||
|
random: false,
|
||||||
|
speed: 1.5,
|
||||||
|
straight: false
|
||||||
|
},
|
||||||
|
number: {
|
||||||
|
density: {
|
||||||
|
enable: true,
|
||||||
|
},
|
||||||
|
value: 40
|
||||||
|
},
|
||||||
|
opacity: {
|
||||||
|
value: 0.5
|
||||||
|
},
|
||||||
|
shape: {
|
||||||
|
type: 'circle'
|
||||||
|
},
|
||||||
|
size: {
|
||||||
|
value: { min: 2, max: 9 }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
detectRetina: true
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
</NuxtParticles>
|
||||||
|
<slot></slot>
|
||||||
|
</template>
|
15
components/Navbar.vue
Normal file
15
components/Navbar.vue
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
<template>
|
||||||
|
<div class="flex justify-center">
|
||||||
|
<div class="flex-col transition-[margin] justify-center md:rounded-md max-md:w-screen lg:mt-3 w-fit-content pr-4 pl-4 bg-purple-500 bg-opacity-25 text-white">
|
||||||
|
<div class="flex justify-center">
|
||||||
|
<a href="/" class="transition text-xl pl-2 pr-2 ease-in-out text-purple-100 hover:text-purple-400 duration-200">Home</a>
|
||||||
|
<a href="/blog/" class="transition text-xl pl-2 pr-2 ease-in-out text-purple-100 hover:text-purple-400 duration-200">Blog</a>
|
||||||
|
<a href="/blog/?post=/blog/awesome.md" class="transition text-xl pl-2 pr-2 ease-in-out text-purple-100 hover:text-purple-400 duration-200">Awesome</a>
|
||||||
|
<a href="/blog/?post=/blog/badges.md" class="transition text-xl pl-2 pr-2 ease-in-out text-purple-100 hover:text-purple-400 duration-200">Badges</a>
|
||||||
|
</div>
|
||||||
|
<div class="flex justify-center">
|
||||||
|
<small class=" ml-3 mr-3">Hosted with <a href="https://github.com/misslunatic/misslunatic.github.io" class="text-blue-500">GitHub Pages</a></small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
80
components/PostCard.vue
Normal file
80
components/PostCard.vue
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
<script setup>
|
||||||
|
import { ref, watch } from 'vue';
|
||||||
|
import fm from 'front-matter';
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
url: String,
|
||||||
|
});
|
||||||
|
|
||||||
|
import { useSlots } from 'vue';
|
||||||
|
|
||||||
|
const slots = useSlots();
|
||||||
|
|
||||||
|
|
||||||
|
const url = ref(props.url)
|
||||||
|
url.value = props.url
|
||||||
|
const loading = ref(false)
|
||||||
|
const data = ref(null)
|
||||||
|
const error = ref(null)
|
||||||
|
|
||||||
|
const background = ref('');
|
||||||
|
const title = ref(null);
|
||||||
|
const description = ref(null);
|
||||||
|
const date = ref(null);
|
||||||
|
const tags = ref(null);
|
||||||
|
|
||||||
|
// watch the params of the route to fetch the data again
|
||||||
|
watch(url, async () => {
|
||||||
|
await fetchData()
|
||||||
|
}, {
|
||||||
|
immediate: true
|
||||||
|
});
|
||||||
|
|
||||||
|
async function fetchData() {
|
||||||
|
error.value = data.value = null
|
||||||
|
loading.value = true
|
||||||
|
|
||||||
|
try {
|
||||||
|
data.value = await (await fetch(url.value)).text()
|
||||||
|
const processed = fm(data.value)
|
||||||
|
background.value = processed.attributes.background
|
||||||
|
title.value = processed.attributes.title
|
||||||
|
description.value = processed.attributes.description
|
||||||
|
date.value = processed.attributes.date
|
||||||
|
tags.value = processed.attributes.tags
|
||||||
|
} catch (err) {
|
||||||
|
error.value = err.toString()
|
||||||
|
loading.value = false
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<a :href="'/blog?post=' +url">
|
||||||
|
<div class="m-4 p-3 min-h-10 w-90 text-white rounded-2xl border-2 border-purple-300 transition hover:bg-purple-600 bg-purple-700 bg-opacity-50 hover:bg-opacity-70"
|
||||||
|
:style="{ backgroundImage: `url(${background})` }">
|
||||||
|
<div v-if="loading" class="text-center animate-pulse">
|
||||||
|
<h2>Loading...</h2>
|
||||||
|
</div>
|
||||||
|
<div v-else-if="error" class="text-center">
|
||||||
|
<h2>Error: {{ error }}</h2>
|
||||||
|
<button @click="fetchData">Retry</button>
|
||||||
|
</div>
|
||||||
|
<div v-else>
|
||||||
|
<div class="grid">
|
||||||
|
<div class="justify-center">
|
||||||
|
<h1>{{ title }}</h1>
|
||||||
|
</div>
|
||||||
|
<div class="flex justify-center">
|
||||||
|
<div v-for="tag in tags" :key="tag" class="m-1 text-center">
|
||||||
|
<span class="text-xs bg-purple-800 border-purple-400 border text-white p-1 rounded-md">{{ tag }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p>{{ description }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</template>
|
24
nuxt.config.ts
Normal file
24
nuxt.config.ts
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
// https://nuxt.com/docs/api/configuration/nuxt-config
|
||||||
|
export default defineNuxtConfig({
|
||||||
|
compatibilityDate: '2024-11-01',
|
||||||
|
devtools: { enabled: true },
|
||||||
|
postcss: {
|
||||||
|
plugins: {
|
||||||
|
tailwindcss: {},
|
||||||
|
autoprefixer: {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
app: {
|
||||||
|
layoutTransition: {
|
||||||
|
name: 'layout',
|
||||||
|
mode: 'out-in'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
modules: [
|
||||||
|
'nuxt-particles'
|
||||||
|
],
|
||||||
|
particles: {
|
||||||
|
mode: 'slim',
|
||||||
|
lazy: true
|
||||||
|
}
|
||||||
|
})
|
31
package.json
Normal file
31
package.json
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
{
|
||||||
|
"name": "nuxt-app",
|
||||||
|
"private": true,
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"build": "rm assets/blog_list.json && sh utils/track_posts.sh >> assets/blog_list.json && nuxt build",
|
||||||
|
"dev": "rm assets/blog_list.json && sh utils/track_posts.sh >> assets/blog_list.json && nuxt dev",
|
||||||
|
"generate": "rm assets/blog_list.json && sh utils/track_posts.sh >> assets/blog_list.json && nuxt generate",
|
||||||
|
"preview": "rm assets/blog_list.json && sh utils/track_posts.sh >> assets/blog_list.json &&nuxt preview",
|
||||||
|
"postinstall": "rm assets/blog_list.json && sh utils/track_posts.sh >> assets/blog_list.json &&nuxt prepare"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@popperjs/core": "^2.11.8",
|
||||||
|
"@tsparticles/slim": "^3.7.1",
|
||||||
|
"nuxt": "^3.14.1592",
|
||||||
|
"tsparticles": "^3.7.1",
|
||||||
|
"vue": "latest",
|
||||||
|
"vue-router": "latest",
|
||||||
|
"@tsparticles/engine": "^3.5.0",
|
||||||
|
"@tsparticles/vue3": "^3.0.1",
|
||||||
|
"front-matter": "^4.0.2",
|
||||||
|
"highlight.js": "^11.10.0",
|
||||||
|
"markdown-it": "^14.1.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"autoprefixer": "^10.4.20",
|
||||||
|
"nuxt-particles": "^0.3.0",
|
||||||
|
"postcss": "^8.4.49",
|
||||||
|
"tailwindcss": "^3.4.17"
|
||||||
|
}
|
||||||
|
}
|
202
pages/blog.vue
Normal file
202
pages/blog.vue
Normal file
|
@ -0,0 +1,202 @@
|
||||||
|
<script setup>
|
||||||
|
import { onMounted, watch, ref } from 'vue';
|
||||||
|
import fm from 'front-matter';
|
||||||
|
import markdownit from 'markdown-it'
|
||||||
|
import PostCard from '../components/PostCard.vue';
|
||||||
|
import hljs from 'highlight.js';
|
||||||
|
|
||||||
|
// Automatically maintained is a blog_list.json in assets/. This file contains a list of all blog posts and their metadata.
|
||||||
|
// This file is generated by a script in the root directory of the project.
|
||||||
|
import blog_list from '../assets/blog_list.json';
|
||||||
|
|
||||||
|
const md = markdownit({
|
||||||
|
breaks: true,
|
||||||
|
typographer: true,
|
||||||
|
html: true,
|
||||||
|
highlight: function (str, lang) {
|
||||||
|
if (lang && hljs.getLanguage(lang)) {
|
||||||
|
try {
|
||||||
|
return '<pre><code class="hljs">' +
|
||||||
|
hljs.highlight(str, { language: lang, ignoreIllegals: true }).value +
|
||||||
|
'</code></pre>';
|
||||||
|
} catch (__) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
return '<pre><code class="hljs">' + md.utils.escapeHtml(str) + '</code></pre>';
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
md.renderer.rules.hr = function (tokens, idx, options, env, self) {
|
||||||
|
return '<div class="rounded-full h-0.5 bg-purple-500 my-3"></div>'
|
||||||
|
}
|
||||||
|
|
||||||
|
md.renderer.rules.softbreak = function (tokens, idx, options, env, self) {
|
||||||
|
return '<br>'
|
||||||
|
}
|
||||||
|
|
||||||
|
md.renderer.rules.hardbreak = function (tokens, idx, options, env, self) {
|
||||||
|
return '<br><br>'
|
||||||
|
}
|
||||||
|
|
||||||
|
const modules = import.meta.glob('/blog/');
|
||||||
|
|
||||||
|
for (const path in modules) {
|
||||||
|
const module = await modules[path]();
|
||||||
|
console.log(path, module.default); // module.default contains the image data
|
||||||
|
}
|
||||||
|
|
||||||
|
let route = useRoute();
|
||||||
|
console.log(route)
|
||||||
|
|
||||||
|
|
||||||
|
const url = ref(null)
|
||||||
|
url.value = route.query.post
|
||||||
|
console.log(url.value)
|
||||||
|
|
||||||
|
const loading = ref(false)
|
||||||
|
const data = ref([])
|
||||||
|
const text = ref([])
|
||||||
|
const error = ref([])
|
||||||
|
|
||||||
|
const list = ref([])
|
||||||
|
const tagList = ref([])
|
||||||
|
const tagFilter = ref([])
|
||||||
|
tagFilter.value = []
|
||||||
|
|
||||||
|
|
||||||
|
const background = ref('');
|
||||||
|
const title = ref(null);
|
||||||
|
const description = ref(null);
|
||||||
|
const date = ref(null);
|
||||||
|
const tags = ref(null);
|
||||||
|
|
||||||
|
// watch the params of the route to fetch the data again
|
||||||
|
|
||||||
|
fetchData(url.value)
|
||||||
|
|
||||||
|
|
||||||
|
async function fetchData(url) {
|
||||||
|
error.value = data.value = null
|
||||||
|
loading.value = true
|
||||||
|
console.log(url)
|
||||||
|
try {
|
||||||
|
data.value = await $fetch(url)
|
||||||
|
console.log(data.value)
|
||||||
|
const processed = fm(data.value)
|
||||||
|
text.value = md.render(processed.body)
|
||||||
|
console.log(text.value)
|
||||||
|
background.value = processed.attributes.background
|
||||||
|
title.value = processed.attributes.title
|
||||||
|
description.value = processed.attributes.description
|
||||||
|
date.value = processed.attributes.date
|
||||||
|
tags.value = processed.attributes.tags
|
||||||
|
} catch (err) {
|
||||||
|
error.value = err.toString()
|
||||||
|
console.error(err)
|
||||||
|
loading.value = false
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If tags are specified, include only posts with those tags */
|
||||||
|
/* else, include all posts */
|
||||||
|
async function fetchList() {
|
||||||
|
/*Example formatting:
|
||||||
|
{
|
||||||
|
"posts": [
|
||||||
|
{
|
||||||
|
"metadata": {
|
||||||
|
"test": "mrrp"
|
||||||
|
},
|
||||||
|
"id": "test",
|
||||||
|
"url": "/blog/test"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"metadata": {
|
||||||
|
" title": "Awesome", "description": "A curated list of awesome stuff I like", "date": "2024-11-26", "tags": ["awesome", "curated"]
|
||||||
|
},
|
||||||
|
"id": "awesome",
|
||||||
|
"url": "/blog/awesome"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"metadata": {
|
||||||
|
"test": "mrrp",
|
||||||
|
"test2": "nya"
|
||||||
|
},
|
||||||
|
"id": "test2",
|
||||||
|
"url": "/blog/test2"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Extract the posts
|
||||||
|
list.value = blog_list.posts
|
||||||
|
|
||||||
|
// Extract the tags
|
||||||
|
tagList.value = blog_list.posts.flatMap(post => post.metadata.tags).filter((tag, index, self) => self.indexOf(tag) === index)
|
||||||
|
|
||||||
|
}
|
||||||
|
fetchList()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="relative z-50 flex w-full justify-center text-white">
|
||||||
|
<div class="mt-8 flex-col text-center">
|
||||||
|
<div v-if="url == null">
|
||||||
|
<h1>Blog</h1>
|
||||||
|
<div class="flex justify-center m-5">
|
||||||
|
<div v-for="tag in tagList" :key="tag" class="m-1 text-center">
|
||||||
|
<button
|
||||||
|
@click="tagFilter.includes(tag) ? tagFilter.splice(tagFilter.indexOf(tag), 1) : tagFilter.push(tag)"
|
||||||
|
class="text-xs bg-purple-800 border-purple-400 border text-white p-1 rounded-md"
|
||||||
|
:class="tagFilter.includes(tag) ? 'border-2 border-purple-200 bg-purple-500' : 'border-1 border-purple-600 bg-purple-800 text-white'">{{
|
||||||
|
tag }}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<TransitionGroup name="list">
|
||||||
|
<div v-for="post in tagFilter.length == 0 ? list : list.filter(post => tagFilter.some(tag => post.metadata.tags.includes(tag)))" :key="post.id">
|
||||||
|
<PostCard :url="post.url" :key="post.id" />
|
||||||
|
</div>
|
||||||
|
</TransitionGroup>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-else>
|
||||||
|
<div class="flex flex-col">
|
||||||
|
<h1>{{ title }}</h1>
|
||||||
|
<div class="max-w-50 flex flex-row justify-center">
|
||||||
|
<div v-for="tag in tags" :key="tag" class="m-1 text-center">
|
||||||
|
<span class="text-xs bg-purple-800 border-purple-400 border text-white p-1 rounded-md">{{
|
||||||
|
tag }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="text-pretty min-w-96 text-left max-w-4xl mt-4 p-6 max-md:w-screen rounded-md container bg-opacity-90 bg-purple-950">
|
||||||
|
<div v-html="text"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.list-move,
|
||||||
|
.list-enter-active,
|
||||||
|
.list-leave-active {
|
||||||
|
transition: all 0.5s cubic-bezier(0.55, 0, 0.1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-enter-from,
|
||||||
|
.list-leave-to {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translate(100px, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-leave-active {
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
</style>
|
47
pages/index.vue
Normal file
47
pages/index.vue
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
<script setup>
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import aboutMe from '../assets/about_me.md?raw'
|
||||||
|
import markdownit from 'markdown-it'
|
||||||
|
import PostCard from '../components/PostCard.vue';
|
||||||
|
|
||||||
|
const md = markdownit({
|
||||||
|
breaks: true,
|
||||||
|
typographer: true,
|
||||||
|
html: true,
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
md.renderer.rules.hr = function(tokens, idx, options, env, self) {
|
||||||
|
return '<div class="rounded-full h-0.5 bg-purple-500 my-3"></div>'
|
||||||
|
}
|
||||||
|
|
||||||
|
md.renderer.rules.softbreak = function(tokens, idx, options, env, self) {
|
||||||
|
return '<br>'
|
||||||
|
}
|
||||||
|
|
||||||
|
md.renderer.rules.hardbreak = function(tokens, idx, options, env, self) {
|
||||||
|
return '<br><br>'
|
||||||
|
}
|
||||||
|
md.renderer.rules.blockquote_open = function(tokens, idx, options, env, self) {
|
||||||
|
return '<blockquote class="border-l-4 border-purple-500 pl-4 my-4">'
|
||||||
|
}
|
||||||
|
const result = ref('')
|
||||||
|
|
||||||
|
result.value = md.render(aboutMe);
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="relative z-50 flex w-full justify-center text-white">
|
||||||
|
<div class="mt-8 flex-col text-center">
|
||||||
|
<div class="flex justify-center">
|
||||||
|
<div class="p-2 shadow-md rounded-full bg-pink-500">
|
||||||
|
<img class="z-20 transition-all w-40 h-40 md:w-56 md:h-56 rounded-full" src="https://avatars.githubusercontent.com/u/94077364?v=4" alt="User PFP" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="max-w-4xl mt-4 p-6 max-md:w-screen rounded-md container bg-opacity-70 bg-purple-950">
|
||||||
|
<div v-html=result></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
BIN
public/badges/nonbinary.gif
Normal file
BIN
public/badges/nonbinary.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 1 KiB |
BIN
public/badges/transfem.gif
Normal file
BIN
public/badges/transfem.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 909 B |
BIN
public/badges/transgender.gif
Normal file
BIN
public/badges/transgender.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
BIN
public/badges/transmasc.gif
Normal file
BIN
public/badges/transmasc.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 1,019 B |
117
public/blog/awesome.md
Normal file
117
public/blog/awesome.md
Normal file
|
@ -0,0 +1,117 @@
|
||||||
|
---
|
||||||
|
title: Awesome
|
||||||
|
description: A curated list of awesome stuff I like
|
||||||
|
date: 2024-11-26
|
||||||
|
tags: ['awesome', 'curated']
|
||||||
|
---
|
||||||
|
|
||||||
|
# Awesome Stuff (WIP)
|
||||||
|
|
||||||
|
## Software
|
||||||
|
|
||||||
|
### Operating Systems
|
||||||
|
|
||||||
|
Honestly can't recommend Windows at all nowadays. It's just... Both spyware and bloatware. It's been enshittified to the point where it's just not worth using in comparison to Linux for most, if not all purposes nowadays, and the only thing it has going for it is existing software, which is a rapidly fading, if not fade***d***, advantage.
|
||||||
|
Windows Recall was especially egregious - The fact that a program that records all your screens, saves it to an unencrypted SQLite database, then feeds it to an AI network was *even on the table* is just... ***YIKES.***
|
||||||
|
|
||||||
|
- [Arch Linux](https://archlinux.org/)
|
||||||
|
|
||||||
|
> btw I use Arch
|
||||||
|
did I mention I use Arch
|
||||||
|
I use Arch btw just in case you didn't know
|
||||||
|
arch btw
|
||||||
|
/j
|
||||||
|
|
||||||
|
- [NixOS](https://nixos.org/)
|
||||||
|
|
||||||
|
> NixOS is a operating system that uses the Nix package manager. It's a great choice for people who want a declarative system configuration, and it's a great choice for people who want to be able to roll back to a previous system configuration if something goes wrong. It's also a great choice for people who want to be able to install packages without having to worry about dependency hell.
|
||||||
|
Because of the way NixOS works, I can use it pretty damn easily across my many systems, and it makes it easy to debloat if I need to.
|
||||||
|
|
||||||
|
## Software Development
|
||||||
|
|
||||||
|
### Languages
|
||||||
|
|
||||||
|
- [Rust](https://www.rust-lang.org/)
|
||||||
|
|
||||||
|
> I came to Rust from C/C++, and I've been loving it ever since. It's a great language that's easy to learn and has a lot of features that make it a great choice for systems programming. It's also a great choice for web development, and it's a decent choice for game development. It's a great choice for pretty much anything, really.
|
||||||
|
|
||||||
|
### Game Development
|
||||||
|
|
||||||
|
- [Godot Engine](https://godotengine.org)
|
||||||
|
|
||||||
|
> Nowadays, I'm mostly using Godot for game development. It's a great engine that's easy to use and has a lot of features. Plus, it's open-source, which is always a plus. The executable is in the magnitude of *MEGABYTES* and you can download it and just get going.
|
||||||
|
Unity is, at this point, inferior to Godot in my opinion for general purpose games. It's bloated as hell, slow, and has a lot of unnecessary core features that are often half-baked or deprecated - There is often 99 ways to do things, but none are good. It's not open source, and isn't nearly as capable of recompiling to cut down on unneeded features as a result. It's also not as user-friendly as Godot, and the documentation is often lacking or outdated. I've had a lot of issues with Unity, and I'm not a fan of it.
|
||||||
|
And on the other end, if you need high-fidelity games... Unreal Engine 5 is a no-brainer over Unity nowadays for the same purpose.
|
||||||
|
And for 2D games... Godot absolutely ***MOPS THE FLOOR WITH UNITY.*** It hardly even compares at this point.
|
||||||
|
|
||||||
|
- [Unreal Engine 5](https://www.unrealengine.com/)
|
||||||
|
|
||||||
|
> I don't use it much, but it's a great engine for high-fidelity games. It's a ***LOT*** more complex than Godot, but it's also more powerful. Plus, it's free to use until you make a certain amount of money, and they let you remain on the same licensing terms from when you start using it.
|
||||||
|
|
||||||
|
- [Material Maker](https://www.materialmaker.org/)
|
||||||
|
|
||||||
|
> Material Maker is a toolkit made in Godot that allows you to create procedural PBR materials, similar to how you would with Blender shaders.
|
||||||
|
It's a great tool for creating materials, and it's open-source, so you can modify it to your heart's content.
|
||||||
|
|
||||||
|
## Games
|
||||||
|
|
||||||
|
I will be using the Entertainment Software Rating Board's rating system for games, under my judgement if a rating does not already exist.
|
||||||
|
These may not actually be rated by the ESRB, but I will be using their rating system for simplicity.
|
||||||
|
See their [Ratings Guide](https://www.esrb.org/ratings-guide/) for more information about their rating system.
|
||||||
|
|
||||||
|
- [Celeste](https://www.celestegame.com/)
|
||||||
|
***Rated E10 for Everyone 10+ by the ESRB***
|
||||||
|
|
||||||
|
> What can I say? It's a great game. The story is touching, the gameplay is challenging, and the music is amazing.
|
||||||
|
Plus, the modding scene is very intense if you're into that.
|
||||||
|
Also... Heat from fire, fire from heat, if ya know. 🏳️⚧️
|
||||||
|
|
||||||
|
- [Wolfenstein: The New Order](https://store.steampowered.com/app/201810/Wolfenstein_The_New_Order/) and its sequel, [Wolfenstein: The New Colossus](https://store.steampowered.com/app/612880/Wolfenstein_II_The_New_Colossus/)
|
||||||
|
***Rated M for Mature 17+ by the ESRB***
|
||||||
|
|
||||||
|
> Before Id made DOOM in 1993, they made Wolfenstein, a game about beating up Nazis. Need I say more?
|
||||||
|
They made a new series of games, starting with The New Order, that are a great mix of story and gameplay. The story is great, the gameplay is great, and the music is great. Criminal that there isn't a third one, though.
|
||||||
|
|
||||||
|
- [OneShot](https://store.steampowered.com/app/420530/OneShot/)
|
||||||
|
***Rated E for Everyone by the ESRB***
|
||||||
|
|
||||||
|
> You only get one shot.
|
||||||
|
|
||||||
|
- [Papers, Please](https://store.steampowered.com/app/239030/Papers_Please/)
|
||||||
|
***Rated M for Mature 17+ by the ESRB***
|
||||||
|
|
||||||
|
> ***Glory to Arstotzka.***
|
||||||
|
|
||||||
|
- [Sonic Adventure 2](https://store.steampowered.com/app/213610/Sonic_Adventure_2/)
|
||||||
|
|
||||||
|
***Rated E10 for Everyone 10+ by the ESRB***
|
||||||
|
> I grew up with SA2. Sure, it has plenty of things that did NOT age well - Such as the audio mixing, the music is *twice as loud* as it should be during scenes, I can barely hear characters, or the quality of the ports being pretty abysmal - But it is still quite a fun game. The story is, perhaps, among the best, in the series, and Doctor Ivo "Eggman" Robotnik's characterization is ***OUTRIGHT the best in the series***. The music (Crush 40, anyone?) is also top-notch.
|
||||||
|
If you play this on PC, such as the Steam version, there exists a mod loader, and plenty of mods to improve the myriad issues with the port.
|
||||||
|
Mad Space is a bit maddening (Well, it's in the name I suppose) though, and the removal of the open-world that SA1 had isn't that great.
|
||||||
|
|
||||||
|
## Media
|
||||||
|
|
||||||
|
I will be using the Motion Picture Association's rating system for movies or media in general should it not have its own rating system, under my judgement if a rating does not already exist.
|
||||||
|
These may not actually be rated by the MPA, but I will be using their rating system for simplicity.
|
||||||
|
See the Motion Picture Association's [Film Ratings](https://www.motionpictures.org/film-ratings/) for more information about their rating system.
|
||||||
|
|
||||||
|
I will be using the TV Parental Guidelines's rating system for shows or series, under my judgement if a rating does not already exist.
|
||||||
|
These may not actually be rated by official organizations, but I will be using their rating system for simplicity.
|
||||||
|
|
||||||
|
### Shows
|
||||||
|
|
||||||
|
- [One Piece](https://www.crunchyroll.com/series/GRMG8ZQZR/one-piece)
|
||||||
|
***Rating varies depending on parts of the show, and movies and whatnot.***
|
||||||
|
***I rate the show as a range from TV-PG V to TV-MA LV.***
|
||||||
|
|
||||||
|
> Oda had better finish the story. I swear to Satan.
|
||||||
|
|
||||||
|
#### Fanmade
|
||||||
|
|
||||||
|
- [Dragon Ball Z Abridged](https://www.youtube.com/watch?v=2nYozPLpJRE&list=PL6EC7B047181AD013) (and related "movies" and videos) by TeamFourStar
|
||||||
|
***I rate this show and its movies as TV-MA DLSV (the whole shebang, in other words)***
|
||||||
|
|
||||||
|
> It's... The iconic parody of all time. It's a great show, and it's a shame that they aren't doing Buu Saga.
|
||||||
|
Even though the series is more comedy focused, it still manages to tell the story of Dragon Ball Z in an *excellent* way.
|
||||||
|
The creators are also based as hell.
|
||||||
|
...Watch it. Just watch it.
|
36
public/blog/badges.md
Normal file
36
public/blog/badges.md
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
---
|
||||||
|
title: Badges!
|
||||||
|
description: A collection of 88x31 badges for various things
|
||||||
|
date: 2024-12-21
|
||||||
|
tags: ['badges', 'retro', 'web']
|
||||||
|
---
|
||||||
|
|
||||||
|
## A collection of 88x31 badges for various things
|
||||||
|
|
||||||
|
You can right-click any of these and either save or copy-link to use these badges on your site or profile.
|
||||||
|
|
||||||
|
### Myself
|
||||||
|
|
||||||
|
For adding to your site or profile.
|
||||||
|
|
||||||
|
Pending... Need to draw some up.
|
||||||
|
|
||||||
|
### LGBTQIA+
|
||||||
|
|
||||||
|
Very gay badges, incoming :3
|
||||||
|
(More to come, I'm still drawing them)
|
||||||
|
|
||||||
|
#### Identity
|
||||||
|
|
||||||
|
- Umbrellas
|
||||||
|
|
||||||
|
> [![Transgender](/badges/transgender.gif)](https://en.wikipedia.org/wiki/Transgender)
|
||||||
|
> [![Nonbinary](/badges/nonbinary.gif)](https://en.wikipedia.org/wiki/Non-binary)
|
||||||
|
|
||||||
|
- Specific Identities
|
||||||
|
|
||||||
|
> [![Transfem](/badges/transfem.gif)](https://en.wikipedia.org/wiki/Trans_woman)
|
||||||
|
> [![Transmasc](/badges/transmasc.gif)](https://en.wikipedia.org/wiki/Trans_man)
|
||||||
|
|
||||||
|
### Miscellaneous
|
||||||
|
|
BIN
public/favicon.ico
Normal file
BIN
public/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.2 KiB |
1
public/robots.txt
Normal file
1
public/robots.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
|
3
server/tsconfig.json
Normal file
3
server/tsconfig.json
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"extends": "../.nuxt/tsconfig.server.json"
|
||||||
|
}
|
30
tailwind.config.js
Normal file
30
tailwind.config.js
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
/** @type {import('tailwindcss').Config} */
|
||||||
|
export default {
|
||||||
|
content: [
|
||||||
|
"./components/**/*.{js,vue,ts}",
|
||||||
|
"./layouts/**/*.vue",
|
||||||
|
"./pages/**/*.vue",
|
||||||
|
"./plugins/**/*.{js,ts}",
|
||||||
|
"./app.vue",
|
||||||
|
"./error.vue",
|
||||||
|
],
|
||||||
|
theme: {
|
||||||
|
extend: {
|
||||||
|
keyframes: {
|
||||||
|
appear: {
|
||||||
|
"0%": {
|
||||||
|
opacity: "0",
|
||||||
|
},
|
||||||
|
"100%": {
|
||||||
|
opacity: "1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
animation: {
|
||||||
|
appear: "appear 0.5s ease-in-out",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
plugins: [],
|
||||||
|
}
|
||||||
|
|
4
tsconfig.json
Normal file
4
tsconfig.json
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
// https://nuxt.com/docs/guide/concepts/typescript
|
||||||
|
"extends": "./.nuxt/tsconfig.json"
|
||||||
|
}
|
80
utils/track_posts.sh
Normal file
80
utils/track_posts.sh
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# This is meant to track the contents of /public/blog/*.md
|
||||||
|
# to maintain an up-to-date list of blog posts.
|
||||||
|
#
|
||||||
|
# It outputs JSON to stdout:
|
||||||
|
# Given a file /public/blog/2019-01-01-foo-bar.md of contents:
|
||||||
|
#
|
||||||
|
# ---
|
||||||
|
# title: Foo Bar
|
||||||
|
# date: 2019-01-01
|
||||||
|
# arbitrary_key: arbitrary_value
|
||||||
|
# ---
|
||||||
|
# # Foo Bar
|
||||||
|
#
|
||||||
|
# it will output:
|
||||||
|
# {
|
||||||
|
# posts: [
|
||||||
|
# {
|
||||||
|
# id: "2019-01-01-foo-bar",
|
||||||
|
# title: "Foo Bar",
|
||||||
|
# date: "2019-01-01",
|
||||||
|
# arbitrary_key: "arbitrary_value",
|
||||||
|
# url: "/blog/2019-01-01-foo-bar"
|
||||||
|
# }
|
||||||
|
# ]
|
||||||
|
# }
|
||||||
|
|
||||||
|
# It should also read the YAML Front Matter of each post
|
||||||
|
# and place all the keys in the JSON output.
|
||||||
|
|
||||||
|
# The script should be run from the root of the project.
|
||||||
|
|
||||||
|
# SCRIPT ENTRY
|
||||||
|
echo "{"
|
||||||
|
echo " \"posts\": ["
|
||||||
|
|
||||||
|
# Front-Matter Extraction (procedure)
|
||||||
|
# Given data, extract the YAML Front Matter header
|
||||||
|
# and output it as JSON.
|
||||||
|
extract_front_matter() {
|
||||||
|
local data="$1"
|
||||||
|
local front_matter=$(echo "$data" | sed -n '/^---/,/^---/p')
|
||||||
|
echo "$front_matter" | sed '1d;$d' | sed 's/^/ "/' | sed 's/: /": "/' | sed 's/$/"/' | tr '\n' ',' | sed 's/,$//' | sed 's/"tags": "\[\(.*\)\]"/"tags": \[\1\]/g' | sed "s/'/\"/g"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Find files via Regex
|
||||||
|
# Find all files in /public/blog/*.md
|
||||||
|
# Process and extract the front matter of each file.
|
||||||
|
# Output the JSON representation of the front matter.
|
||||||
|
extract_files() {
|
||||||
|
local files=$(find public/blog -type f -name "*.md")
|
||||||
|
for file in $files; do
|
||||||
|
# Enter, create {} for each file
|
||||||
|
echo " {"
|
||||||
|
|
||||||
|
echo " \"metadata\": {"
|
||||||
|
|
||||||
|
local data=$(cat $file)
|
||||||
|
local front_matter=$(extract_front_matter "$data")
|
||||||
|
echo "$front_matter"
|
||||||
|
|
||||||
|
echo " },"
|
||||||
|
|
||||||
|
# Add the id and url
|
||||||
|
local id=$(echo "$file" | sed 's/public\/blog\///' | sed 's/\.md//')
|
||||||
|
echo " \"id\": \"$id\","
|
||||||
|
echo " \"url\": \"/blog/$id.md\""
|
||||||
|
|
||||||
|
# Exit, close {} for each file
|
||||||
|
echo " },"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# Process all files
|
||||||
|
extract_files | sed '$s/,$//'
|
||||||
|
|
||||||
|
# SCRIPT EXIT
|
||||||
|
echo " ]"
|
||||||
|
echo "}"
|
Loading…
Add table
Reference in a new issue