Transform site to meet specifications
All checks were successful
Build / build (push) Successful in 57s

This commit is contained in:
Kevin Kandlbinder 2023-05-06 20:40:26 +02:00
parent 6609aed6e1
commit 0e93b591aa
Signed by: kevin
GPG key ID: 1460B586646E180D
9 changed files with 25 additions and 510 deletions

View file

@ -1,82 +0,0 @@
import Secrets from '$lib/server/secrets';
import type { RequestHandler } from './$types';
import GhostContentAPI from '@tryghost/content-api';
import { Feed } from 'feed';
import { DateTime } from 'luxon';
import { error } from '@sveltejs/kit';
export const trailingSlash = 'never';
export const prerender = true;
export const GET: RequestHandler = async (request) => {
//const siteBase = `${request.url.protocol}//${request.url.host}/`
const siteBase = `https://public-spaces-preview.pages.dev/`; // TODO: Change!
const api = new GhostContentAPI({
url: Secrets.ghost.url,
key: Secrets.ghost.key,
version: 'v5.0'
});
const posts = await api.posts.browse({
limit: 100,
include: ['authors', 'tags']
});
const feed = new Feed({
title: 'Public Spaces e.V.',
generator: 'Public Spaces e.V. Web',
description: 'Die neusten Beiträge von Public Spaces e.V.',
language: 'de-DE',
link: siteBase,
feedLinks: {
rss: `${siteBase}posts.rss`,
json: `${siteBase}posts.json`,
atom: `${siteBase}posts.atom`
},
id: siteBase,
copyright: ''
});
posts.forEach((post) => {
const date = DateTime.fromISO(post.updated_at || post.published_at || post.created_at || '');
const datePublished = DateTime.fromISO(post.published_at || post.created_at || '');
feed.addItem({
id: `${siteBase}post/${post.slug}`,
title: post.title || '',
link: `${siteBase}post/${post.slug}`,
date: date.toJSDate(),
published: datePublished.toJSDate(),
description: post.excerpt || '',
content: post.html || undefined,
author: post.authors?.map((author) => {
return {
name: author.name
};
})
});
});
switch (request.params.format) {
case 'rss':
return new Response(feed.rss2(), {
headers: {
'Content-Type': 'application/rss+xml'
}
});
case 'atom':
return new Response(feed.atom1(), {
headers: {
'Content-Type': 'application/atom+xml'
}
});
case 'json':
return new Response(feed.json1(), {
headers: {
'Content-Type': 'application/feed+json'
}
});
}
throw error(404, 'Ungültiges Format');
};

View file

