Transform site to meet specifications
All checks were successful
Build / build (push) Successful in 57s
All checks were successful
Build / build (push) Successful in 57s
This commit is contained in:
parent
6609aed6e1
commit
0e93b591aa
9 changed files with 25 additions and 510 deletions
|
@ -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');
|
||||
};
|
|
@ -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) {
|
||||
|
|
|
@ -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*/ };
|
||||
};
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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 };
|
||||
};
|
|
@ -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} ·
|
||||
<span
|
||||
>{DateTime.fromISO(post.published_at || post.created_at || '2001-11-03')
|
||||
.setLocale('de-DE')
|
||||
.toLocaleString(DateTime.DATE_FULL)}</span
|
||||
>
|
||||
·
|
||||
<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>
|
|
@ -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
|
||||
};
|
||||
};
|
|
@ -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> ·
|
||||
<span
|
||||
>Ca. {data.post.reading_time || data.post.reading_time === 0
|
||||
? Math.max(1, data.post.reading_time) + ' Min.'
|
||||
: 'Unbekannte'} Lesezeit</span
|
||||
>
|
||||
·
|
||||
<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>
|
|
@ -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: ['*']
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
Loading…
Add table
Reference in a new issue