We are half way there

This commit is contained in:
Michal Vanko 2023-01-17 20:57:28 +01:00
parent 145a5571c3
commit dad51ddb33
22 changed files with 2107 additions and 2079 deletions

3785
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -4,52 +4,53 @@
"version": "0.0.1", "version": "0.0.1",
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "svelte-kit dev", "dev": "vite dev",
"dev:debug": "node --inspect node_modules/@sveltejs/kit/dist/cli.js dev",
"prebuild": "npm run svgstore", "prebuild": "npm run svgstore",
"build": "svelte-kit build --verbose", "build": "vite build",
"preview": "svelte-kit preview", "preview": "vite preview",
"start": "svelte-kit start", "start": "svelte-kit start",
"test": "vitest", "test": "vitest",
"lint": "prettier --check . && eslint --ignore-path .gitignore .", "svgstore": "svgstore -o static/build/icons-sprite.svg src/svg/**.svg",
"format": "prettier --write .", "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
"svgstore": "svgstore -o static/build/icons-sprite.svg src/svg/**.svg" "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
"lint": "prettier --plugin-search-dir . --check . && eslint .",
"format": "prettier --plugin-search-dir . --write ."
}, },
"dependencies": { "dependencies": {
"@vanilla-extract/css": "^1.7.2", "@vanilla-extract/css": "^1.9.2",
"@vanilla-extract/sprinkles": "^1.4.1", "@vanilla-extract/sprinkles": "^1.5.1",
"@vanilla-extract/vite-plugin": "^3.2.1", "@vanilla-extract/vite-plugin": "^3.7.0",
"classnames": "^2.3.1", "classnames": "^2.3.2",
"date-fns": "^2.28.0", "date-fns": "^2.29.3",
"feed": "^4.2.2", "feed": "^4.2.2",
"front-matter": "^4.0.2", "front-matter": "^4.0.2",
"marked": "^3.0.8", "marked": "^3.0.8",
"modern-normalize": "^1.1.0", "modern-normalize": "^1.1.0",
"polished": "^4.2.2", "polished": "^4.2.2",
"prismjs": "^1.28.0", "prismjs": "^1.29.0",
"ramda": "^0.28.0" "ramda": "^0.28.0"
}, },
"devDependencies": { "devDependencies": {
"@sveltejs/adapter-static": "^1.0.0-next.34", "@sveltejs/adapter-static": "^1.0.4",
"@sveltejs/kit": "^1.0.0-next.354", "@sveltejs/kit": "^1.1.1",
"@tsconfig/svelte": "^3.0.0", "@tsconfig/svelte": "^3.0.0",
"@types/classnames": "^2.3.1", "@types/classnames": "^2.3.1",
"@types/node": "^18.0.0", "@types/node": "^18.11.18",
"@types/ramda": "^0.28.14", "@types/ramda": "^0.28.21",
"@typescript-eslint/eslint-plugin": "^5.29.0", "@typescript-eslint/eslint-plugin": "^5.48.2",
"@typescript-eslint/parser": "^5.29.0", "@typescript-eslint/parser": "^5.48.2",
"eslint": "^8.18.0", "eslint": "^8.32.0",
"eslint-config-prettier": "^8.5.0", "eslint-config-prettier": "^8.6.0",
"eslint-plugin-svelte3": "^4.0.0", "eslint-plugin-svelte3": "^4.0.0",
"prettier": "~2.7.1", "prettier": "~2.8.3",
"prettier-plugin-svelte": "^2.7.0", "prettier-plugin-svelte": "^2.9.0",
"svelte": "^3.48.0", "svelte": "^3.55.1",
"svelte-preprocess": "^4.10.7", "svelte-preprocess": "^5.0.0",
"svgstore-cli": "^2.0.1", "svgstore-cli": "^2.0.1",
"tslib": "^2.4.0", "tslib": "^2.4.1",
"typescript": "^4.7.4", "typescript": "^4.9.4",
"vite": "^2.9.12", "vite": "^4.0.4",
"vitest": "^0.16.0", "vitest": "^0.27.2",
"vitest-svelte-kit": "^0.0.6" "vitest-svelte-kit": "^0.0.6"
} }
} }

