refactor: use markdown layouts
This commit is contained in:
@@ -4,7 +4,6 @@ import sitemap from "@astrojs/sitemap";
|
|||||||
import Icons from 'unplugin-icons/vite'
|
import Icons from 'unplugin-icons/vite'
|
||||||
import mdx from '@astrojs/mdx';
|
import mdx from '@astrojs/mdx';
|
||||||
import glsl from 'vite-plugin-glsl';
|
import glsl from 'vite-plugin-glsl';
|
||||||
import remarkToc from 'remark-toc'
|
|
||||||
|
|
||||||
import svelte from "@astrojs/svelte";
|
import svelte from "@astrojs/svelte";
|
||||||
import UnoCSS from 'unocss/astro'
|
import UnoCSS from 'unocss/astro'
|
||||||
@@ -15,6 +14,15 @@ const locales = {
|
|||||||
de: "de",
|
de: "de",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const DEFAULT_LAYOUT = '@layouts/Post.astro';
|
||||||
|
|
||||||
|
function setDefaultLayout() {
|
||||||
|
return function (_, file) {
|
||||||
|
const { frontmatter } = file.data.astro;
|
||||||
|
if (!frontmatter.layout) frontmatter.layout = DEFAULT_LAYOUT;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// https://astro.build/config
|
// https://astro.build/config
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
site: "https://max-richter.dev",
|
site: "https://max-richter.dev",
|
||||||
@@ -31,12 +39,11 @@ export default defineConfig({
|
|||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
markdown: {
|
||||||
|
remarkPlugins: [setDefaultLayout]
|
||||||
|
},
|
||||||
integrations: [
|
integrations: [
|
||||||
mdx({
|
mdx(),
|
||||||
remarkPlugins: [
|
|
||||||
remarkToc
|
|
||||||
]
|
|
||||||
}),
|
|
||||||
svelte(),
|
svelte(),
|
||||||
UnoCSS({
|
UnoCSS({
|
||||||
injectReset: true
|
injectReset: true
|
||||||
|
|||||||
@@ -17,6 +17,10 @@
|
|||||||
"astro": "^4.5.5",
|
"astro": "^4.5.5",
|
||||||
"astro-i18n-aut": "^0.7.0",
|
"astro-i18n-aut": "^0.7.0",
|
||||||
"astro-imagetools": "^0.9.0",
|
"astro-imagetools": "^0.9.0",
|
||||||
|
"rehype-autolink-headings": "^7.1.0",
|
||||||
|
"rehype-slug": "^6.0.0",
|
||||||
|
"rehype-stringify": "^10.0.0",
|
||||||
|
"rehype-toc": "^3.0.2",
|
||||||
"remark-toc": "^9.0.0",
|
"remark-toc": "^9.0.0",
|
||||||
"svelte": "^4.2.12",
|
"svelte": "^4.2.12",
|
||||||
"svelte-gestures": "^4.0.0",
|
"svelte-gestures": "^4.0.0",
|
||||||
|
|||||||
57
pnpm-lock.yaml
generated
57
pnpm-lock.yaml
generated
@@ -26,6 +26,18 @@ dependencies:
|
|||||||
astro-imagetools:
|
astro-imagetools:
|
||||||
specifier: ^0.9.0
|
specifier: ^0.9.0
|
||||||
version: 0.9.0(astro@4.5.5)
|
version: 0.9.0(astro@4.5.5)
|
||||||
|
rehype-autolink-headings:
|
||||||
|
specifier: ^7.1.0
|
||||||
|
version: 7.1.0
|
||||||
|
rehype-slug:
|
||||||
|
specifier: ^6.0.0
|
||||||
|
version: 6.0.0
|
||||||
|
rehype-stringify:
|
||||||
|
specifier: ^10.0.0
|
||||||
|
version: 10.0.0
|
||||||
|
rehype-toc:
|
||||||
|
specifier: ^3.0.2
|
||||||
|
version: 3.0.2
|
||||||
remark-toc:
|
remark-toc:
|
||||||
specifier: ^9.0.0
|
specifier: ^9.0.0
|
||||||
version: 9.0.0
|
version: 9.0.0
|
||||||
@@ -1609,6 +1621,11 @@ packages:
|
|||||||
'@jridgewell/resolve-uri': 3.1.2
|
'@jridgewell/resolve-uri': 3.1.2
|
||||||
'@jridgewell/sourcemap-codec': 1.4.15
|
'@jridgewell/sourcemap-codec': 1.4.15
|
||||||
|
|
||||||
|
/@jsdevtools/rehype-toc@3.0.2:
|
||||||
|
resolution: {integrity: sha512-n5JEf16Wr4mdkRMZ8wMP/wN9/sHmTjRPbouXjJH371mZ2LEGDl72t8tEsMRNFerQN/QJtivOxqK1frdGa4QK5Q==}
|
||||||
|
engines: {node: '>=10'}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/@mdx-js/mdx@3.0.1:
|
/@mdx-js/mdx@3.0.1:
|
||||||
resolution: {integrity: sha512-eIQ4QTrOWyL3LWEe/bu6Taqzq2HQvHcyTMaOrI95P2/LmJE7AsfPfgJGuFLPVqBUE1BC1rik3VIhU+s9u72arA==}
|
resolution: {integrity: sha512-eIQ4QTrOWyL3LWEe/bu6Taqzq2HQvHcyTMaOrI95P2/LmJE7AsfPfgJGuFLPVqBUE1BC1rik3VIhU+s9u72arA==}
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -3294,6 +3311,12 @@ packages:
|
|||||||
vfile-location: 5.0.2
|
vfile-location: 5.0.2
|
||||||
web-namespaces: 2.0.1
|
web-namespaces: 2.0.1
|
||||||
|
|
||||||
|
/hast-util-heading-rank@3.0.0:
|
||||||
|
resolution: {integrity: sha512-EJKb8oMUXVHcWZTDepnr+WNbfnXKFNf9duMesmr4S8SXTJBJ9M4Yok08pu9vxdJwdlGRhVumk9mEhkEvKGifwA==}
|
||||||
|
dependencies:
|
||||||
|
'@types/hast': 3.0.4
|
||||||
|
dev: false
|
||||||
|
|
||||||
/hast-util-is-element@3.0.0:
|
/hast-util-is-element@3.0.0:
|
||||||
resolution: {integrity: sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g==}
|
resolution: {integrity: sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g==}
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -3393,6 +3416,12 @@ packages:
|
|||||||
web-namespaces: 2.0.1
|
web-namespaces: 2.0.1
|
||||||
zwitch: 2.0.4
|
zwitch: 2.0.4
|
||||||
|
|
||||||
|
/hast-util-to-string@3.0.0:
|
||||||
|
resolution: {integrity: sha512-OGkAxX1Ua3cbcW6EJ5pT/tslVb90uViVkcJ4ZZIMW/R33DX/AkcJcRrPebPwJkHYwlDHXz4aIwvAAaAdtrACFA==}
|
||||||
|
dependencies:
|
||||||
|
'@types/hast': 3.0.4
|
||||||
|
dev: false
|
||||||
|
|
||||||
/hast-util-to-text@4.0.0:
|
/hast-util-to-text@4.0.0:
|
||||||
resolution: {integrity: sha512-EWiE1FSArNBPUo1cKWtzqgnuRQwEeQbQtnFJRYV1hb1BWDgrAlBU0ExptvZMM/KSA82cDpm2sFGf3Dmc5Mza3w==}
|
resolution: {integrity: sha512-EWiE1FSArNBPUo1cKWtzqgnuRQwEeQbQtnFJRYV1hb1BWDgrAlBU0ExptvZMM/KSA82cDpm2sFGf3Dmc5Mza3w==}
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -4976,6 +5005,17 @@ packages:
|
|||||||
resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==}
|
resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/rehype-autolink-headings@7.1.0:
|
||||||
|
resolution: {integrity: sha512-rItO/pSdvnvsP4QRB1pmPiNHUskikqtPojZKJPPPAVx9Hj8i8TwMBhofrrAYRhYOOBZH9tgmG5lPqDLuIWPWmw==}
|
||||||
|
dependencies:
|
||||||
|
'@types/hast': 3.0.4
|
||||||
|
'@ungap/structured-clone': 1.2.0
|
||||||
|
hast-util-heading-rank: 3.0.0
|
||||||
|
hast-util-is-element: 3.0.0
|
||||||
|
unified: 11.0.4
|
||||||
|
unist-util-visit: 5.0.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
/rehype-parse@9.0.0:
|
/rehype-parse@9.0.0:
|
||||||
resolution: {integrity: sha512-WG7nfvmWWkCR++KEkZevZb/uw41E8TsH4DsY9UxsTbIXCVGbAs4S+r8FrQ+OtH5EEQAs+5UxKC42VinkmpA1Yw==}
|
resolution: {integrity: sha512-WG7nfvmWWkCR++KEkZevZb/uw41E8TsH4DsY9UxsTbIXCVGbAs4S+r8FrQ+OtH5EEQAs+5UxKC42VinkmpA1Yw==}
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -4990,6 +5030,16 @@ packages:
|
|||||||
hast-util-raw: 9.0.2
|
hast-util-raw: 9.0.2
|
||||||
vfile: 6.0.1
|
vfile: 6.0.1
|
||||||
|
|
||||||
|
/rehype-slug@6.0.0:
|
||||||
|
resolution: {integrity: sha512-lWyvf/jwu+oS5+hL5eClVd3hNdmwM1kAC0BUvEGD19pajQMIzcNUd/k9GsfQ+FfECvX+JE+e9/btsKH0EjJT6A==}
|
||||||
|
dependencies:
|
||||||
|
'@types/hast': 3.0.4
|
||||||
|
github-slugger: 2.0.0
|
||||||
|
hast-util-heading-rank: 3.0.0
|
||||||
|
hast-util-to-string: 3.0.0
|
||||||
|
unist-util-visit: 5.0.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
/rehype-stringify@10.0.0:
|
/rehype-stringify@10.0.0:
|
||||||
resolution: {integrity: sha512-1TX1i048LooI9QoecrXy7nGFFbFSufxVRAfc6Y9YMRAi56l+oB0zP51mLSV312uRuvVLPV1opSlJmslozR1XHQ==}
|
resolution: {integrity: sha512-1TX1i048LooI9QoecrXy7nGFFbFSufxVRAfc6Y9YMRAi56l+oB0zP51mLSV312uRuvVLPV1opSlJmslozR1XHQ==}
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -4997,6 +5047,13 @@ packages:
|
|||||||
hast-util-to-html: 9.0.0
|
hast-util-to-html: 9.0.0
|
||||||
unified: 11.0.4
|
unified: 11.0.4
|
||||||
|
|
||||||
|
/rehype-toc@3.0.2:
|
||||||
|
resolution: {integrity: sha512-DMt376+4i1KJGgHJL7Ezd65qKkJ7Eqp6JSB47BJ90ReBrohI9ufrornArM6f4oJjP2E2DVZZHufWucv/9t7GUQ==}
|
||||||
|
engines: {node: '>=10'}
|
||||||
|
dependencies:
|
||||||
|
'@jsdevtools/rehype-toc': 3.0.2
|
||||||
|
dev: false
|
||||||
|
|
||||||
/rehype@13.0.1:
|
/rehype@13.0.1:
|
||||||
resolution: {integrity: sha512-AcSLS2mItY+0fYu9xKxOu1LhUZeBZZBx8//5HKzF+0XP+eP8+6a5MXn2+DW2kfXR6Dtp1FEXMVrjyKAcvcU8vg==}
|
resolution: {integrity: sha512-AcSLS2mItY+0fYu9xKxOu1LhUZeBZZBx8//5HKzF+0XP+eP8+6a5MXn2+DW2kfXR6Dtp1FEXMVrjyKAcvcU8vg==}
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|||||||
@@ -16,14 +16,24 @@ function translatePath(lang: string) {
|
|||||||
return `/${[lang, ...split].join("/")}`;
|
return `/${[lang, ...split].join("/")}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const flags = {
|
||||||
|
de: "🇩🇪",
|
||||||
|
en: "🇬🇧",
|
||||||
|
};
|
||||||
|
|
||||||
const t = useTranslations(Astro.url);
|
const t = useTranslations(Astro.url);
|
||||||
---
|
---
|
||||||
|
|
||||||
<ul>
|
<ul class="flex items-center gap-4">
|
||||||
{
|
{
|
||||||
Object.entries(locales).map(([lang, label]) => (
|
Object.entries(locales).map(([lang, label]) => (
|
||||||
<li>
|
<li>
|
||||||
<a href={translatePath(lang)} data-astro-prefetch>
|
<a
|
||||||
|
class="flex gap-2 items-center"
|
||||||
|
href={translatePath(lang)}
|
||||||
|
data-astro-prefetch
|
||||||
|
>
|
||||||
|
<span class="text-xs">{flags[label as keyof typeof flags]}</span>
|
||||||
{t(label as "de")}
|
{t(label as "de")}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|||||||
BIN
src/content/photos/sestri-levante/index.en.mdx
(Stored with Git LFS)
Normal file
BIN
src/content/photos/sestri-levante/index.en.mdx
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
src/content/photos/sestri-levante/index.mdx
(Stored with Git LFS)
BIN
src/content/photos/sestri-levante/index.mdx
(Stored with Git LFS)
Binary file not shown.
@@ -6,6 +6,7 @@ featured: true
|
|||||||
links: [["website", "https://plant.max-richter.dev"], ["git", "https://github.com/jim-fx/plantarium"]]
|
links: [["website", "https://plant.max-richter.dev"], ["git", "https://github.com/jim-fx/plantarium"]]
|
||||||
tags: ["Web", "3D", "Svelte", "Node-Systeme"]
|
tags: ["Web", "3D", "Svelte", "Node-Systeme"]
|
||||||
draft: false
|
draft: false
|
||||||
|
toc: true
|
||||||
---
|
---
|
||||||
|
|
||||||
# Einführung
|
# Einführung
|
||||||
|
|||||||
@@ -65,7 +65,9 @@ const { title, width = "compact" } = Astro.props;
|
|||||||
--neutral-000: #f1f1f4;
|
--neutral-000: #f1f1f4;
|
||||||
--fill: #cb5a5a;
|
--fill: #cb5a5a;
|
||||||
|
|
||||||
|
--border-radius-sm: 10px;
|
||||||
--border-radius-md: 20px;
|
--border-radius-md: 20px;
|
||||||
|
--border-radius-lg: 30px;
|
||||||
|
|
||||||
--spacing-sm: 10px;
|
--spacing-sm: 10px;
|
||||||
--spacing-md: 20px;
|
--spacing-md: 20px;
|
||||||
@@ -99,15 +101,6 @@ const { title, width = "compact" } = Astro.props;
|
|||||||
--text: var(--neutral-100);
|
--text: var(--neutral-100);
|
||||||
--text-light: white;
|
--text-light: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* .dark .icon-tabler-sun, */
|
|
||||||
/* .light .icon-tabler-moon { */
|
|
||||||
/* display: none; */
|
|
||||||
/* } */
|
|
||||||
/* .dark .icon-tabler-moon, */
|
|
||||||
/* .light .icon-tabler-sun { */
|
|
||||||
/* display: block; */
|
|
||||||
/* } */
|
|
||||||
</style>
|
</style>
|
||||||
<script>
|
<script>
|
||||||
(function () {
|
(function () {
|
||||||
@@ -130,7 +123,9 @@ const { title, width = "compact" } = Astro.props;
|
|||||||
<main id="main-content" class="flex flex-col mt-4xl gap-y-2xl">
|
<main id="main-content" class="flex flex-col mt-4xl gap-y-2xl">
|
||||||
<slot />
|
<slot />
|
||||||
</main>
|
</main>
|
||||||
|
<footer>
|
||||||
<LanguagePicker />
|
<LanguagePicker />
|
||||||
|
</footer>
|
||||||
<style>
|
<style>
|
||||||
.layout-compact {
|
.layout-compact {
|
||||||
max-width: 600px;
|
max-width: 600px;
|
||||||
|
|||||||
@@ -1,24 +1,31 @@
|
|||||||
---
|
---
|
||||||
import type { CollectionEntry } from "astro:content";
|
|
||||||
import Layout from "./Layout.astro";
|
import Layout from "./Layout.astro";
|
||||||
import { useTranslatedPath } from "@i18n/utils";
|
import { useTranslatedPath, useTranslations } from "@i18n/utils";
|
||||||
|
import type { MarkdownLayoutProps } from "astro";
|
||||||
|
|
||||||
type CustomProps = {
|
type Props = MarkdownLayoutProps<{
|
||||||
layout?: "normal" | "transparent";
|
title: string;
|
||||||
backlink?: string;
|
date: Date;
|
||||||
};
|
links?: string[][];
|
||||||
type Props = CollectionEntry<"blog" | "photos" | "videos" | "projects"> &
|
toc?: boolean;
|
||||||
CustomProps;
|
}>;
|
||||||
|
|
||||||
const { data, backlink = "/" } = Astro.props;
|
const { frontmatter } = Astro.props;
|
||||||
const { title, date, links, _layout } = data;
|
const t = useTranslations(Astro.url);
|
||||||
|
const { title, url, date: dateString, links, toc } = frontmatter;
|
||||||
|
const collection = url?.split("/")[2];
|
||||||
|
const date = new Date(dateString);
|
||||||
const path = useTranslatedPath(Astro.url);
|
const path = useTranslatedPath(Astro.url);
|
||||||
|
|
||||||
|
//@ts-ignore
|
||||||
|
const backlinkContent = t(`nav.${collection}`).toLowerCase();
|
||||||
---
|
---
|
||||||
|
|
||||||
<Layout title={title}>
|
<Layout title={title}>
|
||||||
<div class="top-info flex items-center place-content-between m-y-2">
|
<div class="top-info flex items-center place-content-between m-y-2">
|
||||||
<a class="flex items-center gap-1 opacity-50" href={path(backlink)}
|
<a class="flex items-center gap-1 opacity-50" href={path("/" + collection)}
|
||||||
><span class="i-tabler-arrow-left"></span> overview</a
|
><span class="i-tabler-arrow-left"></span>
|
||||||
|
{backlinkContent}</a
|
||||||
>
|
>
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -48,13 +55,11 @@ const path = useTranslatedPath(Astro.url);
|
|||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<article class={`layout-${_layout} flex flex-col gap-4`}>
|
<article class={`flex flex-col gap-4 ${toc ? "show-toc" : ""}`}>
|
||||||
<div class="mb-4 flex flex-col gap-1">
|
<div class="mb-4 flex flex-col gap-1">
|
||||||
<h1 class="text-4xl">
|
<h1 class="text-4xl">
|
||||||
{title}
|
{title}
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
<div class="toc"></div>
|
|
||||||
</div>
|
</div>
|
||||||
<slot />
|
<slot />
|
||||||
</article>
|
</article>
|
||||||
@@ -65,4 +70,32 @@ const path = useTranslatedPath(Astro.url);
|
|||||||
padding: 20px;
|
padding: 20px;
|
||||||
background: var(--background);
|
background: var(--background);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
article :global(picture) {
|
||||||
|
border-radius: var(--border-radius-sm);
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
article :global(.toc-post) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
article.show-toc :global(.toc-post) {
|
||||||
|
display: flex !important;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
article :global(.toc-post > ol ol) {
|
||||||
|
margin-left: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 1200px) {
|
||||||
|
:global(.toc-post) {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
height: 80vh;
|
||||||
|
left: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
---
|
---
|
||||||
import { getCollection } from "astro:content";
|
import { getCollection } from "astro:content";
|
||||||
import Post from "@layouts/Post.astro";
|
|
||||||
import { getLocale } from "astro-i18n-aut";
|
import { getLocale } from "astro-i18n-aut";
|
||||||
import { filterCollection, parseSlug } from "@i18n/utils";
|
import { filterCollection, parseSlug } from "@i18n/utils";
|
||||||
|
|
||||||
@@ -32,6 +31,4 @@ if (!page) {
|
|||||||
const { Content } = await page.render();
|
const { Content } = await page.render();
|
||||||
---
|
---
|
||||||
|
|
||||||
<Post {...page} backlink="/blog">
|
|
||||||
<Content />
|
<Content />
|
||||||
</Post>
|
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
---
|
---
|
||||||
import { getCollection } from "astro:content";
|
import { getCollection } from "astro:content";
|
||||||
import Post from "@layouts/Post.astro";
|
|
||||||
import { getLocale } from "astro-i18n-aut";
|
import { getLocale } from "astro-i18n-aut";
|
||||||
import { filterCollection, parseSlug } from "@i18n/utils";
|
import { filterCollection, parseSlug } from "@i18n/utils";
|
||||||
|
|
||||||
@@ -32,6 +31,4 @@ if (!page) {
|
|||||||
const { Content } = await page.render();
|
const { Content } = await page.render();
|
||||||
---
|
---
|
||||||
|
|
||||||
<Post {...page} backlink="/photos">
|
|
||||||
<Content />
|
<Content />
|
||||||
</Post>
|
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
---
|
---
|
||||||
import { getCollection } from "astro:content";
|
import { getCollection } from "astro:content";
|
||||||
import Post from "@layouts/Post.astro";
|
|
||||||
import { getLocale } from "astro-i18n-aut";
|
import { getLocale } from "astro-i18n-aut";
|
||||||
import { filterCollection, parseSlug } from "@i18n/utils";
|
import { filterCollection, parseSlug } from "@i18n/utils";
|
||||||
|
|
||||||
@@ -32,6 +31,4 @@ if (!page) {
|
|||||||
const { Content } = await page.render();
|
const { Content } = await page.render();
|
||||||
---
|
---
|
||||||
|
|
||||||
<Post {...page} backlink="/projects">
|
|
||||||
<Content />
|
<Content />
|
||||||
</Post>
|
|
||||||
|
|||||||
Reference in New Issue
Block a user