What a refactor of articles
This commit is contained in:
@ -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'
|
||||
|
@ -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 {
|
||||
|
@ -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
|
@ -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" />
|
||||
|
@ -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,
|
||||
|
@ -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'],
|
||||
})
|
@ -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,
|
||||
|
@ -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" />
|
||||
|
@ -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-'))
|
||||
}
|
30
src/routes/broadcasts/[...params]/+page.svelte
Normal file
30
src/routes/broadcasts/[...params]/+page.svelte
Normal 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" />
|
18
src/routes/broadcasts/[...params]/+page.ts
Normal file
18
src/routes/broadcasts/[...params]/+page.ts
Normal 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
|
@ -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'
|
||||
|
39
src/routes/portfolio/components/personal.svelte
Normal file
39
src/routes/portfolio/components/personal.svelte
Normal 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-->
|
18
src/routes/portfolio/components/presentation.css.ts
Normal file
18
src/routes/portfolio/components/presentation.css.ts
Normal 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',
|
||||
})
|
41
src/routes/portfolio/components/presentation.svelte
Normal file
41
src/routes/portfolio/components/presentation.svelte
Normal 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>
|
10
src/routes/portfolio/components/project.css.ts
Normal file
10
src/routes/portfolio/components/project.css.ts
Normal 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
|
21
src/routes/portfolio/components/project.svelte
Normal file
21
src/routes/portfolio/components/project.svelte
Normal 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>
|
17
src/routes/portfolio/components/skills.svelte
Normal file
17
src/routes/portfolio/components/skills.svelte
Normal 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 🚗.</p>
|
||||
</section>
|
15
src/routes/portfolio/components/work.css.ts
Normal file
15
src/routes/portfolio/components/work.css.ts
Normal 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',
|
||||
})
|
27
src/routes/portfolio/components/work.svelte
Normal file
27
src/routes/portfolio/components/work.svelte
Normal 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>
|
Reference in New Issue
Block a user