View File

@ -24,6 +24,8 @@
</head> </head>
<body> <body>
%sveltekit.body% <div style="display: contents">
%sveltekit.body%
</div>
</body> </body>
</html> </html>

View File

@ -1,6 +1,6 @@
<script lang="ts"> <script lang="ts">
import { format } from 'date-fns' import { format } from 'date-fns'
import type { PostContent } from 'src/routes/blog/_content' import type { PostContent } from 'src/routes/blog/content'
import SvgIcon from './SvgIcon.svelte' import SvgIcon from './SvgIcon.svelte'
import { import {
boldClass, boldClass,

View File

@ -12,8 +12,9 @@
portfolioPageNavigationLinksClass, portfolioPageNavigationLinksClass,
selectedClass, selectedClass,
} from './Nav.css' } from './Nav.css'
import { page } from "$app/stores"
export let segment $: segment = $page.url.pathname
</script> </script>
<nav class={navigationClass}> <nav class={navigationClass}>

View File

@ -2,7 +2,7 @@
import { horizontalBorderTopClass } from '$lib/styles/scoops.css' import { horizontalBorderTopClass } from '$lib/styles/scoops.css'
import { format } from 'date-fns' import { format } from 'date-fns'
import type { PostContent } from '../../routes/blog/_content' import type { PostContent } from '../../routes/blog/content'
import { import {
footerClass, footerClass,
publishedClass, publishedClass,

20
src/routes/+layout.svelte Normal file
View File

@ -0,0 +1,20 @@
<script lang="ts">
import type { LayoutData } from "./$types"
import Nav from '../components/Nav.svelte'
import Footer from '../components/Footer.svelte'
import 'modern-normalize/modern-normalize.css'
import '$lib/styles/global.css'
import { mainContentClass } from './layout.css'
export let data: LayoutData
export let latestPosts = data.latestPosts
</script>
<div class="app-content">
<Nav />
<main class={mainContentClass}>
<slot />
</main>
<Footer {latestPosts} />
</div>

12
src/routes/+layout.ts Normal file
View File

@ -0,0 +1,12 @@
import type { LayoutLoad } from './$types';
export const load = (async ({ fetch, url }) => {
const blogPostsResponse = await fetch(`/blog/articles/pageSize/5.json`)
const blogPostsContent = await blogPostsResponse.json()
return {
latestPosts: blogPostsContent.posts.items,
// TODO Check if not bugged FIXME
segment: '',
}
}) satisfies LayoutLoad

View File

@ -1,37 +0,0 @@
<script context="module" lang="ts">
import { take } from 'ramda'
import type { LoadInput, LoadOutput } from '@sveltejs/kit/types/page'
export async function load({ fetch, url }: LoadInput): Promise<LoadOutput> {
const blogPostsResponse = await fetch(`/blog/articles/pageSize/5.json`)
const blogPostsContent = await blogPostsResponse.json()
return {
props: {
latestPosts: blogPostsContent.posts.items,
// TODO Check if not bugged FIXME
// TODO remove console.logs
segment: '',
},
}
}
</script>
<script lang="ts">
import Nav from '../components/Nav.svelte'
import Footer from '../components/Footer.svelte'
import 'modern-normalize/modern-normalize.css'
import '$lib/styles/global.css'
import { mainContentClass } from './layout.css'
export let segment
export let latestPosts
</script>
<div class="app-content">
<Nav {segment} />
<main class={mainContentClass}>
<slot />
</main>
<Footer {latestPosts} />
</div>

View File

@ -25,7 +25,7 @@
import ArticleFooter from '../../components/blog/ArticleFooter.svelte' import ArticleFooter from '../../components/blog/ArticleFooter.svelte'
import Paginator from '../../components/paginator/Paginator.svelte' import Paginator from '../../components/paginator/Paginator.svelte'
import { postListClass, seeAllClass } from './index.css' import { postListClass, seeAllClass } from './index.css'
import type { PostContent } from './_content' import type { PostContent } from './content'
import type { PaginationResult } from '$lib/pagination/pagination' import type { PaginationResult } from '$lib/pagination/pagination'
export let posts: PaginationResult<PostContent> export let posts: PaginationResult<PostContent>

View File

@ -2,7 +2,7 @@ import { readFile } from 'fs'
import { promisify } from 'util' import { promisify } from 'util'
import fm from 'front-matter' import fm from 'front-matter'
import { parseField } from '../../markdown/parse-markdown' import { parseField } from '../../markdown/parse-markdown'
import type { PostAttributes } from './_content' import type { PostAttributes } from './content'
import type { Request, Response } from '@sveltejs/kit' import type { Request, Response } from '@sveltejs/kit'
export interface SinglePost { export interface SinglePost {

View File

@ -2,9 +2,11 @@ import {
getDropTakeFromPageParams, getDropTakeFromPageParams,
parseParams, parseParams,
} from '$lib/pagination/dropTakeParams' } from '$lib/pagination/dropTakeParams'
import { getBlogListing } from '../_content' import { json } from '@sveltejs/kit'
import { getBlogListing } from '../../content'
import type { RequestHandler } from './$types'
export async function get({ params }) { export const GET = (async ({ params }) => {
console.log('article-params', params) console.log('article-params', params)
const handledParams = params.params === 'index' ? '' : params.params const handledParams = params.params === 'index' ? '' : params.params
const { page = 1, pageSize = 7, ...filters } = parseParams(handledParams) const { page = 1, pageSize = 7, ...filters } = parseParams(handledParams)
@ -15,10 +17,7 @@ export async function get({ params }) {
const paginationQuery = { ...paginationParams, filters } const paginationQuery = { ...paginationParams, filters }
const filteredContents = await getBlogListing(paginationQuery) const filteredContents = await getBlogListing(paginationQuery)
return { return json({
status: 200, posts: filteredContents,
body: { })
posts: filteredContents, }) satisfies RequestHandler
},
}
}

View File

@ -1,5 +1,5 @@
import { Feed } from 'feed' import { Feed } from 'feed'
import { getBlogListing } from '../blog/_content' import { getBlogListing } from '../blog/content'
export async function getFeed() { export async function getFeed() {
const feed = new Feed({ const feed = new Feed({

View File

@ -3,6 +3,7 @@ import { promisify } from 'util'
import fm from 'front-matter' import fm from 'front-matter'
import marked from 'marked' import marked from 'marked'
import { parseField } from '../../markdown/parse-markdown' import { parseField } from '../../markdown/parse-markdown'
import type { PageServerLoad } from './$types'
export interface RecordAttributes { export interface RecordAttributes {
name: string name: string
@ -50,16 +51,8 @@ export type PortfolioContent = {
body: string body: string
} }
export async function get() { export const load = (async () => {
let pageSource: string const pageSource = await promisify(readFile)('_pages/portfolio.md', 'utf-8')
try {
pageSource = await promisify(readFile)('_pages/portfolio.md', 'utf-8')
} catch (e) {
return {
status: 500,
body: 'Error loading portfolio source file. \n' + e.toString(),
}
}
const parsed = fm<PortfolioAttributes>(pageSource) const parsed = fm<PortfolioAttributes>(pageSource)
const workHistory = (parsed.attributes.work_history || []) const workHistory = (parsed.attributes.work_history || [])
@ -85,8 +78,5 @@ export async function get() {
presentations, presentations,
} }
return { return response;
status: 200, }) satisfies PageServerLoad
body: response,
}
}

View File

@ -1,30 +1,16 @@
<script lang="ts" context="module">
/**
* @type {import('@sveltejs/kit').Load}
*/
export async function load({ fetch }) {
const res = await fetch('portfolio.json')
const content = await res.json()
return {
props: {
content,
},
}
}
</script>
<script lang="ts"> <script lang="ts">
import Work from '../../components/portfolio/work.svelte' import Work from '../../components/portfolio/work.svelte'
import Project from '../../components/portfolio/project.svelte' import Project from '../../components/portfolio/project.svelte'
import Presentation from '../../components/portfolio/presentation.svelte' import Presentation from '../../components/portfolio/presentation.svelte'
import type { PortfolioContent } from './index.json' import type { PageData } from './$types'
import { listClass, listItemClass, nameTagClass } from './index.css' import { listClass, listItemClass, nameTagClass } from './index.css'
export let content: PortfolioContent export let data: PageData
</script> </script>
<svelte:head> <svelte:head>
<title>{content.title}</title> <title>{data.title}</title>
</svelte:head> </svelte:head>
<h1 class="name-tag {nameTagClass}">Michal Vanko</h1> <h1 class="name-tag {nameTagClass}">Michal Vanko</h1>
@ -34,16 +20,16 @@
</h2> </h2>
<section id="personal-information"> <section id="personal-information">
{@html content.body} {@html data.body}
</section> </section>
<section id="work-history"> <section id="work-history">
<h2>Work experience</h2> <h2>Work experience</h2>
<section class="work-history-prelude"> <section class="work-history-prelude">
{@html content.workHistoryPrelude} {@html data.workHistoryPrelude}
</section> </section>
<ul class={listClass}> <ul class={listClass}>
{#each content.workHistory as work} {#each data.workHistory as work}
<li class={listItemClass}> <li class={listItemClass}>
<Work {work} /> <Work {work} />
</li> </li>
@ -54,7 +40,7 @@
<section id="projects"> <section id="projects">
<h2>Projects</h2> <h2>Projects</h2>
<ul class={listClass}> <ul class={listClass}>
{#each content.projects as project} {#each data.projects as project}
<li class={listItemClass}> <li class={listItemClass}>
<Project {project} /> <Project {project} />
</li> </li>
@ -65,7 +51,7 @@
<section id="presentations"> <section id="presentations">
<h2>Presentations</h2> <h2>Presentations</h2>
<ul class=""> <ul class="">
{#each content.presentations as presentation} {#each data.presentations as presentation}
<li class=""> <li class="">
<Presentation {presentation} /> <Presentation {presentation} />
</li> </li>
@ -76,7 +62,7 @@
<section id="education"> <section id="education">
<h2>Education</h2> <h2>Education</h2>
<ul class={listClass}> <ul class={listClass}>
{#each content.education as work} {#each data.education as work}
<li class={listItemClass}> <li class={listItemClass}>
<Work {work} /> <Work {work} />
</li> </li>

View File

@ -0,0 +1,9 @@
import type { PageLoad } from './$types'
export const load = (async () => {
const res = await fetch('/portfolio.json')
const content = await res.json()
return {
content,
}
}) satisfies PageLoad

View File

@ -1,89 +0,0 @@
import { timestamp, files, build } from '$service-worker'
const ASSETS = `cache${timestamp}`
// `shell` is an array of all the files generated by the bundler,
// `files` is an array of everything in the `static` directory
const to_cache = build.concat(files)
const staticAssets = new Set(to_cache)
self.addEventListener('install', (event) => {
event.waitUntil(
caches
.open(ASSETS)
.then((cache) => cache.addAll(to_cache))
.then(() => {
self.skipWaiting()
})
)
})
self.addEventListener('activate', (event) => {
event.waitUntil(
caches.keys().then(async (keys) => {
// delete old caches
for (const key of keys) {
if (key !== ASSETS) await caches.delete(key)
}
self.clients.claim()
})
)
})
/**
* Fetch the asset from the network and store it in the cache.
* Fall back to the cache if the user is offline.
*/
async function fetchAndCache(request) {
const cache = await caches.open(`offline${timestamp}`)
try {
const response = await fetch(request)
cache.put(request, response.clone())
return response
} catch (err) {
const response = await cache.match(request)
if (response) return response
throw err
}
}
self.addEventListener('fetch', (event) => {
if (event.request.method !== 'GET' || event.request.headers.has('range'))
return
const url = new URL(event.request.url)
// don't try to handle e.g. data: URIs
const isHttp = url.protocol.startsWith('http')
const isDevServerRequest =
url.hostname === self.location.hostname && url.port !== self.location.port
const isStaticAsset =
url.host === self.location.host && staticAssets.has(url.pathname)
const skipBecauseUncached =
event.request.cache === 'only-if-cached' && !isStaticAsset
if (isHttp && !isDevServerRequest && !skipBecauseUncached) {
event.respondWith(
(async () => {
// always serve static files and bundler-generated assets from cache.
// if your application has other URLs with data that will never change,
// set this variable to true for them and they will only be fetched once.
const cachedAsset = isStaticAsset && (await caches.match(event.request))
// for pages, you might want to serve a shell `service-worker-index.html` file,
// which Sapper has generated for you. It's not right for every
// app, but if it's right for yours then uncomment this section
/*
if (!cachedAsset && url.origin === self.origin && routes.find(route => route.pattern.test(url.pathname))) {
return caches.match('/service-worker-index.html');
}
*/
return cachedAsset || fetchAndCache(event.request)
})()
)
}
})

View File

@ -1,23 +1,13 @@
import adapterStatic from '@sveltejs/adapter-static' import adapterStatic from '@sveltejs/adapter-static'
import preprocess from 'svelte-preprocess' import { vitePreprocess } from '@sveltejs/kit/vite'
import { vanillaExtractPlugin } from '@vanilla-extract/vite-plugin'
const mode = process.env.NODE_ENV
const dev = mode === 'development'
/** @type {import('@sveltejs/kit').Config} */ /** @type {import('@sveltejs/kit').Config} */
const config = { const config = {
preprocess: vitePreprocess(),
kit: { kit: {
adapter: adapterStatic(), adapter: adapterStatic(),
vite: { // prerender: { default: true },
plugins: [vanillaExtractPlugin()],
server: { fs: { allow: ['static/build'] } },
},
prerender: { default: true },
}, },
preprocess: preprocess({
sourceMap: dev,
}),
} }
export default config export default config

View File

@ -1,32 +1,18 @@
{ {
"extends": "./.svelte-kit/tsconfig.json", "extends": "./.svelte-kit/tsconfig.json",
"compilerOptions": { "compilerOptions": {
"moduleResolution": "node", "allowJs": true,
"module": "es2020", "checkJs": true,
"lib": ["es2020", "DOM"], "esModuleInterop": true,
"target": "es2019", "forceConsistentCasingInFileNames": true,
/** "resolveJsonModule": true,
svelte-preprocess cannot figure out whether you have a value or a type, so tell TypeScript "skipLibCheck": true,
to enforce using \`import type\` instead of \`import\` for Types. "sourceMap": true,
*/ "strict": true
"importsNotUsedAsValues": "error", }
"isolatedModules": true, // Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias
"resolveJsonModule": true, //
/** // If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes
To have warnings/errors of the Svelte compiler at the correct position, // from the referenced tsconfig.json - TypeScript does not merge them in
enable source maps by default.
*/
"sourceMap": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"baseUrl": ".",
"allowJs": true,
"checkJs": true,
"paths": {
"$lib": ["src/lib"],
"$lib/*": ["src/lib/*"]
}
},
"include": ["src/**/*.d.ts", "src/**/*.js", "src/**/*.ts", "src/**/*.svelte"]
} }

25
vite.config.ts Normal file
View File

@ -0,0 +1,25 @@
import { sveltekit } from '@sveltejs/kit/vite'
import { UserConfig } from 'vite'
import { vanillaExtractPlugin } from '@vanilla-extract/vite-plugin'
const config: UserConfig = {
plugins: [sveltekit(), vanillaExtractPlugin()],
test: {
include: ['src/**/*.{test,spec}.{js,ts}'],
},
server: { fs: { allow: ['static/build'] } },
// kit: {
// adapter: adapterStatic(),
// vite: {
// plugins: [vanillaExtractPlugin()],
// server: { fs: { allow: ['static/build'] } },
// },
// prerender: { default: true },
// },
// preprocess: preprocess({
// sourceMap: dev,
// }),
}
export default config