What a refactor of articles

This commit is contained in:
2023-02-12 14:56:49 +01:00
parent 33bf6769e4
commit f156d4dacc
35 changed files with 228 additions and 134 deletions

View File

@ -1,7 +1,7 @@
<script lang="ts">
import type { LayoutData } from "./$types"
import Nav from '../components/Nav.svelte'
import Footer from '../components/Footer.svelte'
import type { LayoutData } from './$types'
import Nav from '$lib/components/Nav.svelte'
import Footer from '$lib/components/Footer.svelte'
import 'modern-normalize/modern-normalize.css'
import '$lib/styles/global.css'
import { mainContentClass } from './layout.css'

View File

@ -2,7 +2,7 @@ import type { LayoutLoad } from './$types'
export const prerender = true
export const load = (async ({ fetch }) => {
const blogPostsResponse = await fetch(`/blog/articles/pageSize/5.json`)
const blogPostsResponse = await fetch(`/articles/pageSize/5.json`)
const blogPostsContent = await blogPostsResponse.json()
return {

View File

@ -3,7 +3,7 @@ import {
parseParams,
} from '$lib/pagination/dropTakeParams'
import { json } from '@sveltejs/kit'
import { getBlogListing } from '../../content'
import { getBlogListing } from '$lib/content/articleContentListing'
import type { RequestHandler } from './$types'
export const prerender = true

View File

@ -1,12 +1,10 @@
<script lang="ts">
import ArticleFooter from '../../../components/blog/ArticleFooter.svelte'
import Paginator from '../../../components/paginator/Paginator.svelte'
import { postListClass, seeAllClass } from './page.css'
import type { PageData } from './$types'
import ArticlePreviewList from '$lib/components/articles/ArticlePreviewList/ArticlePreviewList.svelte'
import { seeAllClass } from '$lib/components/articles/ArticlePreviewList/ArticlePreviewList.css'
export let data: PageData
let { posts, filters, page, pageSize } = data
$: ({ posts, filters, page, pageSize } = data)
$: ({ posts, filters } = data)
</script>
<svelte:head>
@ -30,36 +28,5 @@
</div>
{/if}
{/if}
<header>
<Paginator
href="blog"
{page}
{pageSize}
{filters}
totalCount={posts.totalCount}
/>
</header>
<ul class="post-list {postListClass}">
{#each posts.items as post (post.slug)}
<li>
<article>
<header>
<h2>
<a rel="prefetch" href="/blog/{post.slug}">{post.title}</a>
</h2>
</header>
{@html post.preview}
</article>
<ArticleFooter {post} />
</li>
{/each}
</ul>
<footer>
<Paginator
href="blog"
{page}
{pageSize}
{filters}
totalCount={posts.totalCount}
/>
</footer>
<ArticlePreviewList {...data} segment="blog" />

View File

@ -1,16 +1,16 @@
import { parseParams } from '$lib/pagination/dropTakeParams'
import type { PageLoad } from './$types'
import type { PostContent } from './../content'
import type { ArticleContent } from '$lib/content/articleContentListing'
import type { PaginationResult } from '$lib/pagination/pagination'
export const load = (async ({ fetch, params }) => {
const { page = 1, pageSize = 7, ...filters } = parseParams(params.params)
const articleResponse = await fetch(
`/blog/articles/${params.params ? params.params : 'index'}.json`
`/articles/${params.params ? params.params : 'index'}.json`
).then((r) => r.json())
return {
posts: articleResponse.posts as PaginationResult<PostContent>,
posts: articleResponse.posts as PaginationResult<ArticleContent>,
page: Number(page),
pageSize,
filters,

View File

@ -1,20 +0,0 @@
import { globalStyle } from '@vanilla-extract/css'
import { vars } from '$lib/styles/vars.css'
import { sprinkles } from '$lib/styles/sprinkles.css'
export const postListClass = sprinkles({
padding: 'none',
lineHeight: '3x',
listStyle: 'none',
})
export const seeAllClass = sprinkles({
textAlign: 'end',
width: 'parent',
maxWidth: 'max',
margin: 'auto',
})
globalStyle(`${postListClass} > li:not(:last-child)`, {
marginBottom: vars.space['4x'],
})

View File

@ -2,8 +2,8 @@ import { readFile } from 'fs'
import { promisify } from 'util'
import fm from 'front-matter'
import { parseField } from '../../../markdown/parse-markdown'
import { error, json } from '@sveltejs/kit'
import type { PostAttributes } from '../content'
import { error } from '@sveltejs/kit'
import type { ArticleAttributes } from '$lib/content/articleContentListing'
import type { PageServerLoad } from './$types'
export const prerender = true
@ -24,7 +24,7 @@ export const load = (async ({ params: { slug } }) => {
throw e
}
const parsedPost = fm<PostAttributes>(postSource)
const parsedPost = fm<ArticleAttributes>(postSource)
const post = parseField<SinglePost>('body')({
...parsedPost.attributes,

View File

@ -1,5 +1,5 @@
<script lang="ts">
import ArticleFooter from '../../../components/blog/ArticleFooter.svelte'
import ArticleFooter from '$lib/components/articles/ArticlePreviewFooter/ArticlePreviewFooter.svelte'
import type { PageData } from './$types'
import { contentClass } from './page.css'
@ -15,4 +15,4 @@
<div class="content {contentClass}">
{@html data.body}
</div>
<ArticleFooter post={data} />
<ArticleFooter article={data} segment="blog" />

View File

@ -1,69 +0,0 @@
import { readdir, readFile } from 'fs'
import { promisify } from 'util'
import { basename } from 'path'
import { pipe, prop, sortBy, reverse, filter } from 'ramda'
import fm from 'front-matter'
import marked from 'marked'
import {
filterAndCount,
type PaginationQuery,
} from '$lib/pagination/pagination'
const { NODE_ENV } = process.env
export interface PostAttributes {
layout: string
title: string
published: boolean
date: string
thumbnail: string
tags: string[]
}
export interface PostContent extends PostAttributes {
preview: string
slug: string
published: boolean
}
export async function getBlogListing(paginationQuery: PaginationQuery) {
const files = await promisify(readdir)(`_posts/blog/`, 'utf-8')
const filteredFiles = filterDevelopmentFiles(files)
const contents = await Promise.all(
filteredFiles.map(async (file) => {
const fileContent = await promisify(readFile)(
`_posts/blog/${file}`,
'utf-8'
)
const parsedAttributes = fm<PostAttributes>(fileContent)
const lineOfTextRegExp = /^(?:\w|\[).+/gm
const lines = parsedAttributes.body
.match(lineOfTextRegExp)
.slice(0, 2)
.join('\n')
const preview = marked(lines)
return {
...parsedAttributes.attributes,
preview,
slug: basename(file, '.md'),
}
})
)
const filteredContents = pipe(
sortBy<PostContent>(prop('date')),
(items) => reverse(items),
filter<(typeof contents)[0]>((article) => article.published),
filterAndCount(paginationQuery)
)(contents)
return filteredContents
}
function filterDevelopmentFiles(files: string[]) {
return NODE_ENV !== 'production'
? files
: files.filter((file) => !file.startsWith('dev-'))
}

View File

@ -0,0 +1,30 @@
<script lang="ts">
import type { PageData } from './$types'
import ArticlePreviewList from '$lib/components/articles/ArticlePreviewList/ArticlePreviewList.svelte'
import { seeAllClass } from '$lib/components/articles/ArticlePreviewList/ArticlePreviewList.css'
export let data: PageData
$: ({ posts, filters } = data)
</script>
<svelte:head>
<title>Broadcasts @michalvankodev</title>
</svelte:head>
{#if posts.items.length === 0}
<p class="no-posts">You've found void in the space.</p>
{:else}
<h1>
{#if filters.tags}
<em>{filters.tags}</em>
{/if}
Broadcasts
</h1>
{#if filters.tags}
<div class={seeAllClass}>
<a href="/broadcasts">See all broadcasts</a>
</div>
{/if}
{/if}
<ArticlePreviewList {...data} segment="broadcasts" />

View File

@ -0,0 +1,18 @@
import { parseParams } from '$lib/pagination/dropTakeParams'
import type { PageLoad } from './$types'
import type { ArticleContent } from '$lib/content/articleContentListing'
import type { PaginationResult } from '$lib/pagination/pagination'
export const load = (async ({ fetch, params }) => {
const { page = 1, pageSize = 7, ...filters } = parseParams(params.params)
const articleResponse = await fetch(
`/articles/${params.params ? params.params : 'index'}.json`
).then((r) => r.json())
return {
posts: articleResponse.posts as PaginationResult<ArticleContent>,
page: Number(page),
pageSize,
filters,
}
}) satisfies PageLoad

View File

@ -1,7 +1,7 @@
<script lang="ts">
import Work from '../../components/portfolio/work.svelte'
import Project from '../../components/portfolio/project.svelte'
import Presentation from '../../components/portfolio/presentation.svelte'
import Work from './components/work.svelte'
import Project from './components/project.svelte'
import Presentation from './components/presentation.svelte'
import type { PageData } from './$types'
import { listClass, listItemClass, nameTagClass } from './page.css'

View File

@ -0,0 +1,39 @@
<section id="personal">
<h3>Personal Information</h3>
<p>I was born on 26th of May in Košice, Slovakia and I still live here.</p>
<h4>Hobbies:</h4>
<p>
I enjoy playing basketball with my friends. I also like to play other team
sports like football and hockey. I also play squash and table tennis. Once
I've won a competition in squash at my university. During summer I love
water skiing and swimming in a nearby lake.
<br />
I am very passionate about music. I've also tried some software for composing
music but I am not really hooked into that yet. From time to time I enjoy playing
board games with my friends.
</p>
<h4>Interests:</h4>
<p>
I like to explore new technologies and I'm passionate about <em
>Open Source movement</em
>,
<em>Internet of Things</em> applications and
<em>Linux desktop evolution</em>.
<br />
I am interested in modern software architecture and
<em>reactive programming</em>.
<br />
I've attended various <strong>tech conferences and hackathons</strong>. I
like them for all of the fascinating ideas that might be invented.
<br />
I've given presentations on various topics related to
<em>web development</em>. You can
<a href="#presentations">take a look at some of them here</a>.
<br />
I enjoy <strong>teaching and explaining</strong> how various technologies
and techniques work to my colleagues for their better understanding.
<br />
I take advantage of <strong>test driven development</strong>.
</p>
</section>
<!--/personal-->

View File

@ -0,0 +1,18 @@
import { sprinkles } from '$lib/styles/sprinkles.css'
export const presentationFrameClass = sprinkles({
width: 'image',
height: 'image',
})
export const presentationPreviewLinksClass = sprinkles({
fontSize: 'sm',
})
export const presentationDescriptionClass = sprinkles({
paddingLeft: '1x',
})
export const presentationNameClass = sprinkles({
fontSize: 'base',
})

View File

@ -0,0 +1,41 @@
<script lang="ts">
import type { PresentationAttributes } from 'src/routes/portfolio/index.json'
import {
presentationDescriptionClass,
presentationFrameClass,
presentationNameClass,
presentationPreviewLinksClass,
} from './presentation.css'
export let presentation: PresentationAttributes
export let previewVisible = false
function togglePreviewVisible() {
previewVisible = !previewVisible
}
</script>
<article>
<a href={presentation.link} target="_blank">
<h3 class={presentationNameClass}>{presentation.name}</h3>
</a>
<section class="description {presentationDescriptionClass}">
{@html presentation.description}
</section>
<section class="preview">
<div class={presentationPreviewLinksClass}>
<a href="#presentations" on:click|preventDefault={togglePreviewVisible}
>{previewVisible ? 'Close' : 'Open'} preview</a
>
</div>
{#if previewVisible}
<iframe
class={presentationFrameClass}
src={presentation.link}
title="Presentation of {presentation.name}"
/>
{/if}
</section>
</article>

View File

@ -0,0 +1,10 @@
import { globalStyle, style } from '@vanilla-extract/css'
export const projectScopeClass = style({})
globalStyle(`${projectScopeClass} img`, {
float: 'right',
width: '25%',
})
// We need to get rid off the global selectors LOL

View File

@ -0,0 +1,21 @@
<script lang="ts">
import type { ProjectAttributes } from '../../routes/portfolio/index.json'
import { projectScopeClass } from './project.css'
export let project: ProjectAttributes
</script>
<article class="project {projectScopeClass}">
<h3>{project.name}</h3>
<section class="description">
{#if project.image}
<img
src={project.image.source}
class="project-image"
alt={project.image.image_description}
/>
{/if}
{@html project.description}
</section>
<aside />
</article>

View File

@ -0,0 +1,17 @@
<section id="skills">
<h3>Skills</h3>
<p>Slovak is my mother tongue and I've learned English as my second language. I speak English on advanced level.</p>
<p>
I'm an experienced <em>Linux Desktop</em> user. I prefer to use open source libraries and technologies while I develop solutions.
<br>
I'm in good command of Office Tools and I've experience with image manipulation programs like <em>GIMP</em> and <em>Inkscape</em>.
<br>
I can also compose music and sounds in <em>digital audio workstation</em>.
</p>
<p>I'm passionate about <em>software architecture</em>. My goal is to be able to design suitable solution for any kind of product. From small <em>presentation sites</em>, <em>IOT devices</em>, to large <em>enterprise applications running on cloud</em>.</p>
<p>
I do <em>public speaking</em> and I am not afraid to share my knowledge and passion about technology.
</p>
<p>I'm advanced user of source code management tools <em>git</em> and <em>svn</em>.</p>
<p>I've a driving licence for category B &#128663;.</p>
</section>

View File

@ -0,0 +1,15 @@
import { sprinkles } from '$lib/styles/sprinkles.css'
export const workFooterClass = sprinkles({
marginTop: '1x',
paddingTop: '1x',
fontSize: 'sm',
lineHeight: '1x',
})
export const workAddressNameClass = sprinkles({
fontStyle: 'italic',
fontWeight: 'normal',
margin: 'none',
fontSize: 'base',
})

View File

@ -0,0 +1,27 @@
<script lang="ts">
import type { WorkAttributes } from '../../routes/portfolio/index.json'
import { workAddressNameClass, workFooterClass } from './work.css'
import { horizontalBorderTopClass } from '$lib/styles/scoops.css'
export let work: WorkAttributes
</script>
<article>
<h3>{work.name}</h3>
<section class="description">
{@html work.description}
</section>
{#if work.address}
<footer class="{workFooterClass} {horizontalBorderTopClass}">
<h4 class={workAddressNameClass}>{work.address.name}</h4>
<address>
<div>
{work.address.location},
{work.address.zipcode}
{work.address.city},
{work.address.country}
</div>
</address>
</footer>
{/if}
</article>