Compare commits
55 Commits
Author | SHA1 | Date |
---|---|---|
BOT Alex | b19050aae1 | |
BOTAlex | 9ca3336059 | |
BOTAlex | 90f0e40ddf | |
BOT Alex | e19bc385a1 | |
BOT Alex | 172c49f72e | |
BOTAlex | 1f5f7a3777 | |
BOTAlex | 041e2935c7 | |
BOT Alex | 359018746c | |
BOT Alex | 73dc865900 | |
BOTAlex | 72e5b2071a | |
BOTAlex | 878c1f6b5f | |
BOTAlex | c3a0c735fa | |
BOTAlex | b444948903 | |
BOTAlex | 7134f79809 | |
BOTAlex | 3d54793847 | |
BOTAlex | 8738a77a4e | |
BOTAlex | e75b6358ef | |
BOTAlex | 8ed6d26c40 | |
BOTAlex | 03cfd5a617 | |
BOTAlex | e79408b9bc | |
BOT Alex | d2b4e839c9 | |
BOT Alex | be35022ed2 | |
Sveske_Juice | bb564a53d1 | |
Sveske_Juice | 65cc1f52d9 | |
Sveske_Juice | a46702de0a | |
Sveske_Juice | 3f47b79603 | |
BOTAlex | 76e57d82c5 | |
Sveske_Juice | 3d36a59d36 | |
Sveske_Juice | 110720ea59 | |
Sveske_Juice | 550b1410e3 | |
Sveske_Juice | 1422b93fcd | |
Sveske_Juice | 2bc072e4b3 | |
Sveske_Juice | fc160a23fd | |
Sveske_Juice | 21428cd03e | |
Sveske_Juice | 3bb2b0ba31 | |
Sveske_Juice | 7734fb45f5 | |
Sveske_Juice | 5be1a80ff4 | |
Sveske_Juice | b6b1f5ecfc | |
Sveske_Juice | 56304e0ca5 | |
Sveske_Juice | 14c9a24402 | |
Sveske_Juice | e07cd844db | |
Sveske_Juice | 547063bfc0 | |
Sveske_Juice | 4d43f20a9c | |
Sveske_Juice | 81ffeaa780 | |
Sveske_Juice | c7fb3f7945 | |
Sveske_Juice | b6f8ef8f37 | |
Sveske_Juice | 8b8b81f3d1 | |
Sveske_Juice | 8b533b296c | |
Sveske_Juice | a0106369c9 | |
Sveske_Juice | 8457f32dd5 | |
Sveske_Juice | 773645f5be | |
Sveske_Juice | 0f4764052f | |
Sveske_Juice | f5bc1db8f1 | |
Sveske_Juice | 718788bb0a | |
Sveske_Juice | 9eae4e8d11 |
|
@ -0,0 +1,10 @@
|
|||
.DS_Store
|
||||
node_modules
|
||||
/build
|
||||
/.svelte-kit
|
||||
/package
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
vite.config.js.timestamp-*
|
||||
vite.config.ts.timestamp-*
|
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"extends": "./.svelte-kit/tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"allowJs": true,
|
||||
"checkJs": true,
|
||||
"esModuleInterop": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"resolveJsonModule": true,
|
||||
"skipLibCheck": true,
|
||||
"sourceMap": true,
|
||||
"strict": true,
|
||||
"moduleResolution": "bundler",
|
||||
"allowImportingTsExtensions": true
|
||||
}
|
||||
// Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias and https://kit.svelte.dev/docs/configuration#files
|
||||
//
|
||||
// If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes
|
||||
// from the referenced tsconfig.json - TypeScript does not merge them in
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
{
|
||||
"name": "deprived-main-website",
|
||||
"version": "0.0.1",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "vite dev",
|
||||
"build": "vite build",
|
||||
"preview": "vite preview",
|
||||
"check": "svelte-kit sync && svelte-check --tsconfig ./jsconfig.json",
|
||||
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./jsconfig.json --watch"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@sveltejs/adapter-auto": "^3.0.0",
|
||||
"@sveltejs/adapter-static": "^3.0.1",
|
||||
"@sveltejs/kit": "^2.0.0",
|
||||
"@sveltejs/vite-plugin-svelte": "^3.0.0",
|
||||
"@zerodevx/svelte-img": "^2.1.0",
|
||||
"svelte": "^4.2.7",
|
||||
"svelte-check": "^3.6.0",
|
||||
"svelte-highlight": "^7.6.0",
|
||||
"svelte-parallax": "^0.6.0",
|
||||
"typescript": "^5.0.0",
|
||||
"vite": "^5.0.3"
|
||||
},
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"svelte-media-queries": "^1.6.2"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
// See https://kit.svelte.dev/docs/types#app
|
||||
// for information about these interfaces
|
||||
declare global {
|
||||
namespace App {
|
||||
// interface Error {}
|
||||
// interface Locals {}
|
||||
// interface PageData {}
|
||||
// interface PageState {}
|
||||
// interface Platform {}
|
||||
}
|
||||
}
|
||||
|
||||
export {};
|
|
@ -0,0 +1,17 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
|
||||
<!-- Change theme for site here -->
|
||||
<link rel="stylesheet" href="/stylesheets/main-theme.css" />
|
||||
<link rel="stylesheet" href="/stylesheets/global.css" />
|
||||
|
||||
%sveltekit.head%
|
||||
|
||||
</head>
|
||||
|
||||
<div style="display: contents">%sveltekit.body%</div>
|
||||
</html>
|
|
@ -0,0 +1,12 @@
|
|||
<div {...$$restProps}>
|
||||
<slot></slot>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.centralize{
|
||||
display: grid;
|
||||
justify-content: center;
|
||||
|
||||
padding: 0;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,4 @@
|
|||
<!-- Just used for ease of read -->
|
||||
<div style="padding: 0;">
|
||||
<slot></slot>
|
||||
</div>
|
|
@ -0,0 +1,8 @@
|
|||
<div class="grow" />
|
||||
|
||||
<style>
|
||||
.grow{
|
||||
display: flex;
|
||||
flex-grow: 1;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,15 @@
|
|||
<script lang="ts">
|
||||
import HorizonalStack from "../Utils/HorizonalStack.svelte";
|
||||
import TimelineItem from "./timelineItem.svelte";
|
||||
</script>
|
||||
|
||||
<HorizonalStack {...$$restProps}>
|
||||
<slot/>
|
||||
</HorizonalStack>
|
||||
|
||||
<style>
|
||||
.JustifyStart{
|
||||
display: flex;
|
||||
justify-content: start;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,100 @@
|
|||
<script lang="ts">
|
||||
import HorizonalStack from "../Utils/HorizonalStack.svelte";
|
||||
import Img from '@zerodevx/svelte-img'
|
||||
import VerticalStack from "../Utils/VerticalStack.svelte";
|
||||
import ZSpacer from "../Utils/ZSpacer.svelte";
|
||||
import MediaQuery from 'svelte-media-queries';
|
||||
|
||||
// Set these when using the component
|
||||
export let date: string = "null";
|
||||
export let imagePath: string = "null";
|
||||
export let title: string = "null";
|
||||
export let desc: string = "null";
|
||||
|
||||
const timelineCollapseThreshhold : string = '1000px';
|
||||
let timelineCollaped: boolean = false;
|
||||
</script>
|
||||
|
||||
<MediaQuery query='(max-width: {timelineCollapseThreshhold})' bind:matches={timelineCollaped} />
|
||||
|
||||
<div class="flexStart timelineItemContainer" style="overflow: auto;">
|
||||
<div style="padding-top: 10px;">
|
||||
{#if imagePath !== "null"}
|
||||
<div class="imageContainer">
|
||||
<img src={imagePath} class="image" alt="nothing"/>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="ItemStrip"/>
|
||||
<div class="noPadding">
|
||||
<div class="title">{@html title}</div>
|
||||
<div class="DateText">{@html date}</div>
|
||||
<div class="bodyText">{@html desc}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.imageContainer {
|
||||
position: relative;
|
||||
z-index: -1;
|
||||
|
||||
width: 10vw;
|
||||
height: 10vw;
|
||||
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.imageContainer img{
|
||||
position: absolute;
|
||||
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
|
||||
min-width: 100%;
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
.timelineItemContainer{
|
||||
column-gap: 3vw;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.noPadding{
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.flexStart{
|
||||
display: flex;
|
||||
justify-content: start;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 200%;
|
||||
|
||||
display: flex;
|
||||
align-content: center;
|
||||
}
|
||||
|
||||
.bodyText{
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.DateText{
|
||||
margin: 0;
|
||||
margin-bottom: 0.5rem;
|
||||
|
||||
color: darkgray;
|
||||
|
||||
display: flex;
|
||||
align-self: flex-start;
|
||||
}
|
||||
|
||||
.ItemStrip{
|
||||
min-width: 5px;
|
||||
display: inline-flex;
|
||||
|
||||
position: relative;
|
||||
|
||||
background-color: rgb(178, 178, 178);
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,66 @@
|
|||
<script lang="ts">
|
||||
import { ButtonType } from "$lib/IO/ButtonType.ts";
|
||||
import { onMount } from "svelte";
|
||||
|
||||
export let href : string = "#";
|
||||
export let type : ButtonType = ButtonType.Primary;
|
||||
let cssName : string;
|
||||
|
||||
const buttonTypeColors = {
|
||||
[ButtonType.Primary]: '--primary',
|
||||
[ButtonType.Secondary]: '--secondary',
|
||||
[ButtonType.Accent]: '--accent',
|
||||
};
|
||||
|
||||
onMount(() => {
|
||||
cssName = buttonTypeColors[type];
|
||||
});
|
||||
</script>
|
||||
|
||||
<a href={href} class="button" style="--button-color: var({cssName});">
|
||||
<div class="content">
|
||||
<slot name="content">
|
||||
Click Me!
|
||||
</slot>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<style>
|
||||
.button {
|
||||
white-space: nowrap;
|
||||
border-radius: 6px;
|
||||
border: none;
|
||||
background-color: var(--button-color);
|
||||
text-decoration: none;
|
||||
|
||||
transition: transform 100ms ease-in-out;
|
||||
transform: translate(0, 0);
|
||||
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
font-size: 1.5em;
|
||||
|
||||
box-shadow: 5px 5px 10px 2px rgba(0, 0, 0, 0.3);
|
||||
padding: 0.8em 4em;
|
||||
}
|
||||
|
||||
.button:hover {
|
||||
transition: transform 100ms ease-in-out;
|
||||
transform: translate(0, -5px);
|
||||
|
||||
cursor: pointer;
|
||||
|
||||
filter: brightness(130%);
|
||||
}
|
||||
|
||||
.content {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
color: var(--text1);
|
||||
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-content: center;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,5 @@
|
|||
export enum ButtonType {
|
||||
Primary,
|
||||
Secondary,
|
||||
Accent
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
<script lang="ts">
|
||||
export let post_url : string = '404';
|
||||
export let thumbnail_url : string = '/favicon.png';
|
||||
export let thumbnail_alt : string = 'Picture describting the deprived devs logo';
|
||||
export let title : string = '<title>';
|
||||
export let summary : string = '<summary>';
|
||||
export let creation_date : string = '<date>';
|
||||
|
||||
const monthNames : string[] = ["January", "February", "March", "April", "May", "June",
|
||||
"July", "August", "September", "October", "November", "December"];
|
||||
|
||||
$: human_creation_date = new Date(+creation_date * 1000);
|
||||
</script>
|
||||
|
||||
<div class="news-card">
|
||||
<a href=/post/{post_url}>
|
||||
<div class="thumbnail">
|
||||
<img src={thumbnail_url} alt={thumbnail_alt}/>
|
||||
</div>
|
||||
<div class="content">
|
||||
<h3 id="title">{title}</h3>
|
||||
<p id="summary-text">{summary}</p>
|
||||
<p id="date">
|
||||
{human_creation_date.getDate()}
|
||||
{monthNames[human_creation_date.getMonth()]}
|
||||
{human_creation_date.getFullYear()}
|
||||
</p>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
a {
|
||||
text-decoration: none;
|
||||
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 15px;
|
||||
}
|
||||
|
||||
.thumbnail > img {
|
||||
object-fit: cover;
|
||||
|
||||
box-shadow: 5px 5px 10px 2px rgba(0, 0, 0, 0.5);
|
||||
border-radius: 8px;
|
||||
|
||||
width: 150px;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.content {
|
||||
flex-shrink: 2;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
#title {
|
||||
margin: 0;
|
||||
text-decoration: none;
|
||||
color: var(--text2);
|
||||
}
|
||||
|
||||
#summary-text {
|
||||
margin: 0;
|
||||
text-decoration: none;
|
||||
color: var(--text3);
|
||||
}
|
||||
|
||||
#date {
|
||||
margin: 0;
|
||||
text-decoration: none;
|
||||
color: var(--text4);
|
||||
}
|
||||
|
||||
</style>
|
|
@ -0,0 +1,79 @@
|
|||
<script lang="ts">
|
||||
export let post_url : string = '404';
|
||||
export let thumbnail_url : string = '/favicon.png';
|
||||
export let thumbnail_alt : string = 'Picture describting the deprived devs logo';
|
||||
export let title : string = '<title>';
|
||||
export let summary : string = '<summary>';
|
||||
export let creation_date : string = '<date>';
|
||||
|
||||
const monthNames : string[] = ["January", "February", "March", "April", "May", "June",
|
||||
"July", "August", "September", "October", "November", "December"];
|
||||
|
||||
$: human_creation_date = new Date(+creation_date * 1000);
|
||||
</script>
|
||||
|
||||
<div class="news-card">
|
||||
<a href={post_url}>
|
||||
<div class="thumbnail">
|
||||
<img src={thumbnail_url} alt={thumbnail_alt}/>
|
||||
</div>
|
||||
<div class="content">
|
||||
<p id="date">
|
||||
{human_creation_date.getDate()}
|
||||
{monthNames[human_creation_date.getMonth()]}
|
||||
{human_creation_date.getFullYear()}
|
||||
</p>
|
||||
<h3 id="title">{title}</h3>
|
||||
<p id="summary-text">{summary}</p>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.news-card {
|
||||
flex: 0 0 300px;
|
||||
}
|
||||
|
||||
a {
|
||||
min-width: 100%;
|
||||
text-decoration: none;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.thumbnail > img {
|
||||
object-fit: cover;
|
||||
|
||||
box-shadow: 5px 5px 10px 2px rgba(0, 0, 0, 0.5);
|
||||
border-radius: 8px;
|
||||
|
||||
min-width: 100%;
|
||||
aspect-ratio: 16 / 9;
|
||||
}
|
||||
|
||||
.content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
#title {
|
||||
font-size: 22px;
|
||||
margin: 0;
|
||||
text-decoration: none;
|
||||
color: var(--text2);
|
||||
}
|
||||
|
||||
#summary-text {
|
||||
margin: 0;
|
||||
text-decoration: none;
|
||||
color: var(--text3);
|
||||
}
|
||||
|
||||
#date {
|
||||
margin: 0;
|
||||
text-decoration: none;
|
||||
color: var(--text4);
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,78 @@
|
|||
<script>
|
||||
export let post_url = '404';
|
||||
export let thumbnail_url = '/favicon.png';
|
||||
export let thumbnail_alt = 'Picture describting the deprived devs logo';
|
||||
export let title = '<title>';
|
||||
export let summary = '<summary>';
|
||||
export let creation_date = 1710006969;
|
||||
|
||||
const monthNames = ["January", "February", "March", "April", "May", "June",
|
||||
"July", "August", "September", "October", "November", "December"];
|
||||
|
||||
$: human_creation_date = new Date(+creation_date * 1000);
|
||||
</script>
|
||||
|
||||
<div class="news-card">
|
||||
<a href=/post/{post_url} >
|
||||
<div title={thumbnail_alt} class="thumbnail" style="background-image: url({thumbnail_url});">
|
||||
</div>
|
||||
<div class="content">
|
||||
<h3 id="title">{title}</h3>
|
||||
<p id="summary-text">{summary}</p>
|
||||
<p id="date">{human_creation_date.getDate()} {monthNames[human_creation_date.getMonth()]} {human_creation_date.getFullYear()}</p>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.news-card {
|
||||
display: inline-flex;
|
||||
flex-direction: column;
|
||||
gap: 15px;
|
||||
}
|
||||
|
||||
.news-card h3 {
|
||||
color: var(--text1);
|
||||
margin: 0px;
|
||||
font-size: 22px;
|
||||
}
|
||||
|
||||
.thumbnail {
|
||||
aspect-ratio: 16 / 9;
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
|
||||
box-shadow: 5px 5px 10px 2px rgba(0, 0, 0, 0.5);
|
||||
border-radius: 8px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
#title {
|
||||
margin: 0;
|
||||
text-decoration: none;
|
||||
color: var(--text1);
|
||||
}
|
||||
|
||||
#summary-text {
|
||||
margin: 0;
|
||||
text-decoration: none;
|
||||
color: var(--text2);
|
||||
}
|
||||
|
||||
#date {
|
||||
margin: 0;
|
||||
text-decoration: none;
|
||||
color: var(--text4);
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* Provides post summaries to all pages. That means every page can access summaries
|
||||
* for all posts on the website.
|
||||
*/
|
||||
|
||||
import { type Post, posts } from './posts/posts_data';
|
||||
|
||||
export function load() {
|
||||
let summaries : Post[] = [];
|
||||
|
||||
// Sort by newest news first
|
||||
posts.sort((a, b) => b.creation_date - a.creation_date);
|
||||
|
||||
posts.forEach((post) => {
|
||||
summaries.push(post);
|
||||
});
|
||||
|
||||
return { summaries };
|
||||
}
|
|
@ -0,0 +1,244 @@
|
|||
<script lang="ts">
|
||||
import { fly } from 'svelte/transition';
|
||||
import MediaQuery from 'svelte-media-queries';
|
||||
|
||||
const footerCollapseThreshold : string = '1000px';
|
||||
const headerCollapseThreshold : string = '1000px';
|
||||
let footerCollapse : boolean;
|
||||
let headerCollapse : boolean;
|
||||
|
||||
let navbarHidden : boolean = true;
|
||||
|
||||
function resetNavBar() {
|
||||
navbarHidden = true;
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- Detect mobile -->
|
||||
<MediaQuery query='(max-width: {footerCollapseThreshold})' bind:matches={footerCollapse} />
|
||||
<MediaQuery query='(max-width: {headerCollapseThreshold})' bind:matches={headerCollapse} />
|
||||
|
||||
<!-- Nav bar -->
|
||||
<header>
|
||||
<div class="nav-bar">
|
||||
{#if !headerCollapse}
|
||||
<div class="desktop">
|
||||
<a href="/" class="nav-head">
|
||||
<img id="logo-link" src="/images/logo.png" alt="The Deprived Devs Logo"/>
|
||||
<h3 id="logo-text">The Deprived Devs</h3>
|
||||
</a>
|
||||
<div class="nav-spacer" />
|
||||
<a href="/">Home</a>
|
||||
<a href="/games">Games</a>
|
||||
<a href="/posts">Blog</a>
|
||||
<a href="/about">About</a>
|
||||
</div>
|
||||
{:else}
|
||||
<div class="collapsed">
|
||||
<a on:click={resetNavBar} href="/" class="nav-head">
|
||||
<img id="logo-link" src="/images/logo.png" alt="The Deprived Devs Logo"/>
|
||||
<h3 id="logo-text">The Deprived Devs</h3>
|
||||
</a>
|
||||
<div class="nav-spacer" />
|
||||
<button id="toggle-nav" on:click={() => navbarHidden = !navbarHidden}>
|
||||
<img src="/images/icons/hamburger_menu.svg" alt="Toggle Navigation Bar" />
|
||||
</button>
|
||||
</div>
|
||||
{#if !navbarHidden}
|
||||
<div class="nav-list" transition:fly={{ y: -25, duration: 350 }}>
|
||||
<a on:click={resetNavBar} href="/">Home</a>
|
||||
<a on:click={resetNavBar} href="/games">Games</a>
|
||||
<a on:click={resetNavBar} href="/posts">Blog</a>
|
||||
<a on:click={resetNavBar} href="/about">About</a>
|
||||
</div>
|
||||
{/if}
|
||||
{/if}
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- Page content -->
|
||||
<slot />
|
||||
|
||||
<!-- About footer -->
|
||||
<footer>
|
||||
<div class="about-container">
|
||||
<div class="credits">
|
||||
<span>© 2023-2024</span>
|
||||
<br>
|
||||
<span>Benjamin Dreyer</span>
|
||||
<br>
|
||||
<span>Oliver Schwenger</span>
|
||||
<br>
|
||||
<span>Sylvester Junge</span>
|
||||
<br>
|
||||
<span>Zhentao Wei</span>
|
||||
<br>
|
||||
<br>
|
||||
<span>Website <a href="https://gitea.deprived.dev/Sveskejuice/deprived-main-website" target="_blank">source code</a></span>
|
||||
</div>
|
||||
<div>
|
||||
<h3>About Us</h3>
|
||||
<a href="/about">About</a>
|
||||
</div>
|
||||
<div class="contact">
|
||||
<h3>Contact</h3>
|
||||
<a href="https://discord.gg/awatEEqc3M" target="_blank" class="social">
|
||||
<img src="/images/icons/discord.svg" alt="Discord"/>
|
||||
<span>Discord</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
|
||||
<style>
|
||||
/* Nav bar. */
|
||||
header {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
header a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.nav-bar {
|
||||
width: 100%;
|
||||
max-width: 1400px;
|
||||
}
|
||||
|
||||
.desktop {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
gap: 30px;
|
||||
}
|
||||
|
||||
.collapsed {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
#toggle-nav {
|
||||
background: transparent;
|
||||
border: none;
|
||||
}
|
||||
|
||||
|
||||
.nav-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.nav-head {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
#logo-link {
|
||||
width: 64px;
|
||||
aspect-ratio: 1 / 1;
|
||||
}
|
||||
|
||||
#logo-text {
|
||||
font-size: 24px;
|
||||
color: var(--text2);
|
||||
font-family: var(--title-font);
|
||||
margin: 0;
|
||||
|
||||
min-width: 200px;
|
||||
}
|
||||
|
||||
.nav-spacer {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
header a {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
font-size: 22px;
|
||||
font-family: var(--title-font);
|
||||
color: var(--text2);
|
||||
}
|
||||
|
||||
/* Footer. */
|
||||
footer {
|
||||
margin-top: 50px;
|
||||
padding: 25px 0;
|
||||
background-color: var(--background1);
|
||||
|
||||
height: 100%;
|
||||
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.about-container {
|
||||
width: 80%;
|
||||
height: 100%;
|
||||
|
||||
color: var(--text2);
|
||||
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-evenly;
|
||||
}
|
||||
|
||||
.about-container > div {
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.credits {
|
||||
line-height: 2;
|
||||
}
|
||||
|
||||
.contact {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.social {
|
||||
display: flex;
|
||||
align-content: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.social > img {
|
||||
width: 24px;
|
||||
}
|
||||
|
||||
footer h3 {
|
||||
margin-top: 0px;
|
||||
color: var(--text2);
|
||||
}
|
||||
|
||||
footer a {
|
||||
color: var(--text2);
|
||||
text-decoration-line: underline;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
filter: brightness(130%);
|
||||
}
|
||||
</style>
|
||||
|
||||
{#if footerCollapse}
|
||||
<style>
|
||||
.about-container {
|
||||
flex-direction: column;
|
||||
justify-content: center !important;
|
||||
gap: 25px;
|
||||
}
|
||||
</style>
|
||||
{/if}
|
||||
|
||||
{#if headerCollapse}
|
||||
<style>
|
||||
|
||||
</style>
|
||||
{/if}
|
|
@ -0,0 +1 @@
|
|||
export const prerender = true;
|
|
@ -0,0 +1,156 @@
|
|||
<script lang="ts">
|
||||
import MediaQuery from 'svelte-media-queries';
|
||||
import NewsCard from '$lib/posts/NewsCard.svelte';
|
||||
import ShowcaseNewsCard from '$lib/posts/ShowcaseNewsCard.svelte';
|
||||
import Button from '$lib/IO/Button.svelte';
|
||||
import { ButtonType } from '$lib/IO/ButtonType.ts';
|
||||
import Timeline from '../comps/timeline/timeline.svelte';
|
||||
|
||||
export let data; // <- contains post data
|
||||
|
||||
$: most_recent_post = data.summaries[0];
|
||||
|
||||
const mobileThreshold : string = '1000px';
|
||||
let mobile : boolean;
|
||||
const post_show_count : number = 3;
|
||||
</script>
|
||||
|
||||
<!-- Detect mobile -->
|
||||
<MediaQuery query='(max-width: {mobileThreshold})' bind:matches={mobile} />
|
||||
|
||||
<div class="main-title">
|
||||
<h1>The Deprived Devs</h1>
|
||||
</div>
|
||||
|
||||
|
||||
<section id="news-section">
|
||||
<header id="news-header">
|
||||
<h1>Recent News</h1>
|
||||
</header>
|
||||
<div class="news-container">
|
||||
<!-- The newest blog post being showcased -->
|
||||
<div class="showcase">
|
||||
<ShowcaseNewsCard
|
||||
thumbnail_url={most_recent_post.cover_img}
|
||||
thumbnail_alt={most_recent_post.cover_alt}
|
||||
post_url={most_recent_post.url}
|
||||
title={most_recent_post.title}
|
||||
summary={most_recent_post.summary}
|
||||
creation_date={most_recent_post.creation_date}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="news-list">
|
||||
{#each data.summaries.slice(1, post_show_count) as summary}
|
||||
<NewsCard
|
||||
thumbnail_url={summary.cover_img}
|
||||
thumbnail_alt={summary.cover_alt}
|
||||
post_url={summary.url}
|
||||
title={summary.title}
|
||||
summary={summary.summary}
|
||||
creation_date={summary.creation_date}
|
||||
/>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
<footer id="news-footer">
|
||||
<div class="dummy"/>
|
||||
<div id="more-posts">
|
||||
<Button href="/posts" type={ButtonType.Primary}>
|
||||
<span slot="content">More News</span>
|
||||
</Button>
|
||||
</div>
|
||||
</footer>
|
||||
</section>
|
||||
|
||||
<Timeline/>
|
||||
|
||||
<style>
|
||||
#news-section {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
|
||||
transition-duration: 500ms;
|
||||
transition-property: width;
|
||||
width: 80%;
|
||||
max-width: 1400px;
|
||||
margin-inline: auto;
|
||||
}
|
||||
|
||||
#news-header {
|
||||
font-size: min(8vw, 36px);
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.news-container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 25px;
|
||||
|
||||
width: 100%;
|
||||
align-items: left;
|
||||
}
|
||||
|
||||
.news-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
#news-footer {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
|
||||
margin-top: 25px;
|
||||
}
|
||||
|
||||
.dummy {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#more-posts {
|
||||
flex-grow: 1;
|
||||
min-width: 10em;
|
||||
}
|
||||
|
||||
.main-title {
|
||||
color: var(--text1);
|
||||
margin: 0 auto;
|
||||
width: 80%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.main-title > h1 {
|
||||
font-size: 9vw; /* Change if title changes */
|
||||
}
|
||||
|
||||
.main-title {
|
||||
font-family: var(--title-font);
|
||||
color: var(--text1);
|
||||
}
|
||||
</style>
|
||||
|
||||
{#if mobile}
|
||||
<style>
|
||||
#news-section {
|
||||
transition-duration: 500ms;
|
||||
transition-property: width;
|
||||
width: 90% !important;
|
||||
}
|
||||
.news-container {
|
||||
flex-direction: column !important;
|
||||
}
|
||||
|
||||
.dummy {
|
||||
width: 0% !important;
|
||||
}
|
||||
|
||||
/* #more-posts { */
|
||||
/* flex-grow: 1 !important; */
|
||||
/* } */
|
||||
|
||||
</style>
|
||||
{/if}
|
||||
|
|
@ -0,0 +1 @@
|
|||
<p>This is an informative about page :) </p>
|
|
@ -0,0 +1 @@
|
|||
WIP
|
|
@ -0,0 +1,92 @@
|
|||
<!-- Layout for posts -->
|
||||
<script lang="ts">
|
||||
import { type BlogData } from './+layout';
|
||||
|
||||
export let data : BlogData
|
||||
|
||||
const monthNames : string[] = ["January", "February", "March", "April", "May", "June",
|
||||
"July", "August", "September", "October", "November", "December"];
|
||||
function humanDate(date : Date) : string {
|
||||
return `${date.getDate()} ${monthNames[date.getMonth()]} ${date.getFullYear()}`;
|
||||
}
|
||||
</script>
|
||||
|
||||
<article>
|
||||
<div class="body">
|
||||
<header>
|
||||
<img id="blog-cover-img" src={data.post.cover_img} alt={data.post.cover_alt} />
|
||||
<h3 id="title">{data.post.title}</h3>
|
||||
<div class="dates">
|
||||
<span class="date">Created {humanDate(new Date(+data.post.creation_date * 1000))}</span>
|
||||
<span class="date">Last Modified {humanDate(new Date(+data.post.modification_date * 1000))}</span>
|
||||
</div>
|
||||
</header>
|
||||
<div class="content">
|
||||
<slot />
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
|
||||
<style>
|
||||
article {
|
||||
margin-top: 25px;
|
||||
margin-inline: auto;
|
||||
max-width: 1000px;
|
||||
|
||||
/* background: var(--background1); */
|
||||
}
|
||||
|
||||
header {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
margin-bottom: 50px;
|
||||
}
|
||||
|
||||
#blog-cover-img {
|
||||
aspect-ratio: 16 / 9;
|
||||
max-width: 100%;
|
||||
|
||||
border-radius: 0.5rem;
|
||||
}
|
||||
|
||||
#title {
|
||||
font-family: var(--title-font);
|
||||
font-size: 36px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.dates {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
flex-wrap: wrap;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.date {
|
||||
color: var(--text3);
|
||||
}
|
||||
|
||||
.body {
|
||||
margin-inline: auto;
|
||||
max-width: 1200px;
|
||||
padding: 25px;
|
||||
}
|
||||
|
||||
.content {
|
||||
line-height: 2;
|
||||
font-size: 18px;
|
||||
text-rendering: optimizeLegibility;
|
||||
}
|
||||
|
||||
/* CSS for posts - child rooutes. */
|
||||
img {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
:global(a) {
|
||||
color: var(--text1);
|
||||
text-decoration-line: underline;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,17 @@
|
|||
import { posts, type Post } from '../posts/posts_data';
|
||||
|
||||
export interface BlogData {
|
||||
summaries: Post[],
|
||||
post: Post
|
||||
}
|
||||
|
||||
export async function load({ url, parent }) : Promise<BlogData> {
|
||||
const { summaries } = await parent();
|
||||
const websiteUrl = url.pathname.split('/');
|
||||
const windowUrl = websiteUrl.pop() || websiteUrl.pop(); // Handle trailing /
|
||||
|
||||
return {
|
||||
summaries: summaries,
|
||||
post: posts.filter((post) => post.url == windowUrl)[0],
|
||||
};
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
<div class="post-container">
|
||||
<div class="post-header">
|
||||
<slot name="title" />
|
||||
<slot name="creation-date" />
|
||||
<slot name="modification-date" />
|
||||
|
||||
<!-- the post content goes in this slot -->
|
||||
<slot />
|
||||
</div>
|
||||
</div>
|
|
@ -0,0 +1,2 @@
|
|||
Lorem ipsum dolor sit amet, officia excepteur ex fugiat reprehenderit enim labore culpa sint ad nisi Lorem pariatur mollit ex esse exercitation amet. Nisi anim cupidatat excepteur officia. Reprehenderit nostrud nostrud ipsum Lorem est aliquip amet voluptate voluptate dolor minim nulla est proident. Nostrud officia pariatur ut officia. Sit irure elit esse ea nulla sunt ex occaecat reprehenderit commodo officia dolor Lorem duis laboris cupidatat officia voluptate. Culpa proident adipisicing id nulla nisi laboris ex in Lorem sunt duis officia eiusmod. Aliqua reprehenderit commodo ex non excepteur duis sunt velit enim. Voluptate laboris sint cupidatat ullamco ut ea consectetur et est culpa et culpa duis.
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
<script>
|
||||
import Highlight from "svelte-highlight";
|
||||
import { shell } from "svelte-highlight/languages";
|
||||
import obsidian from "svelte-highlight/styles/obsidian";
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
{@html obsidian}
|
||||
</svelte:head>
|
||||
|
||||
<p>
|
||||
Finding the specific commit that introduced a bug in your code can be frustrating,
|
||||
especially in big projects with a lot of commits. Git bisecting is a method
|
||||
used to quickly find which commit is the culprit. Git bisect works by you specifying
|
||||
a so called 'bad' commit where you know the bug occurs and a commit where you know the
|
||||
bug doesn't occur. Afterwards git will binary search it's way to find the commit
|
||||
introducing the bug.
|
||||
</p>
|
||||
<p>
|
||||
Suppose we've the following git history:
|
||||
</p>
|
||||
|
||||
<img src="/images/posts/git-bisecting/bisect_problem.png" alt="Showing a git history, where on the left there is a 'good' commit with a couple of commits between the current commit on the right"/>
|
||||
<p>
|
||||
It could potentially contain many more commits between the known 'good' commit and the
|
||||
current one. Somewhere in the commits 1, 2, 3, 4 or the current one, a bug was
|
||||
introduced. One way to find the specific commit that introduced the bug, could
|
||||
be to check each commit starting from commit 1 then 2 then 3 ... and so on.
|
||||
This is known as a linear search, and would take very long if there are a lot
|
||||
of commits between the bad and the current.
|
||||
</p>
|
||||
<p>
|
||||
Instead git bisect comes to the rescue. Git bisect performs a
|
||||
<a href="https://en.wikipedia.org/wiki/Binary_search_algorithm" target="_blank">binary search</a>,
|
||||
which is much faster.
|
||||
To use git bisect, you must tell git to start bisecting:
|
||||
</p>
|
||||
<Highlight language={shell} code="$ git bisect start" />
|
||||
<p>
|
||||
Afterwards we mark the 'bad' commit - any commit we know the bug occurs in. In this example
|
||||
the current commit that we know is bad have the commit hash <code>c26cf8a</code>, so
|
||||
we mark the commit bad:
|
||||
</p>
|
||||
<Highlight language={shell} code="$ git bisect bad c26cf8a" />
|
||||
<p>
|
||||
After that we mark a previous commit that we know the bug doesn't occur in. In this
|
||||
example it's the 'good' commit (se picture above), which has a commit hash of <code>b34ec52</code>
|
||||
</p>
|
||||
<Highlight language={shell} code="$ git bisect good b34ec52" />
|
||||
<p>
|
||||
Now git will automatically checkout a commit somewhere in between the good and bad commit.
|
||||
Your job is now to re-build your project and test if the bug occurs. If the bug
|
||||
<b>doesn't</b> occur you report it to git:
|
||||
</p>
|
||||
<Highlight language={shell} code="$ git bisect good" />
|
||||
<p>
|
||||
However if it does occur you mark it bad:
|
||||
</p>
|
||||
<Highlight language={shell} code="$ git bisect bad" />
|
||||
<p>
|
||||
You continue to do this until git has tracked down the first bad commit, ie. the
|
||||
commit that introduced the bug.
|
||||
</p>
|
||||
|
||||
<h2>Resources</h2>
|
||||
Git bisect man page: <a href="https://git-scm.com/docs/git-bisect">https://git-scm.com/docs/git-bisect</a>
|
|
@ -0,0 +1,81 @@
|
|||
<script lang="ts">
|
||||
import { type Post } from './posts_data';
|
||||
import NewsVerticalCard from '$lib/posts/NewsVerticalCard.svelte';
|
||||
|
||||
export let data; // <- contains post data
|
||||
|
||||
let search : string;
|
||||
$: regex = search ? new RegExp(search, 'i') : null;
|
||||
$: matches = (item : Post) =>
|
||||
regex ? regex.test(item.title) || regex.test(item.summary) : true;
|
||||
$: matched_posts = data.summaries.filter(matches);
|
||||
</script>
|
||||
|
||||
<div class="head">
|
||||
<header>
|
||||
<h1>Blog Posts</h1>
|
||||
<input id="search" placeholder="Search Blog Posts" bind:value={search} />
|
||||
</header>
|
||||
</div>
|
||||
|
||||
<div class="list">
|
||||
{#if matched_posts.length == 0}
|
||||
<span>No Matches</span>
|
||||
{/if}
|
||||
{#each matched_posts as summary}
|
||||
<NewsVerticalCard
|
||||
post_url="/post/{summary.url}"
|
||||
title={summary.title}
|
||||
summary={summary.summary}
|
||||
creation_date={summary.creation_date.toString()}
|
||||
/>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
h1 {
|
||||
font-size: 48px;
|
||||
font-family: var(--title-font);
|
||||
}
|
||||
.head {
|
||||
width: 100%;
|
||||
background-color: var(--primary);
|
||||
}
|
||||
|
||||
header {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
||||
align-content: center;
|
||||
justify-content: space-around;
|
||||
|
||||
padding: 0 0 20px 0;
|
||||
margin-bottom: 25px;
|
||||
}
|
||||
|
||||
#search {
|
||||
height: 40px;
|
||||
|
||||
align-self: center;
|
||||
border: none;
|
||||
border-radius: 10px;
|
||||
font-size: 18px;
|
||||
line-height: 2;
|
||||
padding: 0.5rem 0.8rem;
|
||||
margin-top: 0px;
|
||||
|
||||
background-color: var(--background);
|
||||
color: var(--text1);
|
||||
}
|
||||
|
||||
.list {
|
||||
max-width: 1500px;
|
||||
margin-inline: auto;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 25px;
|
||||
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
</style>
|
|
@ -0,0 +1,53 @@
|
|||
// TODO: document members
|
||||
export type Post = {
|
||||
// Required
|
||||
url : string,
|
||||
cover_img : string,
|
||||
cover_alt : string,
|
||||
title: string,
|
||||
summary : string,
|
||||
creation_date : number
|
||||
modification_date: number,
|
||||
|
||||
// Optional
|
||||
// TODO: author?
|
||||
}
|
||||
|
||||
export const posts : Post[] = [
|
||||
{
|
||||
url: 'git-bisecting',
|
||||
cover_img: '/images/posts/git-bisecting/thumbnail.png',
|
||||
cover_alt: 'Photo of a bug',
|
||||
title: 'Tracking down bugs in your code — using git bisect',
|
||||
summary: 'Track down which specific change introduced a bug using the binary search tool provided by git.',
|
||||
creation_date: 1709907213,
|
||||
modification_date: 1709907213,
|
||||
},
|
||||
{
|
||||
url: 'folder-icons',
|
||||
cover_img: '/images/posts/folder-icons/cover.png',
|
||||
cover_alt: 'Image of folder icons being used in the editor',
|
||||
title: 'Amazing Icons for Folders in Unity!',
|
||||
summary: 'See how you can use Zhen\'s folder icons for Unity to boost your developer experience',
|
||||
creation_date: 1708382491,
|
||||
modification_date: 1708382491,
|
||||
},
|
||||
{
|
||||
url: 'lorem',
|
||||
cover_img: '/images/posts/folder-icons/cover.png',
|
||||
cover_alt: 'Lorem ipsum dolor sit amet, qui minim labore adipisicing minim sint cillum sint consectetur cupidatat.',
|
||||
title: 'Lorem Ipsum !!',
|
||||
summary: 'This is a nice exploanation on lorem ipsum latin',
|
||||
creation_date: 1708382491,
|
||||
modification_date: 1708382491,
|
||||
},
|
||||
{
|
||||
url: 'lorem1',
|
||||
cover_img: '/images/posts/folder-icons/cover.png',
|
||||
cover_alt: 'Lorem ipsum dolor sit amet, qui minim labore adipisicing minim sint cillum sint consectetur cupidatat.',
|
||||
title: 'Idk some arcticle bruh!',
|
||||
summary: 'Lorem ipsum dolor sit amet, qui minim labore adipisicing minim sint cillum sint consectetur cupidatat.',
|
||||
creation_date: 1708558377,
|
||||
modification_date: 1708558377,
|
||||
},
|
||||
];
|
|
@ -0,0 +1,13 @@
|
|||
<script lang="ts">
|
||||
import TopAnimatedBackground from "./Comps/TopAnimatedBackground.svelte";
|
||||
import { Parallax, ParallaxLayer, StickyLayer } from "svelte-parallax";
|
||||
import ZhenAboutMe from "./Comps/AboutMe.svelte"
|
||||
</script>
|
||||
|
||||
<Parallax sections={2} config={{ stiffness: 0.1, damping: 0.3 }}>
|
||||
<TopAnimatedBackground/>
|
||||
|
||||
<ParallaxLayer rate={0.5} offset={0.5} style="background-color: var(--background);">
|
||||
<ZhenAboutMe/>
|
||||
</ParallaxLayer>
|
||||
</Parallax>
|
|
@ -0,0 +1,67 @@
|
|||
<script lang="ts">
|
||||
import Timeline from "../../../comps/timeline/timeline.svelte";
|
||||
import TimelineItem from "../../../comps/timeline/timelineItem.svelte";
|
||||
</script>
|
||||
|
||||
<Timeline style="padding: 2rem; padding-left: 3vw; padding-bottom: 5rem;">
|
||||
<TimelineItem
|
||||
date="1.G 2021"
|
||||
desc='Dette initiativ involverede implementeringen af et avanceret værktøj fra Google kendt som "teachable machine", som blev konfigureret til at identificere en række håndudtryk. Med en kompleks kombination af maskinlæringsteknikker og datadrevne algoritmer blev dette projekt realiseret med ekspertise og præcision. Ved at udnytte avancerede neurale netværk og dybdegående datasæt muliggjorde dette værktøj en dybtgående analyse af de subtile nuancer i håndgester, hvilket resulterede i en imponerende nøjagtighed og pålidelighed i genkendelsen af disse udtryk. Dette projekt repræsenterer et skridt fremad i feltet for computer vision og maskinlæring, og det illustrerer potentialet i at anvende avancerede teknologier til at løse komplekse problemer inden for menneske-maskine-interaktion.'
|
||||
title="Machine learning: gesture recognition"
|
||||
imagePath="sveske_files/thumb_005.png"
|
||||
/>
|
||||
<TimelineItem
|
||||
date="1.G 2022"
|
||||
desc="Denne applikation, konstrueret i AppLab, agerer som en præcis katalysator, der faciliterer forståelsen af de 13 globale bæredygtighedsmål fastsat af De Forenede Nationer. Med en intuitiv brugergrænseflade og en enestående funktionalitet præsenterer den en omfattende oversigt over disse komplekse mål, hvilket muliggør en dybdegående indsigt i de multidimensionelle aspekter af global udvikling. Med en elegant integration af avancerede algoritmer og interaktive elementer guider denne app brugeren gennem et labyrintisk landskab af komplekse socioøkonomiske og miljømæssige koncepter, hvilket fremmer en dybere forståelse og engagement i bestræbelserne på at opnå en mere bæredygtig planet."
|
||||
title="App lab verdensmål"
|
||||
imagePath="/images/Zhen/Infomatik/1.G-App.png"
|
||||
/>
|
||||
<TimelineItem
|
||||
date="1.G 2022"
|
||||
title="Quest for grass"
|
||||
desc="Dette avancerede projekt udvikler et dynamisk spil i Unity-miljøet med en sofistikeret integration af en database, der skrupelløst opbevarer og manipulerer brugerens præstationer. Den benyttede database struktureres og drives af den altopslugende Google Firebase-platform, der leverer en robust og skalerbar infrastruktur til håndtering af data. Gennem en sublim kombination af komplekse algoritmer og interaktionelle mekanismer, optimeres brugeroplevelsen, og spillets dybde forøges betragteligt. Dette projekt fremhæver det symbiotiske forhold mellem teknologiske avancer og kreative visioner, idet det udforsker nye horisonter inden for spiludvikling og datamanagement. <br/><br/>Link: <a href='https://youtu.be/Vb_2U2lyVFY' style='color:lightblue;'>Youtube video</a>"
|
||||
imagePath="/images/Zhen/Infomatik/QuestForGrass.png"
|
||||
/>
|
||||
<TimelineItem
|
||||
date="2.G 2022"
|
||||
title="Game rankings website"
|
||||
desc="Denne pionerende webside, skabt med hovedsageligt HTML og et minimængde af CSS, repræsenterer en banebrydende praksis i webudviklingen. Ved at begrænse brugen af CSS til et minimum og ved at undlade JavaScript, demonstrerer den en avantgarde tilgang til design og funktionalitet. Med en fokuseret brug af HTML som kerneelement til opbygning af websiden, fremhæver den vigtigheden af semantisk strukturering og tilgængelighed. Denne minimalistiske tilgang afspejler en dyb forståelse for webudviklingens essentielle principper og skaber samtidig en unik æstetik og brugeroplevelse, der inspirerer til refleksion over konventionelle praksisser inden for digital design."
|
||||
imagePath="/images/Zhen/Infomatik/FirstWebsite.png"
|
||||
/>
|
||||
<TimelineItem
|
||||
date="2.G 2022"
|
||||
title="Uncle roger's recipies"
|
||||
desc="Denne sekundære webplatform, udspringende af mine digitale kreationer, udfolder sig som en kyndig panorama over de bedste 5 opskrifter præsenteret af Uncle Rogers. Udformet med pur HTML og anstrøg af CSS, emmer den af enkelhed kombineret med subtil elegance, og inkorporerer diskrete CSS-animationer for at tilføje en dynamisk dimension til brugeroplevelsen. Med en nøje sammensat struktur og en stringent implementering af webteknologier, udforsker den dybden af kulinariske inspirationer fra den anerkendte kogekunstner, alt imens den søger at fremme gastronomisk kreativitet og forfinelse."
|
||||
imagePath="/images/Zhen/Infomatik/UncleRogers.png"
|
||||
/>
|
||||
<TimelineItem
|
||||
date="2.G 11/9-2022"
|
||||
title="Visit copenhagen"
|
||||
desc="Dette projekt inkorporerede en mangefacetteret tilgang med adskillige elementer af gestaltloven, og det udnyttede HTML og CSS til at animere disse aspekter. Den valgte ramme, .NET Blazor, fungerede som fundamentet for implementeringen af disse avancerede visuelle og interaktive komponenter. Gennem en dybdegående anvendelse af komplekse gestaltprincipper blev en symbiotisk syntese opnået, hvilket resulterede i en dynamisk digital oplevelse, der strømlinede brugerinteraktionen og forbedrede æstetikken af det endelige produkt. <br/><br/>Link: <a href='https://youtu.be/S9Rpm12Al0Y' style='color:lightblue;'>Youtube video</a>"
|
||||
imagePath="/images/Zhen/Infomatik/VisitCopenhagen.png"
|
||||
/>
|
||||
<TimelineItem
|
||||
date="2.G 10/3-2023"
|
||||
title="Makey Makey: pressure plate"
|
||||
desc="Ved anvendelse af Makey Makey har vi skabt en innovativ og funktionel trykplade af papir, tape, aluminiumsfolie og selve Makey Makey-enheden. Denne teknologiske opfindelse udgør et paradigmeskift inden for DIY-elektronik og inkorporerer en særegen symbiose af håndværksmæssig finesse og digital innovation. Ved at omfavne en konvergens af analoge og digitale teknologier demonstrerer denne opfindelse et ekstraordinært niveau af teknisk snilde og kreativ tænkning. Gennem en kompleks integration af disse elementer opnår denne trykplade ikke blot funktionalitet, men repræsenterer også en manifestation af menneskelig opfindsomhed og teknologisk fremgang. <br/><br/>Link: <a href='https://www.youtube.com/watch?v=AIUuqfbgKRw' style='color:lightblue;'>Youtube video</a><br/>Link 2: <a href='https://www.youtube.com/watch?v=tJ_N_K_kbjw' style='color:lightblue;'>Youtube video</a>"
|
||||
imagePath="/images/Zhen/Infomatik/PressurePlate.png"
|
||||
/>
|
||||
<TimelineItem
|
||||
date="2.G 16/6-2023"
|
||||
title="Otakians"
|
||||
desc='Dette projekt repræsenterer apogeeen af mine anstrengelser og stræben inden for teknologisk innovation. Det er en avanceret webapplikation konstrueret med en sofistikeret arkitektur, der omfatter HTML, CSS, C#, og javascript som fundamentale byggesten. Indlejret i dets omfangsrige struktur findes et imponerende repertoire af funktioner, herunder en grundig præsentationssektion, en dynamisk chatmodul, en omfattende FAQ-sektion og et stringent, indbygget login-system. Projektets kerneformål er at fungere som et digitalt samlingspunkt for tilhængere af anime, kendt som "weebs", hvor de kan dele, diskutere og opbygge fællesskaber om deres passion for denne japanske popkulturform. Med en sofistikeret integration af komplekse algoritmer og brugercentrerede designprincipper stræber denne hjemmeside mod at skabe en opslidende og meningsfuld oplevelse for sine brugere, og dermed forstærke forbindelserne inden for dette særlige interessefællesskab.'
|
||||
imagePath="/images/Zhen/Infomatik/Otakians.png"
|
||||
/>
|
||||
<TimelineItem
|
||||
date="3.G 3/12-2023"
|
||||
title="Extraordinær menneskelig sans"
|
||||
desc='Med brug af en M5StickCPlus og en bevægelses sensor, så skabte benjamin og jeg en ekstra menneskelig sans.'
|
||||
imagePath="sveske_files/thumb.png"
|
||||
/>
|
||||
<TimelineItem
|
||||
date="3.G 10/3-20234"
|
||||
title="Prolog Apple device recommendation"
|
||||
desc='Et program lavet med Prolog, som finder en tilpassende Apple enhed baseret på dato udgivet og pris af enheden.'
|
||||
imagePath="sveske_files/thumb_004.png"
|
||||
/>
|
||||
</Timeline>
|
|
@ -0,0 +1,229 @@
|
|||
<script lang="ts">
|
||||
import { onMount } from "svelte";
|
||||
import { Vector2 } from "./../Utils/Vector2";
|
||||
import TopNameTextPlate from "./TopNameTextPlate.svelte";
|
||||
//import { throttle } from "./../Utils/Throttle";
|
||||
|
||||
import { Parallax, ParallaxLayer, StickyLayer } from "svelte-parallax";
|
||||
|
||||
// Params
|
||||
let mouseMoveScale: number = 0.25;
|
||||
let targetTextLenght: number = 100;
|
||||
|
||||
// Site variables
|
||||
let mousePos: Vector2;
|
||||
|
||||
// Element binded variables
|
||||
let mouseRelativeScaled: Vector2 = new Vector2(0, 0);
|
||||
|
||||
let windowWidth = 0;
|
||||
let windowHeight = 0;
|
||||
|
||||
let screenCenter: Vector2;
|
||||
|
||||
let StartPageAnimated: Element | null;
|
||||
let windowRef: Window;
|
||||
|
||||
function onMouseMoved(event: MouseEvent) {
|
||||
mousePos = new Vector2(event.clientX, event.clientY);
|
||||
|
||||
updateAnimation(mousePos);
|
||||
}
|
||||
|
||||
function updateAnimation(mousePos: Vector2) {
|
||||
let mouseRelativePos = mousePos.Sub(screenCenter);
|
||||
mouseRelativeScaled = mouseRelativePos.Scale(mouseMoveScale);
|
||||
|
||||
//console.log(mouseRelativePos.x+"\n"+mouseRelativePos.y);
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
windowRef = window;
|
||||
|
||||
const updateDimensions = () => {
|
||||
windowWidth = windowRef.innerWidth;
|
||||
windowHeight = windowRef.innerHeight;
|
||||
|
||||
screenCenter = new Vector2(windowWidth / 2, windowHeight / 2);
|
||||
|
||||
//console.log("Window size changed: (" + windowWidth + ", " + windowHeight + ")");
|
||||
};
|
||||
|
||||
updateDimensions(); // On first pass
|
||||
|
||||
windowRef.addEventListener("resize", updateDimensions);
|
||||
|
||||
const RevertToOrigin = () => {
|
||||
if (
|
||||
navigator.userAgent.search(/gecko/i) > 0 &&
|
||||
StartPageAnimated !== null
|
||||
) {
|
||||
StartPageAnimated.classList.add("FirefoxSmoothTranition");
|
||||
}
|
||||
updateAnimation(new Vector2(windowWidth / 2, windowHeight / 2));
|
||||
};
|
||||
document.documentElement.addEventListener("mouseleave", RevertToOrigin);
|
||||
|
||||
const RemoveFirefoxSmoothTranition = () => {
|
||||
if (
|
||||
navigator.userAgent.search(/gecko/i) > 0 &&
|
||||
StartPageAnimated !== null
|
||||
) {
|
||||
StartPageAnimated.classList.remove("FirefoxSmoothTranition");
|
||||
}
|
||||
};
|
||||
document.documentElement.addEventListener(
|
||||
"mouseenter",
|
||||
RemoveFirefoxSmoothTranition,
|
||||
);
|
||||
|
||||
return () => {
|
||||
windowRef.removeEventListener("resize", updateDimensions);
|
||||
};
|
||||
});
|
||||
|
||||
const programmingLanguages: string[] = [
|
||||
"C++",
|
||||
"C#",
|
||||
"ARDUINO",
|
||||
"PYTHON",
|
||||
"JAVA",
|
||||
"JAVASCRIPT",
|
||||
"TYPESCRIPT",
|
||||
"HTML",
|
||||
"CSS",
|
||||
];
|
||||
|
||||
function getRandomInt(max: number) {
|
||||
return Math.floor(Math.random() * max);
|
||||
}
|
||||
|
||||
function GrabRandomString() {
|
||||
let outString: string = "";
|
||||
while (outString.length < targetTextLenght) {
|
||||
outString +=
|
||||
programmingLanguages[
|
||||
getRandomInt(programmingLanguages.length)
|
||||
] + " ";
|
||||
}
|
||||
|
||||
return outString; // At about target size
|
||||
}
|
||||
</script>
|
||||
|
||||
<svelte:window on:mousemove={onMouseMoved} />
|
||||
|
||||
|
||||
<ParallaxLayer class="StartPageContainer" rate={0.25} offset={0} span={0}>
|
||||
<div
|
||||
class="StartPageAnimated"
|
||||
bind:this={StartPageAnimated}
|
||||
style="transform: translate({mouseRelativeScaled.x}px, {mouseRelativeScaled.y}px) translateZ(0) rotate(0.001deg);"
|
||||
>
|
||||
{#each { length: 100 } as _, i}
|
||||
<span class="rotate45 SkillsText">
|
||||
{GrabRandomString()}
|
||||
</span>
|
||||
{/each}
|
||||
</div>
|
||||
</ParallaxLayer>
|
||||
|
||||
<ParallaxLayer rate={0} offset={0.25} span={0}>
|
||||
<TopNameTextPlate />
|
||||
</ParallaxLayer>
|
||||
|
||||
<!-- <div class="StartPageContainer">
|
||||
<div class="TopOverlay">
|
||||
<TopNameTextPlate/>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="StartPageAnimated"
|
||||
id="StartPageAnimated"
|
||||
bind:this={StartPageAnimated}
|
||||
style="transform: translate({mouseRelativeScaled.x}px, {mouseRelativeScaled.y}px) translateZ(0) rotate(0.001deg);"
|
||||
>
|
||||
{#each {length: 100} as _, i}
|
||||
|
||||
<span
|
||||
class="rotate45 SkillsText"
|
||||
>
|
||||
{GrabRandomString()}
|
||||
</span
|
||||
>
|
||||
{/each}
|
||||
</div>
|
||||
</div> -->
|
||||
|
||||
<div id="DummyDiv" class="FirefoxSmoothTranition StartPageContainer TopOverlay" style="display: none !important;" />
|
||||
|
||||
<style>
|
||||
.StartPageContainer {
|
||||
/* height: 40vh; */
|
||||
|
||||
background-color: burlywood;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
display: flex;
|
||||
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.StartPageAnimated {
|
||||
/* background: url("https://i1.adis.ws/i/canon/future_of_forests_header_16x9_dc14bbe1e35040f79bf566eedaf5c8f7?$hero-header-half-16by9-dt$"); */
|
||||
background-color: #131313;
|
||||
position: absolute;
|
||||
height: 150vh;
|
||||
width: 150vw;
|
||||
|
||||
padding: 0;
|
||||
|
||||
transition: transform 1000ms cubic-bezier(0.16, 1.63, 0.01, 0.99);
|
||||
-moz-transition: none;
|
||||
|
||||
left: -25vw;
|
||||
top: -50vh;
|
||||
|
||||
justify-content: center;
|
||||
vertical-align: middle;
|
||||
display: flex;
|
||||
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.FirefoxSmoothTranition {
|
||||
transition: transform 1000ms cubic-bezier(0.16, 1.63, 0.01, 0.99);
|
||||
-moz-transition: transform 1000ms cubic-bezier(0.16, 1.63, 0.01, 0.99) !important;
|
||||
}
|
||||
|
||||
.SkillsText {
|
||||
font-family: "CozetteVector";
|
||||
|
||||
text-align: start;
|
||||
font-size: x-large;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
white-space: nowrap;
|
||||
|
||||
width: 2rem;
|
||||
|
||||
color: rgb(66, 66, 66);
|
||||
}
|
||||
|
||||
.TopOverlay {
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.rotate45 {
|
||||
transform: rotate(-45deg); /* Rotate the element by 45 degrees */
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,57 @@
|
|||
<script lang="ts">
|
||||
import HorizonalStack from './../../../comps/Utils/HorizonalStack.svelte'
|
||||
</script>
|
||||
|
||||
<div class="container">
|
||||
<div style="flex-grow: 1;" />
|
||||
<div class="TextContainer">
|
||||
<span class="NamePlateText" >
|
||||
Zhentao Wei
|
||||
<br/>
|
||||
<p class="NickNameText">Alex</p>
|
||||
</span>
|
||||
</div>
|
||||
<div style="flex-grow: 2;" />
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.container{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
align-items: center;
|
||||
vertical-align: middle;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.TextContainer{
|
||||
align-items: center;
|
||||
vertical-align: middle;
|
||||
display: flex;
|
||||
|
||||
/* background-color: aliceblue; */
|
||||
background-color: rgba(45, 45, 45, 0.645);
|
||||
padding: 0.75rem 1rem;
|
||||
border-radius: 20px;
|
||||
|
||||
backdrop-filter: blur(1px);
|
||||
}
|
||||
|
||||
.NamePlateText{
|
||||
/* font-family: 'CozetteVector'; */
|
||||
text-align: left;
|
||||
font-size: 300%;
|
||||
color: rgb(225, 225, 225);
|
||||
|
||||
border-left: 0.5rem solid rgb(88, 198, 82);
|
||||
padding-left: 1rem;
|
||||
}
|
||||
|
||||
.NickNameText{
|
||||
font-size: 75%;
|
||||
margin: 0;
|
||||
margin-top: -1rem;
|
||||
|
||||
color: rgb(99, 99, 99);
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,21 @@
|
|||
export function throttle(callback, wait) {
|
||||
let timeoutId = null;
|
||||
let lastExecutedTime = 0;
|
||||
|
||||
return function (...args) {
|
||||
const currentTime = Date.now();
|
||||
|
||||
const execute = () => {
|
||||
lastExecutedTime = currentTime;
|
||||
callback.apply(this, args);
|
||||
};
|
||||
|
||||
if (currentTime - lastExecutedTime >= wait) {
|
||||
execute();
|
||||
} else {
|
||||
clearTimeout(timeoutId);
|
||||
timeoutId = setTimeout(execute, wait - (currentTime - lastExecutedTime));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
export class Vector2 {
|
||||
x: number;
|
||||
y: number;
|
||||
|
||||
constructor(x: number, y: number) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
Add(vec2: Vector2){
|
||||
return new Vector2(this.x + vec2.x, this.y + vec2.y);
|
||||
}
|
||||
|
||||
Sub(vec2: Vector2){
|
||||
return new Vector2(this.x - vec2.x, this.y - vec2.y);
|
||||
}
|
||||
|
||||
Scale(mult: number){
|
||||
return new Vector2(this.x * mult, this.y * mult);;
|
||||
}
|
||||
}
|
After Width: | Height: | Size: 9.5 KiB |
After Width: | Height: | Size: 146 KiB |
After Width: | Height: | Size: 121 KiB |
After Width: | Height: | Size: 742 KiB |
After Width: | Height: | Size: 282 KiB |
After Width: | Height: | Size: 154 KiB |
After Width: | Height: | Size: 1.8 MiB |
After Width: | Height: | Size: 1.1 MiB |
|
@ -0,0 +1,18 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
fill="#000000"
|
||||
width="800.02313"
|
||||
height="609.78137"
|
||||
viewBox="0 0 24.000694 18.293441"
|
||||
role="img"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<path
|
||||
d="m 20.317481,1.5163647 a 19.791,19.791 0 0 0 -4.885,-1.51500001 0.074,0.074 0 0 0 -0.079,0.037 c -0.21,0.375 -0.444,0.864 -0.608,1.25000001 a 18.27,18.27 0 0 0 -5.4870004,0 12.64,12.64 0 0 0 -0.617,-1.25000001 0.077,0.077 0 0 0 -0.079,-0.037 19.736,19.736 0 0 0 -4.885,1.51500001 0.07,0.07 0 0 0 -0.032,0.027 c -3.11199997,4.649 -3.96499997,9.1830003 -3.54599997,13.6600003 a 0.082,0.082 0 0 0 0.031,0.057 19.9,19.9 0 0 0 5.99299997,3.03 0.078,0.078 0 0 0 0.084,-0.028 14.09,14.09 0 0 0 1.226,-1.994 0.076,0.076 0 0 0 -0.041,-0.106 13.107,13.107 0 0 1 -1.872,-0.892 0.077,0.077 0 0 1 -0.008,-0.128 10.2,10.2 0 0 0 0.372,-0.292 0.074,0.074 0 0 1 0.077,-0.01 c 3.928,1.793 8.1800004,1.793 12.0620004,0 a 0.074,0.074 0 0 1 0.078,0.01 c 0.12,0.098 0.246,0.198 0.373,0.292 a 0.077,0.077 0 0 1 -0.006,0.127 12.299,12.299 0 0 1 -1.873,0.892 0.077,0.077 0 0 0 -0.041,0.107 c 0.36,0.698 0.772,1.362 1.225,1.993 a 0.076,0.076 0 0 0 0.084,0.028 19.839,19.839 0 0 0 6.002,-3.03 0.077,0.077 0 0 0 0.032,-0.054 c 0.5,-5.177 -0.838,-9.6740003 -3.549,-13.6600003 a 0.061,0.061 0 0 0 -0.031,-0.03 z M 8.0204806,12.476365 c -1.183,0 -2.157,-1.085 -2.157,-2.419 0,-1.3330003 0.956,-2.4190003 2.157,-2.4190003 1.21,0 2.1760004,1.096 2.1570004,2.4200003 0,1.333 -0.9560004,2.418 -2.1570004,2.418 z m 7.9750004,0 c -1.183,0 -2.157,-1.085 -2.157,-2.419 0,-1.3330003 0.955,-2.4190003 2.157,-2.4190003 1.21,0 2.176,1.096 2.157,2.4200003 0,1.333 -0.946,2.418 -2.157,2.418 z"
|
||||
id="path1"
|
||||
style="fill:#fdfdfd;fill-opacity:1" />
|
||||
</svg>
|
After Width: | Height: | Size: 1.8 KiB |
|
@ -0,0 +1,14 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
height="20"
|
||||
id="Layer_1"
|
||||
version="1.1"
|
||||
viewBox="0 0 28 20"
|
||||
width="28"
|
||||
xml:space="preserve"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"><defs
|
||||
id="defs1" /><path
|
||||
d="M 2,4 H 26 C 27.104,4 28,3.104 28,2 28,0.896 27.104,0 26,0 H 2 C 0.896,0 0,0.896 0,2 0,3.104 0.896,4 2,4 Z M 26,8 H 2 c -1.104,0 -2,0.896 -2,2 0,1.104 0.896,2 2,2 h 24 c 1.104,0 2,-0.896 2,-2 0,-1.104 -0.896,-2 -2,-2 z m 0,8 H 2 c -1.104,0 -2,0.896 -2,2 0,1.104 0.896,2 2,2 h 24 c 1.104,0 2,-0.896 2,-2 0,-1.104 -0.896,-2 -2,-2 z"
|
||||
id="path1"
|
||||
style="fill:#ffffff;fill-opacity:1" /></svg>
|
After Width: | Height: | Size: 684 B |
After Width: | Height: | Size: 24 KiB |
After Width: | Height: | Size: 24 KiB |
After Width: | Height: | Size: 51 KiB |
After Width: | Height: | Size: 75 KiB |
|
@ -0,0 +1,33 @@
|
|||
/* --- FONTS --- */
|
||||
@font-face {
|
||||
font-family: "CozetteVector";
|
||||
src:
|
||||
local("CozetteVector"),
|
||||
url("/fonts/CozetteVector.ttf") format("truetype");
|
||||
}
|
||||
|
||||
html {
|
||||
background: var(--background1);
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: var(--main-font);
|
||||
color: var(--text1); /* Default to primary text color. */
|
||||
background-color: var(--background);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
a, a:link a:visited {
|
||||
color: var(--text1);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
code {
|
||||
font-weight: 400;
|
||||
font-size: 0.9rem;
|
||||
line-height: 1.3;
|
||||
letter-spacing: .32px;
|
||||
border-radius: .25rem;
|
||||
padding: 0 .5rem;
|
||||
background-color: #333333;
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
:root {
|
||||
--title-font: 'CozetteVector';
|
||||
--main-font: 'Segoe UI';
|
||||
--text1: #fff; /* Primary text. */
|
||||
--text2: #cac9c6; /* Secondary text. */
|
||||
--text3: #b0afad; /* Third text color. */
|
||||
--text4: #868584; /* Fourth text color. */
|
||||
--background: #232222;
|
||||
--background1: #1b1a1a;
|
||||
--primary: #227c9d;
|
||||
--secondary: #ffcb77;
|
||||
--accent: #17c3b2;
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
|
||||
import adapter from '@sveltejs/adapter-static';
|
||||
|
||||
/** @type {import('@sveltejs/kit').Config} */
|
||||
export default {
|
||||
preprocess: vitePreprocess(),
|
||||
kit: {
|
||||
prerender: {
|
||||
handleHttpError: 'fail'
|
||||
},
|
||||
adapter: adapter({
|
||||
pages: 'build',
|
||||
assets: 'build',
|
||||
fallback: undefined,
|
||||
precompress: false,
|
||||
strict: true
|
||||
})
|
||||
}
|
||||
};
|
|
@ -0,0 +1,7 @@
|
|||
import { sveltekit } from '@sveltejs/kit/vite';
|
||||
import { defineConfig } from 'vite';
|
||||
import { imagetools } from '@zerodevx/svelte-img/vite' // https://zerodevx.github.io/svelte-img/
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [sveltekit(), imagetools()]
|
||||
});
|