You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
230 lines
4.6 KiB
230 lines
4.6 KiB
<script context="module">
|
|
import markdown from "$/lib/blog.js";
|
|
import Markdown from "$/client/components/Markdown.svelte";
|
|
|
|
export const getPaths = () => {
|
|
// slug has to be present here to match [slug] directory
|
|
return markdown.load("rendered/posts");
|
|
}
|
|
|
|
export const getData = post => post;
|
|
</script>
|
|
|
|
<script>
|
|
import Layout from '$/rendered/Layout.svelte';
|
|
import IconImage from "$/client/components/IconImage.svelte";
|
|
import { og_base_host, twitter_user } from "$/client/config.js";
|
|
import SEOTricks from "$/client/components/SEOTricks.svelte";
|
|
|
|
export let metadata;
|
|
export let toc;
|
|
export let content;
|
|
export let slug;
|
|
|
|
let related = markdown.load("rendered/posts").slice(0, 4).map(p => p.metadata);
|
|
|
|
let og = {
|
|
"title": metadata.title, // title of the article
|
|
"description": metadata.summary, // description for inside preview
|
|
"url": `${ og_base_host }/blog/${ metadata.slug }/`, // URL to article
|
|
"type": "website", // not mentioned on linked in but needed
|
|
}
|
|
|
|
let twitter = {
|
|
"card": "summary", // must be summary, summary_large_image, app, player
|
|
"creator": twitter_user, // @username of content creator
|
|
"description": og.description, // max 200 chars
|
|
"site": "@lzsthw", // @username of site
|
|
"title": og.title,
|
|
}
|
|
|
|
if(metadata.image) {
|
|
og.image = `${og_base_host}/${metadata.image}`;
|
|
twitter.image = og.image;
|
|
}
|
|
</script>
|
|
|
|
<SEOTricks og={og} twitter={twitter} />
|
|
|
|
<style>
|
|
content {
|
|
overflow: auto;
|
|
padding-left: 5rem;
|
|
padding-right: 5rem;
|
|
display: flex;
|
|
font-size: 1.5rem;
|
|
flex-direction: column;
|
|
}
|
|
|
|
hero {
|
|
width: 100%;
|
|
}
|
|
|
|
hero.icon {
|
|
display: block;
|
|
}
|
|
|
|
hero.icon:hover div {
|
|
opacity: 0.2;
|
|
}
|
|
|
|
hero cover {
|
|
padding: 1rem;
|
|
font-size: clamp(1.5em, 2vw, 2em);
|
|
}
|
|
|
|
:global(content > h1) {
|
|
margin-top: 2rem;
|
|
margin-bottom: 2rem;
|
|
}
|
|
|
|
|
|
content info {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 1rem;
|
|
margin-top: 1rem;
|
|
}
|
|
|
|
posts {
|
|
display: grid;
|
|
grid-template-columns: repeat(2, 1fr);
|
|
gap: 1rem;
|
|
max-width: var(--width-content);
|
|
margin-bottom: 1rem;
|
|
}
|
|
|
|
posts card {
|
|
border: unset;
|
|
border-radius: unset;
|
|
}
|
|
|
|
posts card top {
|
|
max-height: 250px;
|
|
}
|
|
|
|
posts card middle {
|
|
padding: 1rem;
|
|
}
|
|
|
|
posts card bottom {
|
|
padding: 0.5rem;
|
|
}
|
|
|
|
tags {
|
|
display: flex;
|
|
margin-top: 1rem;
|
|
justify-content: space-between;
|
|
}
|
|
|
|
tags tag {
|
|
border-radius: 20px;
|
|
background-color: var(--value7);
|
|
color: var(--value3);
|
|
font-size: 0.8em;
|
|
padding-left: 0.3rem;
|
|
padding-right: 0.3rem;
|
|
}
|
|
|
|
tags info {
|
|
font-size: 0.8em;
|
|
color: var(--value3);
|
|
}
|
|
|
|
@media only screen and (min-width: 1285px) {
|
|
posts,
|
|
content,
|
|
hero {
|
|
width: var(--width-content);
|
|
}
|
|
}
|
|
|
|
@media only screen and (max-width: 900px) {
|
|
content {
|
|
overflow: auto;
|
|
padding-left: 0.5rem;
|
|
padding-right: 0.5rem;
|
|
display: flex;
|
|
font-size: 1.2rem;
|
|
flex-direction: column;
|
|
}
|
|
|
|
posts {
|
|
max-width: 90vw;
|
|
}
|
|
}
|
|
|
|
|
|
@media only screen and (max-width: 700px) {
|
|
posts {
|
|
grid-template-columns: repeat(1, 1fr);
|
|
}
|
|
}
|
|
|
|
|
|
</style>
|
|
|
|
<Layout centered={ true } fullwidth={ true }>
|
|
<hero class="main" class:icon={ !metadata.image } data-testid="home-page">
|
|
{#if metadata.image}
|
|
<img src={ metadata.image } />
|
|
{:else if metadata.icon}
|
|
<div>
|
|
<IconImage name={ metadata.icon} aspect_ratio="16/9" icon_height="70%" icon_width="70%" />
|
|
</div>
|
|
{/if}
|
|
|
|
<cover>
|
|
<h1>
|
|
<Markdown content={ metadata.title } />
|
|
</h1>
|
|
{#if metadata.summary }
|
|
<span id="slogan">
|
|
<Markdown content={ metadata.summary } />
|
|
</span>
|
|
{/if}
|
|
<br/>
|
|
</cover>
|
|
</hero>
|
|
|
|
<content>
|
|
<info>
|
|
<author>
|
|
{#if metadata.repost}
|
|
<b>Reposted from</b>
|
|
<a href={metadata.repost.link}>{metadata.repost.title}</a>
|
|
{/if}
|
|
|
|
<b>By</b> { metadata.author }
|
|
</author>
|
|
</info>
|
|
|
|
{@html content}
|
|
|
|
<hr>
|
|
<h6>More from Learn Code the Hard Way</h6>
|
|
</content>
|
|
|
|
<posts>
|
|
{#each related as post}
|
|
<card class="stacked">
|
|
<top>
|
|
<a href="/blog/{ post.slug }/">
|
|
<IconImage name={ post.icon } pattern={ false } aspect_ratio="16/9" />
|
|
</a>
|
|
</top>
|
|
<middle>
|
|
<h4><a href="/blog/{post.slug}/">{post.title}</a></h4>
|
|
<p>{ post.summary }</p>
|
|
</middle>
|
|
|
|
<bottom>
|
|
<tags>
|
|
<tag>{ post.tag }</tag>
|
|
<info><a href="/blog/{post.slug}/">Published { post.date }</a><info>
|
|
</tags>
|
|
</bottom>
|
|
</card>
|
|
{/each}
|
|
</posts>
|
|
</Layout>
|
|
|