Broadcasting section

This commit is contained in:
2023-02-18 06:41:07 +01:00
parent dac3e13520
commit 3640a5f13a
13 changed files with 79 additions and 53 deletions

View File

@ -0,0 +1,37 @@
import { error } from "@sveltejs/kit";
import fm from "front-matter";
import { readFile } from "fs";
import { parseField } from "$lib/markdown/parse-markdown";
import { promisify } from "util";
export interface ArticleAttributes {
slug: string
layout: string
title: string
published: boolean
date: string
thumbnail: string
tags: string[]
body: string
}
export async function getArticleContent(slug: string) {
let postSource: string
try {
postSource = await promisify(readFile)(`_posts/blog/${slug}.md`, 'utf-8')
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} catch (e: any) {
if (e.code === 'ENOENT') {
throw error(404, 'Post not found \n' + e.toString())
}
throw e
}
const parsedPost = fm<ArticleAttributes>(postSource)
const post = parseField<ArticleAttributes>('body')({
...parsedPost.attributes,
body: parsedPost.body,
})
return post
}

View File

@ -8,24 +8,13 @@ import {
filterAndCount,
type PaginationQuery,
} from '$lib/pagination/pagination'
import type { ArticleAttributes } from './articleContent'
export interface ArticlePreviewAttributes extends ArticleAttributes {
preview: string
}
const { NODE_ENV } = process.env
export interface ArticleAttributes {
layout: string
title: string
published: boolean
date: string
thumbnail: string
tags: string[]
}
export interface ArticleContent extends ArticleAttributes {
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)
@ -52,9 +41,8 @@ export async function getBlogListing(paginationQuery: PaginationQuery) {
}
})
)
console.log(paginationQuery);
const filteredContents = pipe(
sortBy<ArticleContent>(prop('date')),
sortBy<ArticlePreviewAttributes>(prop('date')),
(items) => reverse(items),
filter<(typeof contents)[0]>((article) => article.published),
filterAndCount(paginationQuery)

View File

@ -0,0 +1,11 @@
import marked from 'marked'
import { renderer } from './renderer-extension'
marked.use({ renderer })
export function parseField<T>(field: keyof T) {
return (item: T): T => ({
...item,
[field]: marked(item[field]),
})
}

View File

@ -0,0 +1,49 @@
import { generateSrcSet, getNFResize } from '$lib/large-media'
import Prism from 'prismjs'
import loadLanguages from 'prismjs/components/index.js'
loadLanguages(['bash', 'markdown', 'json', 'yaml', 'typescript'])
export const renderer = {
heading(text: string, level: string) {
const escapedText = text.toLowerCase().replace(/[^\w]+/g, '-')
return `
<h${level}>
<a name="${escapedText}" class="anchor" href="#${escapedText}">
<span class="header-link"></span>
</a>
${text}
</h${level}>
`
},
image(href: string, title: string, text: string) {
const figcaption = title ? `<figcaption>${title}</figcaption>` : ''
const isLocal = !href.startsWith('http')
const src = isLocal ? getNFResize(href, { height: 800, width: 800 }) : href
const srcset = isLocal
? `srcset="${generateSrcSet(href, { width: 800, height: 800 })}"`
: ''
return `
<figure>
<img
alt="${text}"
${srcset}
src="${src}"
/>
${figcaption}
</figure>
`
},
code(source: string, lang?: string) {
// When lang is not specified it is usually an empty string which has to be handled
const usedLang = !lang ? 'shell' : lang
const highlightedSource = Prism.highlight(
source,
Prism.languages[usedLang],
usedLang
)
return `<pre class='language-${usedLang}'><code class='language-${usedLang}'>${highlightedSource}</code></pre>`
},
}

View File

@ -0,0 +1,21 @@
import { globalStyle, style } from '@vanilla-extract/css'
import { vars } from '$lib/styles/vars.css'
export const contentClass = style({})
globalStyle(`${contentClass} ul, ${contentClass} ol`, {
lineHeight: vars.lineHeight['2x'],
})
globalStyle(`${contentClass} li`, {
marginBottom: vars.space['2x'],
})
globalStyle(`${contentClass} img`, {
maxHeight: vars.height.image,
})
globalStyle(`${contentClass} img:only-child`, {
display: 'block',
margin: '0 auto',
})