@ -25,24 +25,30 @@
</a>
</div>
<div class={'offscreen-nav' + (menuOpen ? ' active' : '')}>
<a
<!--<a
href="/posts"
on:click={() => {
menuOpen = false;
}}>Beiträge</a
>
<a
>-->
<!--<a
href="/about"
on:click={() => {
menuOpen = false;
}}>Über Uns</a
>
>-->
<a
href="/contact"
on:click={() => {
menuOpen = false;
}}>Kontakt</a
>
<a
href="/donate"
on:click={() => {
menuOpen = false;
}}>Spenden</a
>
</div>
<div class="offscreen-nav-button">
<button
@ -68,33 +74,15 @@
<div class="primary-links">
<a href="/imprint">Impressum</a>
<a href="/data_protection">Datenschutz</a>
<a href="/disclaimer">Disclaimer</a>
<a href="/statute">Satzung</a>
</div>
<div class="border" />
<!--<div class="border" />
<div class="socials">
<!--<a
href="https://twitter.com/TODO"
target="_blank"
rel="noreferrer"
title="Twitter"
>
{@html siTwitter.svg}
<span class="sr-only">Twitter @TODO</span>
</a>
<a
href="https://t.me/TODO"
target="_blank"
rel="noreferrer"
title="Telegram"
>
{@html siTelegram.svg}
<span class="sr-only">Telegram @TODO</span>
</a>-->
</div>
<div class="border" />
<div class="supporters">
<span class="title">Unterstützer des Vereins</span>
</div>
</div>-->
</div>
<div class="copy-notice">
CC-BY-4.0 {new Date().getFullYear()}, Public Spaces e.V.
@ -122,7 +110,8 @@
.grid {
grid-column: wide-start/wide-end;
display: grid;
grid-template-columns: 1fr 1px 1fr 1px 1fr;
//grid-template-columns: 1fr 1px 1fr 1px 1fr;
grid-template-columns: 1fr;
gap: var(--gap);
@media (max-width: 700px) {

View file

@ -14,9 +14,9 @@ export const load: PageServerLoad = async () => {
include: ['authors', 'tags']
});
const about = await api.pages.read({
/*const about = await api.pages.read({
slug: 'about'
});
});*/
return { posts, about };
return { posts /*, about*/ };
};

View file

@ -1,11 +1,11 @@
<script lang="ts">
import type { PageData } from './$types';
import { ChevronRight } from 'lucide-svelte';
//import type { PageData } from './$types';
//import { ChevronRight } from 'lucide-svelte';
import Logo from '../assets/logo/LOGO-public-spaces.svg';
import HWFLogo from '../assets/logo/LOGO-hamburg-werbefrei.svg';
import BWFLogo from '../assets/logo/LOGO-berlin-werbefrei.svg';
export let data: PageData;
//export let data: PageData;
</script>
<svelte:head>
@ -48,9 +48,9 @@
</a>
</div>
<a href="/about" class="more-cta">Mehr über uns <ChevronRight /></a>
<!--<a href="/about" class="more-cta">Mehr über uns <ChevronRight /></a>-->
<hr />
<!--<hr />
<h2>Neuste Beiträge</h2>
@ -73,8 +73,7 @@
{/each}
</div>
<a href="/posts" class="kg-btn">Alle Beiträge sehen</a>
<!--<a href="/about" class="more-cta">Alle Beiträge <ChevronRight/></a>-->
<a href="/posts" class="kg-btn">Alle Beiträge sehen</a>-->
</div>
<style lang="scss">

View file

@ -1,18 +0,0 @@
import type { PageServerLoad } from './$types';
import GhostContentAPI from '@tryghost/content-api';
import Secrets from '$lib/server/secrets';
export const load: PageServerLoad = async () => {
const api = new GhostContentAPI({
url: Secrets.ghost.url,
key: Secrets.ghost.key,
version: 'v5.0'
});
const posts = await api.posts.browse({
limit: 100,
include: ['authors', 'tags']
});
return { posts };
};

View file

@ -1,127 +0,0 @@
<script lang="ts">
import type { PageData } from './$types';
import { DateTime } from 'luxon';
export let data: PageData;
</script>
<svelte:head>
<title>Beiträge | Public Spaces e.V.</title>
<meta name="title" content={'Beiträge'} />
<meta
name="description"
content={'Lies die neusten Beiträge von Public Spaces e.V. Hier findest du Pressemitteilungen, Artikel und andere Inhalte.'}
/>
</svelte:head>
<div class="container">
<h1>Beiträge</h1>
<div class="posts">
{#each data.posts as post}
<a href={`/posts/` + post.slug}>
<div class="feature-image">
{#if post.feature_image}
<img
src={post.feature_image}
alt={post.feature_image_alt ||
post.feature_image_caption ||
post.title ||
'Feature Image'}
/>
{/if}
</div>
<div class="details">
<span class="title">{post.title}</span>
<span class="meta">
{#each post.authors || [] as author, i}
{i > 0 ? ' & ' : ''}<span>{author.name}</span>
{/each} &middot;
<span
>{DateTime.fromISO(post.published_at || post.created_at || '2001-11-03')
.setLocale('de-DE')
.toLocaleString(DateTime.DATE_FULL)}</span
>
&middot;
<span
>Ca. {post.reading_time || post.reading_time === 0
? Math.max(1, post.reading_time) + ' Min.'
: 'Unbekannte'} Lesezeit</span
>
</span>
{#if post.custom_excerpt || post.excerpt}
<p class="excerpt">
{(post.custom_excerpt || post.excerpt)?.replaceAll('\n', ' ')}
</p>
{/if}
</div>
</a>
{/each}
</div>
</div>
<style lang="scss">
.container {
@include contentGrid;
}
.posts {
> a {
display: flex;
gap: var(--gap);
padding: var(--gap) 0;
color: inherit;
text-decoration: none;
position: relative;
&::after {
position: absolute;
content: '';
display: block;
width: 90%;
margin: 0 auto;
bottom: 0;
left: 50%;
transform: translate(-50%, 0);
border-bottom: thin solid var(--color-border);
}
> .feature-image {
--size: 150px;
width: var(--size);
height: var(--size);
flex-shrink: 0;
> img {
width: 100%;
height: 100%;
object-fit: cover;
object-position: center;
}
}
> .details {
display: flex;
flex-direction: column;
> .title {
font-size: 1.6em;
font-weight: 600;
color: var(--color-accent);
}
> .meta {
opacity: 0.75;
margin-top: 5px;
font-weight: 300;
}
> .excerpt {
margin-bottom: 0;
}
}
}
}
</style>

View file

@ -1,29 +0,0 @@
import type { PageServerLoad } from './$types';
import GhostContentAPI from '@tryghost/content-api';
import Secrets from '$lib/server/secrets';
import { error } from '@sveltejs/kit';
export const load: PageServerLoad = async ({ params }) => {
const api = new GhostContentAPI({
url: Secrets.ghost.url,
key: Secrets.ghost.key,
version: 'v5.0'
});
let post = null;
try {
post = await api.posts.read(
{
slug: params.slug
},
{ include: ['tags', 'authors'] }
);
} catch (e) {
throw error(404, 'Artikel Nicht Gefunden');
}
return {
post
};
};

View file

@ -1,217 +0,0 @@
<script lang="ts">
import type { PageData } from './$types';
import { DateTime } from 'luxon';
import { Globe } from 'lucide-svelte';
import { siTwitter } from 'simple-icons';
export let data: PageData;
$: publishTime = DateTime.fromISO(data.post.published_at || data.post.created_at || '2001-11-03');
</script>
<svelte:head>
<title>{data.post.title}</title>
<meta name="title" content={data.post.meta_title || data.post.title} />
<meta
name="description"
content={data.post.meta_description || data.post.custom_excerpt || data.post.excerpt}
/>
<meta name="twitter:card" content="summary" />
<meta name="twitter:site" content="@todo" />
<!-- TODO: Change me. -->
<meta
name="twitter:title"
content={data.post.twitter_title || data.post.meta_title || data.post.title}
/>
<meta
name="twitter:description"
content={data.post.twitter_description ||
data.post.meta_description ||
data.post.custom_excerpt ||
data.post.excerpt}
/>
<meta name="twitter:image" content={data.post.twitter_image || data.post.feature_image} />
<meta property="og:type" content="article" />
<meta
property="og:title"
content={data.post.og_title || data.post.meta_title || data.post.title}
/>
<meta
property="og:description"
content={data.post.og_description ||
data.post.meta_description ||
data.post.custom_excerpt ||
data.post.excerpt}
/>
<meta
property="og:image"
content={data.post.og_image || data.post.twitter_image || data.post.feature_image}
/>
<meta property="article:published_time" content={data.post.published_at} />
{#if data.post.updated_at}
<meta property="article:modified_time" content={data.post.updated_at} />
{/if}
{#if data.post.primary_tag}
<meta
property="article:section"
content={data.post.primary_tag.og_title || data.post.primary_tag.name}
/>
{/if}
{@html `<script type="application/ld+json">${JSON.stringify({
'@context': 'https://schema.org',
'@type': 'Article',
headline: data.post.title,
image: data.post.feature_image,
datePublished: data.post.published_at,
dateModified: data.post.updated_at,
author: data.post.authors?.map((author) => {
return {
'@type': 'Person',
name: author.name
};
})
})}</script>`}
</svelte:head>
<div class="container">
<div class="header">
<h1>{data.post?.title}</h1>
<span class="meta">
<span>{publishTime.setLocale('de-DE').toLocaleString(DateTime.DATE_FULL)}</span> &middot;
<span
>Ca. {data.post.reading_time || data.post.reading_time === 0
? Math.max(1, data.post.reading_time) + ' Min.'
: 'Unbekannte'} Lesezeit</span
>
&middot;
<span>
{#each data.post.tags || [] as tag, i}
{i > 0 ? ', ' : ''}<span>{tag.name}</span><!--href={`/posts/` + tag.slug}-->
{/each}
</span>
</span>
{#if data.post.feature_image}
<div class="feature-image">
<figure>
<img src={data.post.feature_image} alt={data.post.feature_image_alt || 'Feature Image'} />
<figcaption>{@html data.post.feature_image_caption || ''}</figcaption>
</figure>
</div>
{/if}
</div>
<div class="article">
{@html data.post?.html}
<!--<pre>{JSON.stringify(data.post, null, 2)}</pre>-->
</div>
<div class="authors">
<hr />
{#each data.post.authors || [] as author}
<div class="author">
<div class="pic">
{#if author.profile_image}
<img src={author.profile_image} alt={'Profilbild von ' + author.name} />
{/if}
{#if !author.profile_image}
<div class="photo-placeholder" />
{/if}
</div>
<div class="meta">
<span class="name">{author.name}</span>
<p>{author.bio || ''}</p>
<div class="links">
{#if author.website}
<a href={author.website}><Globe /> {new URL(author.website).host}</a>
{/if}
{#if author.twitter}
<a href={'https://twitter.com/' + author.twitter} class="twitter"
>{@html siTwitter.svg} {author.twitter}</a
>
{/if}
</div>
</div>
</div>
{/each}
</div>
</div>
<style lang="scss">
.article {
:global {
@include ghostContentContainer;
}
}
.authors {
@include contentGrid;
.author {
display: flex;
gap: var(--gap);
margin-bottom: var(--gap);
> * {
flex-grow: 0;
flex-shrink: 0;
}
.pic {
width: 125px;
img,
.photo-placeholder {
width: 125px;
height: 125px;
object-fit: cover;
object-position: center;
background-color: var(--color-dark-surface);
}
}
.meta {
width: 0;
flex-grow: 1;
padding: var(--padding);
.name {
font-size: 2em;
font-weight: 700;
}
p {
width: 100%;
}
.links {
display: flex;
gap: var(--gap);
a {
display: flex;
justify-content: center;
align-items: center;
:global(svg) {
width: 25px;
height: 25px;
margin-right: var(--padding);
}
&.twitter {
:global(svg) {
fill: currentColor;
}
}
}
}
}
}
}
.header {
@include articleHeader;
}
</style>

View file

@ -23,7 +23,7 @@ const config = {
// See https://kit.svelte.dev/docs/adapters for more information about adapters.
adapter: adapter({}),
prerender: {
entries: ['*', '/posts.rss', '/posts.atom', '/posts.json']
entries: ['*']
}
}
};