redacted my info, into my database #1
|
|
@ -12,6 +12,9 @@ jobs:
|
||||||
- name: Signal deprived.dev for rebuild
|
- name: Signal deprived.dev for rebuild
|
||||||
env:
|
env:
|
||||||
SSH_PRIVATE_KEY: ${{ secrets.SSH_KEY }}
|
SSH_PRIVATE_KEY: ${{ secrets.SSH_KEY }}
|
||||||
|
GITKEY: ${{ secrets.GITKEY }}
|
||||||
|
PUBLIC_URL_BASE: ${{ variables.PUBLIC_URL_BASE }}
|
||||||
|
PUBLIC_POCKET_URL: ${{ variables.PUBLIC_POCKET_URL }}
|
||||||
run: |
|
run: |
|
||||||
sshkey=$(mktemp)
|
sshkey=$(mktemp)
|
||||||
trap "rm -rf $sshkey" exit
|
trap "rm -rf $sshkey" exit
|
||||||
|
|
|
||||||
6
.gitignore
vendored
|
|
@ -8,3 +8,9 @@ node_modules
|
||||||
!.env.example
|
!.env.example
|
||||||
vite.config.js.timestamp-*
|
vite.config.js.timestamp-*
|
||||||
vite.config.ts.timestamp-*
|
vite.config.ts.timestamp-*
|
||||||
|
redacted_cv_info.json
|
||||||
|
.npm-cache/
|
||||||
|
.npm-cache
|
||||||
|
.ssh/
|
||||||
|
*/build/
|
||||||
|
*/*.log
|
||||||
|
|
|
||||||
56
deprecated/tools/+page.svelte
Normal file
|
|
@ -0,0 +1,56 @@
|
||||||
|
<script>
|
||||||
|
import A4 from "../zhen/notes/physics/sharedComps/A4.svelte";
|
||||||
|
import ToolButton from "./comps/ToolButton.svelte";
|
||||||
|
import BatteryMedium from "@lucide/svelte/icons/battery-medium";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="flex justify-center pt-10">
|
||||||
|
<A4
|
||||||
|
bottomBorder={false}
|
||||||
|
bgColor={"rounded-lg bg-base-300"}
|
||||||
|
class="cozette text-base-content h-full"
|
||||||
|
>
|
||||||
|
<div class="p-4 flex flex-col h-full">
|
||||||
|
<h1 class="text-5xl font-bold">
|
||||||
|
Tools (NOT FINISHED. come back in the future.)
|
||||||
|
</h1>
|
||||||
|
<span class="w-full text-xl"
|
||||||
|
>These are the tools collected from different places of the internet</span
|
||||||
|
>
|
||||||
|
|
||||||
|
<!-- Spacing -->
|
||||||
|
<div class="pt-14"></div>
|
||||||
|
|
||||||
|
<div class="p-4 bg-base-200 rounded-lg">
|
||||||
|
<h2 class="text-2xl font-bolc">MPUs/SoCs</h2>
|
||||||
|
<span>Whatever acronym you want lol</span>
|
||||||
|
<div class="grid grid-cols-3 gap-4">
|
||||||
|
<ToolButton
|
||||||
|
title="Sleeping battery life"
|
||||||
|
desc="Calculates the battery life depending on sleep and non-sleep power usage."
|
||||||
|
btnText="To calculator"
|
||||||
|
toolIcon={BatteryMedium}
|
||||||
|
/>
|
||||||
|
<!-- <ToolButton
|
||||||
|
title="Sleeping battery life"
|
||||||
|
desc="Calculates the battery life depending on sleep and non-sleep power usage."
|
||||||
|
btnText="To calculator"
|
||||||
|
toolIcon={BatteryMedium}
|
||||||
|
/>
|
||||||
|
<ToolButton
|
||||||
|
title="Sleeping battery life"
|
||||||
|
desc="Calculates the battery life depending on sleep and non-sleep power usage."
|
||||||
|
btnText="To calculator"
|
||||||
|
toolIcon={BatteryMedium}
|
||||||
|
/> -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-auto align-text-bottom">
|
||||||
|
I if you have tool suggestions, then either create an issue, create a
|
||||||
|
pull request, or send an email. I probably wont add it though, since
|
||||||
|
this is free work lol.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</A4>
|
||||||
|
</div>
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
export let fontSize: string = "3mm";
|
export let fontSize: string = "3mm";
|
||||||
export let lineHeight: string = "3.1mm";
|
export let lineHeight: string = "3.1mm";
|
||||||
|
|
||||||
import { onMount } from "svelte";
|
import onMount from "@e/onMount";
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
imageCaption = logo.split(/(\\|\/)/g).pop();
|
imageCaption = logo.split(/(\\|\/)/g).pop();
|
||||||
});
|
});
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
export let logoWidths: string = "35%";
|
export let logoWidths: string = "35%";
|
||||||
|
|
||||||
|
|
||||||
import { onMount } from "svelte";
|
import onMount from "@e/onMount";
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
imageCaption = logo.split(/(\\|\/)/g).pop();
|
imageCaption = logo.split(/(\\|\/)/g).pop();
|
||||||
});
|
});
|
||||||
106
deprecated/zhen/cv/CompsRev3/LinkToSource.svelte
Normal file
|
|
@ -0,0 +1,106 @@
|
||||||
|
<script>
|
||||||
|
import svelteLogo from "$lib/svelteLogos/svelte-logo-cutout.svg";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
<div class="flex justify-center">
|
||||||
|
<div class="corner-border-container p-1 m-1">
|
||||||
|
<div class="flex">
|
||||||
|
This CV was made using html, css and <a
|
||||||
|
class="grid place-content-center"
|
||||||
|
href="https://kit.svelte.dev/"
|
||||||
|
><img src={svelteLogo} class="w-2 h-2" alt="SvelteKit logo" /></a
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
Sources:
|
||||||
|
<a
|
||||||
|
href="https://gitea.deprived.dev/Sveskejuice/deprived-main-website/src/branch/dev/src/routes/zhen/cv/rev2/+page.svelte"
|
||||||
|
>CV source code</a
|
||||||
|
>
|
||||||
|
and
|
||||||
|
<a href="/cv?hideOnPrint=1">My Website</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.corner-border-container {
|
||||||
|
--length: 5px;
|
||||||
|
--width: 1px;
|
||||||
|
background-color: var(--left-grid-bg-color);
|
||||||
|
background-image:
|
||||||
|
linear-gradient(
|
||||||
|
var(--left-decor-line-color),
|
||||||
|
var(--left-decor-line-color)
|
||||||
|
),
|
||||||
|
linear-gradient(
|
||||||
|
var(--left-decor-line-color),
|
||||||
|
var(--left-decor-line-color)
|
||||||
|
),
|
||||||
|
linear-gradient(
|
||||||
|
var(--left-decor-line-color),
|
||||||
|
var(--left-decor-line-color)
|
||||||
|
),
|
||||||
|
linear-gradient(
|
||||||
|
var(--left-decor-line-color),
|
||||||
|
var(--left-decor-line-color)
|
||||||
|
),
|
||||||
|
linear-gradient(
|
||||||
|
var(--left-decor-line-color),
|
||||||
|
var(--left-decor-line-color)
|
||||||
|
),
|
||||||
|
linear-gradient(
|
||||||
|
var(--left-decor-line-color),
|
||||||
|
var(--left-decor-line-color)
|
||||||
|
),
|
||||||
|
linear-gradient(
|
||||||
|
var(--left-decor-line-color),
|
||||||
|
var(--left-decor-line-color)
|
||||||
|
),
|
||||||
|
linear-gradient(
|
||||||
|
var(--left-decor-line-color),
|
||||||
|
var(--left-decor-line-color)
|
||||||
|
);
|
||||||
|
background-size:
|
||||||
|
var(--length) var(--width),
|
||||||
|
var(--width) var(--length),
|
||||||
|
var(--length) var(--width),
|
||||||
|
var(--width) var(--length),
|
||||||
|
var(--length) var(--width),
|
||||||
|
var(--width) var(--length),
|
||||||
|
var(--length) var(--width),
|
||||||
|
var(--width) var(--length);
|
||||||
|
background-position:
|
||||||
|
top left,
|
||||||
|
top left,
|
||||||
|
top right,
|
||||||
|
top right,
|
||||||
|
bottom right,
|
||||||
|
bottom right,
|
||||||
|
bottom left,
|
||||||
|
bottom left;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
z-index: 1;
|
||||||
|
|
||||||
|
font-size: 0.5rem;
|
||||||
|
|
||||||
|
//white-space: nowrap;
|
||||||
|
|
||||||
|
color: #777777;
|
||||||
|
|
||||||
|
* a {
|
||||||
|
color: #3d6ddc;
|
||||||
|
padding-left: 1mm;
|
||||||
|
padding-right: 1mm;
|
||||||
|
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
div:nth-child(2) {
|
||||||
|
padding-bottom: 2mm;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -24,7 +24,7 @@
|
||||||
import preveiwImage from "$lib/zhen/cv-comps/EposCvPreveiw.png";
|
import preveiwImage from "$lib/zhen/cv-comps/EposCvPreveiw.png";
|
||||||
|
|
||||||
// Print detection setup
|
// Print detection setup
|
||||||
import { onMount } from "svelte";
|
import onMount from "@e/onMount";
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
// Check if the query parameter exists in the URL
|
// Check if the query parameter exists in the URL
|
||||||
const urlParams = new URLSearchParams(window.location.search);
|
const urlParams = new URLSearchParams(window.location.search);
|
||||||
61
flake.lock
generated
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
{
|
||||||
|
"nodes": {
|
||||||
|
"flake-utils": {
|
||||||
|
"inputs": {
|
||||||
|
"systems": "systems"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1731533236,
|
||||||
|
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1735563628,
|
||||||
|
"narHash": "sha256-OnSAY7XDSx7CtDoqNh8jwVwh4xNL/2HaJxGjryLWzX8=",
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "b134951a4c9f3c995fd7be05f3243f8ecd65d798",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "NixOS",
|
||||||
|
"ref": "nixos-24.05",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": {
|
||||||
|
"inputs": {
|
||||||
|
"flake-utils": "flake-utils",
|
||||||
|
"nixpkgs": "nixpkgs"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"systems": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1681028828,
|
||||||
|
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": "root",
|
||||||
|
"version": 7
|
||||||
|
}
|
||||||
35
flake.nix
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
{
|
||||||
|
description = "NPM project (dev shell + run, auto-install deps)";
|
||||||
|
|
||||||
|
inputs = {
|
||||||
|
nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.05";
|
||||||
|
flake-utils.url = "github:numtide/flake-utils";
|
||||||
|
};
|
||||||
|
|
||||||
|
outputs = { self, nixpkgs, flake-utils }:
|
||||||
|
flake-utils.lib.eachDefaultSystem (system:
|
||||||
|
let
|
||||||
|
pkgs = import nixpkgs { inherit system; };
|
||||||
|
node = pkgs.nodejs_22; # or pkgs.nodejs_20
|
||||||
|
|
||||||
|
|
||||||
|
start = pkgs.writeShellApplication {
|
||||||
|
name = "start";
|
||||||
|
runtimeInputs = [ node ];
|
||||||
|
text = ''
|
||||||
|
set -euo pipefail
|
||||||
|
export npm_config_cache="$PWD/.npm-cache"
|
||||||
|
if [ -f package-lock.json ]; then cmd=ci; else cmd=install; fi
|
||||||
|
echo "→ npm $cmd (nix run)"
|
||||||
|
${node}/bin/npm "$cmd"
|
||||||
|
exec ${node}/bin/npm run dev -- "$@"
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
in
|
||||||
|
{
|
||||||
|
devShells.default = pkgs.mkShell { buildInputs = [ node ]; shellHook = ''export npm_config_cache="$PWD/.npm-cache"''; };
|
||||||
|
apps.default = { type = "app"; program = "${start}/bin/start"; };
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -32,6 +32,9 @@
|
||||||
],
|
],
|
||||||
"@stores": [
|
"@stores": [
|
||||||
"./src/ts/store.ts"
|
"./src/ts/store.ts"
|
||||||
|
],
|
||||||
|
"@e/*": [
|
||||||
|
"./src/optimizers/*"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
12
package-lock.json
generated
|
|
@ -14,7 +14,8 @@
|
||||||
"pocketbase": "^0.26.2",
|
"pocketbase": "^0.26.2",
|
||||||
"svelte-katex": "^0.1.2",
|
"svelte-katex": "^0.1.2",
|
||||||
"svelte-media-queries": "^1.6.2",
|
"svelte-media-queries": "^1.6.2",
|
||||||
"theme-change": "^2.5.0"
|
"theme-change": "^2.5.0",
|
||||||
|
"zod": "^4.1.11"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@sveltejs/adapter-auto": "^3.0.0",
|
"@sveltejs/adapter-auto": "^3.0.0",
|
||||||
|
|
@ -3808,6 +3809,15 @@
|
||||||
"version": "1.1.2",
|
"version": "1.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/zimmerframe/-/zimmerframe-1.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/zimmerframe/-/zimmerframe-1.1.2.tgz",
|
||||||
"integrity": "sha512-rAbqEGa8ovJy4pyBxZM70hg4pE6gDgaQ0Sl9M3enG3I0d6H4XSAM3GeNGLKnsBpuijUow064sf7ww1nutC5/3w=="
|
"integrity": "sha512-rAbqEGa8ovJy4pyBxZM70hg4pE6gDgaQ0Sl9M3enG3I0d6H4XSAM3GeNGLKnsBpuijUow064sf7ww1nutC5/3w=="
|
||||||
|
},
|
||||||
|
"node_modules/zod": {
|
||||||
|
"version": "4.1.11",
|
||||||
|
"resolved": "https://registry.npmjs.org/zod/-/zod-4.1.11.tgz",
|
||||||
|
"integrity": "sha512-WPsqwxITS2tzx1bzhIKsEs19ABD5vmCVa4xBo2tq/SrV4RNZtfws1EnCWQXM6yh8bD08a1idvkB5MZSBiZsjwg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/colinhacks"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@
|
||||||
"pocketbase": "^0.26.2",
|
"pocketbase": "^0.26.2",
|
||||||
"svelte-katex": "^0.1.2",
|
"svelte-katex": "^0.1.2",
|
||||||
"svelte-media-queries": "^1.6.2",
|
"svelte-media-queries": "^1.6.2",
|
||||||
"theme-change": "^2.5.0"
|
"theme-change": "^2.5.0",
|
||||||
|
"zod": "^4.1.11"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
Before Width: | Height: | Size: 7.4 KiB After Width: | Height: | Size: 7.4 KiB |
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 6.1 KiB After Width: | Height: | Size: 6.1 KiB |
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 5.6 KiB |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 6.4 KiB After Width: | Height: | Size: 6.4 KiB |
|
Before Width: | Height: | Size: 5.9 KiB After Width: | Height: | Size: 5.9 KiB |
|
Before Width: | Height: | Size: 7.7 KiB After Width: | Height: | Size: 7.7 KiB |
|
Before Width: | Height: | Size: 673 KiB After Width: | Height: | Size: 673 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 3.4 KiB |
BIN
src/lib/alex/cv-comps/preview.png
Normal file
|
After Width: | Height: | Size: 505 KiB |
|
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 35 KiB |
|
Before Width: | Height: | Size: 139 KiB |
|
Before Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 391 KiB |
|
Before Width: | Height: | Size: 587 KiB |
1
src/optimizers/fly.ts
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
export { fly as default } from "svelte/transition";
|
||||||
1
src/optimizers/onDestroy.ts
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
export { onDestroy as default } from "svelte";
|
||||||
1
src/optimizers/onMount.ts
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
export { onMount as default } from "svelte";
|
||||||
1
src/optimizers/sveltekit.ts
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
export { sveltekit as default } from "@sveltejs/kit/vite";
|
||||||
1
src/optimizers/tick.ts
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
export { tick as default } from "svelte";
|
||||||
1
src/optimizers/viteThing.js
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
export { vitePreprocess as default } from "@sveltejs/vite-plugin-svelte";
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { onMount } from "svelte";
|
import onMount from "@e/onMount";
|
||||||
import ShopItemCard from "./comps/ShopItemCard.svelte";
|
import ShopItemCard from "./comps/ShopItemCard.svelte";
|
||||||
import { api } from "@stores";
|
import { api } from "@stores";
|
||||||
import { ShopItem } from "@src/ts/api/classes/ShopItem";
|
import ShopItem from "@src/ts/api/classes/ShopItem";
|
||||||
|
|
||||||
let allItems: undefined | ShopItem[] = undefined;
|
let allItems: undefined | ShopItem[] = undefined;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { onMount } from "svelte";
|
import onMount from "@e/onMount";
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
console.log(window.location.href);
|
console.log(window.location.href);
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { ShopItem } from "@src/ts/api/classes/ShopItem";
|
import type ShopItem from "@src/ts/api/classes/ShopItem";
|
||||||
import { ArrowBigRight } from "lucide-svelte";
|
import ArrowBigRight from "lucide-svelte/icons/arrow-big-right";
|
||||||
|
|
||||||
export let shopItem: ShopItem;
|
export let shopItem: ShopItem;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,10 @@
|
||||||
<!-- If url contains "hideOnPrint" param, then detect if start printing then hide elements -->
|
<!-- If url contains "hideOnPrint" param, then detect if start printing then hide elements -->
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import "../app.css";
|
import "../app.css";
|
||||||
import { fly } from "svelte/transition";
|
import fly from "@e/fly";
|
||||||
import MediaQuery from "svelte-media-queries";
|
import MediaQuery from "svelte-media-queries";
|
||||||
import { Dices } from "@lucide/svelte";
|
import Dices from "@lucide/svelte/icons/dices";
|
||||||
|
import re from "@ts/Redaction/Redactor";
|
||||||
let hideOnPrint: boolean = $state(false);
|
let hideOnPrint: boolean = $state(false);
|
||||||
|
|
||||||
let { children } = $props();
|
let { children } = $props();
|
||||||
|
|
@ -22,21 +23,31 @@
|
||||||
navbarHidden = true;
|
navbarHidden = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
import { afterNavigate } from "$app/navigation";
|
function handleUrlParams() {
|
||||||
afterNavigate(() => {
|
|
||||||
const params = new URLSearchParams(window.location.search);
|
const params = new URLSearchParams(window.location.search);
|
||||||
hideOnPrint = params.get("hideOnPrint") === "1";
|
hideOnPrint = params.get("hideOnPrint") === "1";
|
||||||
// console.log(hideOnPrint);
|
if (!!params.get("key")) {
|
||||||
|
localStorage.setItem("key", params.get("key")!);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
import { afterNavigate } from "$app/navigation";
|
||||||
|
afterNavigate(() => {
|
||||||
|
handleUrlParams();
|
||||||
});
|
});
|
||||||
|
|
||||||
import { onMount } from "svelte";
|
import onMount from "@e/onMount";
|
||||||
import Zooter from "./comps/Zooter.svelte";
|
import Zooter from "./comps/Zooter.svelte";
|
||||||
import CustomScrollBar from "./comps/CustomScrollBar.svelte";
|
import CustomScrollBar from "./comps/CustomScrollBar.svelte";
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
|
handleUrlParams();
|
||||||
|
|
||||||
const lock = document.createElement("meta");
|
const lock = document.createElement("meta");
|
||||||
lock.name = "darkreader-lock";
|
lock.name = "darkreader-lock";
|
||||||
document.head.appendChild(lock);
|
document.head.appendChild(lock);
|
||||||
|
|
||||||
|
await re.TryGetUnredacter();
|
||||||
});
|
});
|
||||||
|
|
||||||
function nextTheme() {
|
function nextTheme() {
|
||||||
|
|
@ -104,16 +115,14 @@
|
||||||
</a>
|
</a>
|
||||||
<div class="nav-spacer" />
|
<div class="nav-spacer" />
|
||||||
|
|
||||||
<!-- <a href="/">Home</a> -->
|
|
||||||
<!-- <a href="/zhen/notes/physics/1?hideOnPrint=1" target="_blank" style="width: 7.5rem;">Notes</a> -->
|
|
||||||
|
|
||||||
{@render SwitchThemeButton()}
|
{@render SwitchThemeButton()}
|
||||||
|
|
||||||
<a
|
<a
|
||||||
href="/zhen/cv/rev3?hideOnPrint=1"
|
href="/cv?hideOnPrint=1"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
style="width: 7.5rem;"
|
style="width: 7.5rem;"
|
||||||
class="text-center justify-center">Zhen CV</a
|
class="text-center justify-center text-md"
|
||||||
|
>{$re?.nick ?? "Alex"}'s CV</a
|
||||||
>
|
>
|
||||||
<!-- <a href="/tools" style="width: 7.5rem;" class="text-center">Tools</a> -->
|
<!-- <a href="/tools" style="width: 7.5rem;" class="text-center">Tools</a> -->
|
||||||
<a href="https://botalex.itch.io/" target="_blank">Games</a>
|
<a href="https://botalex.itch.io/" target="_blank">Games</a>
|
||||||
|
|
@ -150,10 +159,8 @@
|
||||||
href="https://botalex.itch.io/"
|
href="https://botalex.itch.io/"
|
||||||
target="_blank">Games</a
|
target="_blank">Games</a
|
||||||
>
|
>
|
||||||
<a
|
<a href="/cv?hideOnPrint=1" target="_blank" class="justify-center"
|
||||||
href="/zhen/cv/rev3?hideOnPrint=1"
|
>{$re?.nick ?? "Alex"}'s CV</a
|
||||||
target="_blank"
|
|
||||||
class="justify-center">Zhen's CV</a
|
|
||||||
>
|
>
|
||||||
<!-- <a onclick={resetNavBar} href="/posts">Blog</a>
|
<!-- <a onclick={resetNavBar} href="/posts">Blog</a>
|
||||||
<a onclick={resetNavBar} href="/about">About</a> -->
|
<a onclick={resetNavBar} href="/about">About</a> -->
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import ProfileSpacer from "./comps/ProfileSpacer.svelte";
|
// import ProfileSpacer from "./comps/ProfileSpacer.svelte";
|
||||||
import MediaQuery from "svelte-media-queries";
|
import MediaQuery from "svelte-media-queries";
|
||||||
import { onMount, tick } from "svelte";
|
import onMount from "@e/onMount";
|
||||||
|
// import tick from "@e/tick";
|
||||||
|
|
||||||
import PreviewDeprivedLogo from "$lib/images/DeprivedLogo-NoBackground.png";
|
import PreviewDeprivedLogo from "$lib/images/DeprivedLogo-NoBackground.png";
|
||||||
|
|
||||||
|
|
@ -23,12 +24,13 @@
|
||||||
import Time3 from "$lib/GamePreviews/time-3.png";
|
import Time3 from "$lib/GamePreviews/time-3.png";
|
||||||
import Time4 from "$lib/GamePreviews/time-4.png";
|
import Time4 from "$lib/GamePreviews/time-4.png";
|
||||||
import Time5 from "$lib/GamePreviews/time-5.gif";
|
import Time5 from "$lib/GamePreviews/time-5.gif";
|
||||||
import Tags from "./comps/Tags.svelte";
|
// import Tags from "./comps/Tags.svelte";
|
||||||
import NameAndTag from "./comps/NameAndTag.svelte";
|
// import NameAndTag from "./comps/NameAndTag.svelte";
|
||||||
import Profile from "./comps/Profile.svelte";
|
import Profile from "./comps/Profile.svelte";
|
||||||
import DeprivedTrackerSection from "./comps/DeprivedTrackerSection.svelte";
|
import DeprivedTrackerSection from "./comps/DeprivedTrackerSection.svelte";
|
||||||
|
import re from "@src/ts/Redaction/Redactor";
|
||||||
|
|
||||||
const mobileThreshold: string = "600px"; // was 1000px. zhen testing
|
const mobileThreshold: string = "600px"; // was 1000px.
|
||||||
let mobile: boolean;
|
let mobile: boolean;
|
||||||
let debug = false;
|
let debug = false;
|
||||||
|
|
||||||
|
|
@ -101,19 +103,19 @@
|
||||||
class="grid max-lg:grid-cols-1 sm:grid-cols-2 gap-4 p-4 max-lg:px-0 w-full"
|
class="grid max-lg:grid-cols-1 sm:grid-cols-2 gap-4 p-4 max-lg:px-0 w-full"
|
||||||
>
|
>
|
||||||
<Profile
|
<Profile
|
||||||
name="Zhen / Alex"
|
name={$re?.nick ? $re?.nick + "/Alex" : "Alex"}
|
||||||
tags={["Programmer", "3D artist", "UX Designer"]}
|
tags={["Programmer", "3D artist", "UX Designer"]}
|
||||||
isMobile={mobile}
|
isMobile={mobile}
|
||||||
>
|
>
|
||||||
<span>
|
<span>
|
||||||
<p>
|
<p>
|
||||||
Hi, I am Alex/Zhen, {@html !mobile ? "" : "<br/>"} I'm that chinese
|
Hi, I am {$re?.nick ? $re?.nick + "/Alex" : "Alex"}, {@html !mobile
|
||||||
guy.
|
? ""
|
||||||
|
: "<br/>"} I'm that chinese guy.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Here's my CV: <a
|
Here's my CV: <a href="/cv?hideOnPrint=1" style="color:lightblue;"
|
||||||
href="/zhen/cv/rev3?hideOnPrint=1"
|
>pdf</a
|
||||||
style="color:lightblue;">pdf</a
|
|
||||||
>
|
>
|
||||||
</p>
|
</p>
|
||||||
</span>
|
</span>
|
||||||
|
|
@ -203,7 +205,6 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="py-4"></div>
|
<div class="py-4"></div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class="grid place-content-center place-items-center pointer-events-auto font-mono"
|
class="grid place-content-center place-items-center pointer-events-auto font-mono"
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { onMount } from "svelte";
|
import onMount from "@e/onMount";
|
||||||
|
|
||||||
export let images: string[] = []; // Expose images as a parameter
|
export let images: string[] = []; // Expose images as a parameter
|
||||||
let currentIndex: number = 0;
|
let currentIndex: number = 0;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { onMount, onDestroy } from "svelte";
|
import onMount from "@e/onMount";
|
||||||
|
import onDestroy from "@e/onDestroy";
|
||||||
import MediaQuery from "svelte-media-queries";
|
import MediaQuery from "svelte-media-queries";
|
||||||
|
|
||||||
// Public props
|
// Public props
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<script>
|
<script>
|
||||||
import { onMount } from "svelte";
|
import onMount from "@e/onMount";
|
||||||
|
|
||||||
let debug = false;
|
let debug = false;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { onMount } from "svelte";
|
import onMount from "@e/onMount";
|
||||||
import { Vector2 } from "../zhen/Utils/Vector2";
|
import { Vector2 } from "../zhen/Utils/Vector2";
|
||||||
|
|
||||||
// Params
|
// Params
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,10 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import svelteLogo from "$lib/svelteLogos/svelte-logo.png";
|
import svelteLogo from "$lib/svelteLogos/svelte-logo.png";
|
||||||
import { browser } from "$app/environment";
|
import onMount from "@e/onMount";
|
||||||
import { onDestroy, onMount } from "svelte";
|
import onDestroy from "@e/onDestroy";
|
||||||
import { ArrowBigDown } from "lucide-svelte";
|
import ArrowBigDown from "lucide-svelte/icons/arrow-big-down";
|
||||||
import { fly } from "svelte/transition";
|
import fly from "@e/fly";
|
||||||
|
import re from "@ts/Redaction/Redactor";
|
||||||
const buildTime = __BUILD_TIME__;
|
const buildTime = __BUILD_TIME__;
|
||||||
|
|
||||||
let scrollY = 0;
|
let scrollY = 0;
|
||||||
|
|
@ -156,16 +157,16 @@
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div class="{hideOnPrint ? 'hide-on-print' : ''} w-full">
|
<div class="{hideOnPrint ? 'hide-on-print' : ''} w-full">
|
||||||
<!-- Keep scrolling thing -->
|
<!-- <!-- Keep scrolling thing --> -->
|
||||||
<div class="hidden h-64 w-full flex flex-col justify-center items-center">
|
<!-- <div class="hidden h-64 w-full flex flex-col justify-center items-center"> -->
|
||||||
<div>Keep scrolling to veiw Zhen's portfolio site!</div>
|
<!-- <div>Keep scrolling to veiw [Redacted]'s portfolio site!</div> -->
|
||||||
<div class="flex justify-center">
|
<!-- <div class="flex justify-center"> -->
|
||||||
<ArrowBigDown />
|
<!-- <ArrowBigDown /> -->
|
||||||
<ArrowBigDown />
|
<!-- <ArrowBigDown /> -->
|
||||||
<ArrowBigDown />
|
<!-- <ArrowBigDown /> -->
|
||||||
<ArrowBigDown />
|
<!-- <ArrowBigDown /> -->
|
||||||
</div>
|
<!-- </div> -->
|
||||||
</div>
|
<!-- </div> -->
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class="hidden h-64 w-full flex flex-col justify-end items-center"
|
class="hidden h-64 w-full flex flex-col justify-end items-center"
|
||||||
|
|
@ -193,7 +194,7 @@
|
||||||
<br />
|
<br />
|
||||||
<span>Snorre Ettrup Altschul</span>
|
<span>Snorre Ettrup Altschul</span>
|
||||||
<br />
|
<br />
|
||||||
<span>Zhentao Wei</span>
|
<span>{$re?.name ?? "BOT Alex"}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col items-center">
|
<div class="flex flex-col items-center">
|
||||||
<h3><b>About this website</b></h3>
|
<h3><b>About this website</b></h3>
|
||||||
|
|
@ -221,7 +222,9 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col items-center">
|
<div class="flex flex-col items-center">
|
||||||
<h3><b>Contact</b></h3>
|
<h3><b>Contact</b></h3>
|
||||||
<a href="mailto:zhen@deprived.dev">zhen@deprived.dev</a>
|
<a href="mailto:{$re?.email ?? 'Alex@deprived.dev'}"
|
||||||
|
>{$re?.email ?? "alex@deprived.dev"}</a
|
||||||
|
>
|
||||||
<div class="mt-2"></div>
|
<div class="mt-2"></div>
|
||||||
<a
|
<a
|
||||||
href="https://discord.gg/awatEEqc3M"
|
href="https://discord.gg/awatEEqc3M"
|
||||||
|
|
|
||||||
321
src/routes/cv/+page.svelte
Normal file
|
|
@ -0,0 +1,321 @@
|
||||||
|
<script lang="ts">
|
||||||
|
import re from "@ts/Redaction/Redactor";
|
||||||
|
|
||||||
|
// Left side
|
||||||
|
import NameAndImage from "./comps/NameAndImage.svelte";
|
||||||
|
import ShortProfile from "./comps/ShortProfile.svelte";
|
||||||
|
import CombinedContacts from "./comps/CombinedContacts.svelte";
|
||||||
|
import LinkedInQR from "./comps/LinkedInQR.svelte";
|
||||||
|
|
||||||
|
// Right side
|
||||||
|
import Profile from "./comps/Profile.svelte";
|
||||||
|
import Experience from "./comps/Experience.svelte";
|
||||||
|
import Education from "./comps/Education.svelte";
|
||||||
|
import BiggestFlex from "./comps/BiggestFlex.svelte";
|
||||||
|
import TableOfProjects from "./comps/TableOfProjects.svelte";
|
||||||
|
|
||||||
|
// Decorations
|
||||||
|
import LeftTopDecor from "./comps/LeftTopDecor.svelte";
|
||||||
|
import BottomRightDecor from "./comps/BottomRightDecor.svelte";
|
||||||
|
import AlexWatermark from "./comps/AlexWatermark.svelte";
|
||||||
|
import RepeatedSkills from "./comps/RepeatedSkills.svelte";
|
||||||
|
|
||||||
|
// Discord embed
|
||||||
|
import preveiwImage from "$lib/alex/cv-comps/preview.png";
|
||||||
|
|
||||||
|
// Print detection setup
|
||||||
|
import onMount from "@e/onMount";
|
||||||
|
onMount(() => {
|
||||||
|
// Check if the query parameter exists in the URL
|
||||||
|
const urlParams = new URLSearchParams(window.location.search);
|
||||||
|
const hideOnPrintParam = urlParams.get("hideOnPrint");
|
||||||
|
|
||||||
|
// If the query parameter is not detected, reload the page with the parameter added
|
||||||
|
if (!hideOnPrintParam) {
|
||||||
|
window.location.href = `${window.location.href}?hideOnPrint=1`;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function getFormattedDate(): string {
|
||||||
|
const date = new Date();
|
||||||
|
const day = String(date.getDate()).padStart(2, "0");
|
||||||
|
const month = String(date.getMonth() + 1).padStart(2, "0");
|
||||||
|
const year = date.getFullYear();
|
||||||
|
|
||||||
|
return `${day}-${month}-${year}`;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<title>{$re?.name ?? "Alex"}'s CV {getFormattedDate()}</title>
|
||||||
|
<meta content="{$re?.name ?? 'Alex'}'s CV" property="og:title" />
|
||||||
|
<meta
|
||||||
|
content="This CV is made completely with svelte + html + css + js"
|
||||||
|
property="og:description"
|
||||||
|
/>
|
||||||
|
<meta content={preveiwImage} property="og:image" />
|
||||||
|
<meta content="#bdd6ee" data-react-helmet="true" name="theme-color" />
|
||||||
|
|
||||||
|
<div class="cv-info-container hide-on-print">
|
||||||
|
<div>
|
||||||
|
Under here is my CV rev1 for an application made entirely in HTML and CSS.
|
||||||
|
The page is designed to be saved as PDF. This can be done by pressing <div
|
||||||
|
class="keyboard-key"
|
||||||
|
>
|
||||||
|
P
|
||||||
|
</div>
|
||||||
|
+
|
||||||
|
<div class="keyboard-key">CTRL</div>
|
||||||
|
, then set scaling to 100% and no margins. Lastly, select save to PDF or print.
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
I have to sadly recommend chrome for this process. Firefox somehow messes with
|
||||||
|
the quality of the PDF :(
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="NotoSans cv-config cv-container-container include-in-print">
|
||||||
|
<div class="cv-container sections decorations">
|
||||||
|
<div id="left-section" class="bg-grid-cv flex justify-center">
|
||||||
|
<LeftTopDecor />
|
||||||
|
<BottomRightDecor Style="pointer-events: none;" />
|
||||||
|
<div
|
||||||
|
class="absolute rotate-12 width-[10cm] h-full right-[15cm]"
|
||||||
|
style="background-color: #bdd6ee"
|
||||||
|
></div>
|
||||||
|
<div class="text-[var(--left-text-color)] pointer-events-none">
|
||||||
|
<div
|
||||||
|
class="pointer-events-auto flex flex-col justify-center w-full items-center"
|
||||||
|
>
|
||||||
|
<NameAndImage />
|
||||||
|
<div class="py-2"></div>
|
||||||
|
<ShortProfile />
|
||||||
|
<div class="py-2"></div>
|
||||||
|
<CombinedContacts />
|
||||||
|
<div class="py-2"></div>
|
||||||
|
<LinkedInQR />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="leftSectionSeperator"></div>
|
||||||
|
<div id="right-section" class="text-[var(--right-text-color)]">
|
||||||
|
<AlexWatermark Style="pointer-events: none;" />
|
||||||
|
<div id="TopRightSkillsText">
|
||||||
|
<RepeatedSkills
|
||||||
|
class="cozette-force"
|
||||||
|
targetTextHeight={30}
|
||||||
|
targetTextWidth={75}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<Profile />
|
||||||
|
<BiggestFlex />
|
||||||
|
<TableOfProjects />
|
||||||
|
<Experience />
|
||||||
|
<Education />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.cv-config * {
|
||||||
|
--left-text-color: #eeeeee;
|
||||||
|
--left-line-color: #999999;
|
||||||
|
|
||||||
|
--left-decor-text-color: #eeeeee;
|
||||||
|
--left-decor-line-color: #999999;
|
||||||
|
|
||||||
|
--qr-color: #999999;
|
||||||
|
|
||||||
|
--left-grid-line-color: #ffffff;
|
||||||
|
--left-grid-bg-color: #000000;
|
||||||
|
--left-grid-opacity: 0.1;
|
||||||
|
--left-grid-size: 10px;
|
||||||
|
|
||||||
|
--right-text-color: #333333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.corner-border-container {
|
||||||
|
background-color: var(--left-grid-bg-color);
|
||||||
|
background-image:
|
||||||
|
linear-gradient(
|
||||||
|
var(--left-decor-line-color),
|
||||||
|
var(--left-decor-line-color)
|
||||||
|
),
|
||||||
|
linear-gradient(
|
||||||
|
var(--left-decor-line-color),
|
||||||
|
var(--left-decor-line-color)
|
||||||
|
),
|
||||||
|
linear-gradient(
|
||||||
|
var(--left-decor-line-color),
|
||||||
|
var(--left-decor-line-color)
|
||||||
|
),
|
||||||
|
linear-gradient(
|
||||||
|
var(--left-decor-line-color),
|
||||||
|
var(--left-decor-line-color)
|
||||||
|
);
|
||||||
|
background-size:
|
||||||
|
30px 4px,
|
||||||
|
/* top-left horizontal */ 4px 30px,
|
||||||
|
/* top-left vertical */ 30px 4px,
|
||||||
|
/* bottom-right horizontal */ 4px 30px; /* bottom-right vertical */
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position:
|
||||||
|
top left,
|
||||||
|
top left,
|
||||||
|
bottom right,
|
||||||
|
bottom right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-grid-cv {
|
||||||
|
background:
|
||||||
|
linear-gradient(
|
||||||
|
-90deg,
|
||||||
|
rgba(255, 255, 255, var(--left-grid-opacity)) 1px,
|
||||||
|
transparent 1px
|
||||||
|
),
|
||||||
|
linear-gradient(
|
||||||
|
rgba(255, 255, 255, var(--left-grid-opacity)) 1px,
|
||||||
|
transparent 1px
|
||||||
|
),
|
||||||
|
var(--left-grid-line-color);
|
||||||
|
background-size:
|
||||||
|
var(--left-grid-size) var(--left-grid-size),
|
||||||
|
var(--left-grid-size) var(--left-grid-size),
|
||||||
|
80px 80px,
|
||||||
|
80px 80px,
|
||||||
|
80px 80px,
|
||||||
|
80px 80px,
|
||||||
|
80px 80px,
|
||||||
|
80px 80px;
|
||||||
|
background-color: var(--color-base-100);
|
||||||
|
}
|
||||||
|
|
||||||
|
.cv-info-container {
|
||||||
|
height: 40mm;
|
||||||
|
background-color: #2b2a2a;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.keyboard-key {
|
||||||
|
display: inline;
|
||||||
|
padding-left: 1mm;
|
||||||
|
padding-right: 1mm;
|
||||||
|
|
||||||
|
border-radius: 2mm;
|
||||||
|
|
||||||
|
background-color: #3e3d3d;
|
||||||
|
}
|
||||||
|
|
||||||
|
> div {
|
||||||
|
width: 80%;
|
||||||
|
height: 60%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.cv-container-container {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
display: grid;
|
||||||
|
place-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cv-container {
|
||||||
|
width: 210mm;
|
||||||
|
height: 297mm;
|
||||||
|
|
||||||
|
background-color: #eeeeee;
|
||||||
|
|
||||||
|
overflow: visible;
|
||||||
|
display: flex;
|
||||||
|
padding: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sections {
|
||||||
|
// Shared between sections
|
||||||
|
> div {
|
||||||
|
display: grid;
|
||||||
|
z-index: 0;
|
||||||
|
|
||||||
|
// Needed to cuttoff the extra decoration
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
#left-section {
|
||||||
|
// background-color: #bdd6ee;
|
||||||
|
|
||||||
|
> div:last-child {
|
||||||
|
z-index: 1;
|
||||||
|
width: 17.5rem;
|
||||||
|
|
||||||
|
left: 0;
|
||||||
|
|
||||||
|
padding-top: 30mm;
|
||||||
|
padding-bottom: 30mm;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#right-section {
|
||||||
|
width: calc(100% / 3 * 2);
|
||||||
|
|
||||||
|
> div:last-child {
|
||||||
|
z-index: 1;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
left: 0;
|
||||||
|
|
||||||
|
display: grid;
|
||||||
|
place-items: center;
|
||||||
|
row-gap: 6mm;
|
||||||
|
|
||||||
|
padding-top: 45mm;
|
||||||
|
padding-bottom: 30mm;
|
||||||
|
|
||||||
|
// Disable interactivity for padding
|
||||||
|
// pointer-events: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.decorations {
|
||||||
|
#leftSectionSeperator {
|
||||||
|
position: relative;
|
||||||
|
height: 100%;
|
||||||
|
width: 0%;
|
||||||
|
z-index: 1;
|
||||||
|
overflow: visible;
|
||||||
|
> div {
|
||||||
|
position: absolute;
|
||||||
|
height: 100%;
|
||||||
|
width: 5mm;
|
||||||
|
z-index: 1;
|
||||||
|
background: linear-gradient(90deg, #3636364f, #00000000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
> div {
|
||||||
|
#TopRightSkillsText {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 0;
|
||||||
|
|
||||||
|
display: grid;
|
||||||
|
place-items: center;
|
||||||
|
vertical-align: top;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
place-content: center;
|
||||||
|
|
||||||
|
padding: 0;
|
||||||
|
height: 50mm;
|
||||||
|
|
||||||
|
mask-image: linear-gradient(180deg, #000 0%, transparent 110%);
|
||||||
|
|
||||||
|
color: rgb(190, 190, 190);
|
||||||
|
font-family: "CozetteVector";
|
||||||
|
font-size: x-large;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
23
src/routes/cv/comps/AlexWatermark.svelte
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
<script>
|
||||||
|
export let Style = "";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="container" style="{Style}">
|
||||||
|
ALEX
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.container {
|
||||||
|
position: absolute;
|
||||||
|
display: grid;
|
||||||
|
justify-self: end;
|
||||||
|
vertical-align: bottom;
|
||||||
|
align-self: flex-end;
|
||||||
|
|
||||||
|
// font settings
|
||||||
|
font-size: 80mm;
|
||||||
|
color: #e4e4e4;
|
||||||
|
|
||||||
|
transform: translate(32%, -32%) rotate(-90deg);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
25
src/routes/cv/comps/BiggestFlex.svelte
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
<div class="short-profile-container">
|
||||||
|
<div class="flex gap-1 items-baseline">
|
||||||
|
<b style="text-align:left;">
|
||||||
|
Biggest flex
|
||||||
|
</b>
|
||||||
|
<h1 style="font-size: 0.5rem; color: grey;">*Gamejams that had competitions.</h1>
|
||||||
|
</div>
|
||||||
|
<div class="text-[0.85rem] text-left">
|
||||||
|
<a href="https://deprived.dev" >The <span class="text-blue-500 underline">deprived devs</span></a> has won every gamejam, we've participated. <br/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.short-profile-container{
|
||||||
|
width: 90%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.short-profile-container > div:first-child {
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
/* Bottom border stripe*/
|
||||||
|
border-bottom: 1mm solid black;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
53
src/routes/cv/comps/BottomRightDecor.svelte
Normal file
|
|
@ -0,0 +1,53 @@
|
||||||
|
<script>
|
||||||
|
export let Style = "";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="container" style={Style}>
|
||||||
|
<div class="w-full flex justify-center">
|
||||||
|
<div class="text-center"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.container {
|
||||||
|
position: absolute;
|
||||||
|
transform: translate(20.3mm, -5mm) rotate(-45deg);
|
||||||
|
display: grid;
|
||||||
|
justify-self: end;
|
||||||
|
vertical-align: bottom;
|
||||||
|
align-self: flex-end;
|
||||||
|
|
||||||
|
z-index: 0;
|
||||||
|
|
||||||
|
> div:nth-child(1) {
|
||||||
|
padding-top: 5mm;
|
||||||
|
//border-bottom: #4472c4 dashed 2mm;
|
||||||
|
|
||||||
|
background-image: linear-gradient(
|
||||||
|
to right,
|
||||||
|
var(--left-decor-line-color) 70%,
|
||||||
|
rgba(255, 255, 255, 0) 0%
|
||||||
|
);
|
||||||
|
background-position: top;
|
||||||
|
background-size: 6mm 1.5mm;
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
}
|
||||||
|
|
||||||
|
> div:nth-child(2) {
|
||||||
|
background-color: var(--left-decor-line-color);
|
||||||
|
width: 100mm;
|
||||||
|
height: 25mm;
|
||||||
|
|
||||||
|
// Text
|
||||||
|
display: grid;
|
||||||
|
place-content: center;
|
||||||
|
align-content: flex-start;
|
||||||
|
> div {
|
||||||
|
padding-top: 3.5mm;
|
||||||
|
color: #4a7bcf;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
7
src/routes/cv/comps/CombinedContacts.svelte
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
<script>
|
||||||
|
import Contact from "./Contact.svelte";
|
||||||
|
import OtherContact from "./OtherContact.svelte";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<Contact/>
|
||||||
|
<OtherContact/>
|
||||||
81
src/routes/cv/comps/Contact.svelte
Normal file
|
|
@ -0,0 +1,81 @@
|
||||||
|
<script lang="ts">
|
||||||
|
import re from "@ts/Redaction/Redactor";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
<div>
|
||||||
|
<b style="text-align:left;"> Contact </b>
|
||||||
|
</div>
|
||||||
|
<div class="table-display">
|
||||||
|
<div class="table-item">
|
||||||
|
<div>Email</div>
|
||||||
|
<div>{$re?.email ?? "alex@deprived.dev"}</div>
|
||||||
|
</div>
|
||||||
|
<div class="table-item">
|
||||||
|
<div>Phone</div>
|
||||||
|
<div>{$re?.phone ?? "1-800-273-8255"}</div>
|
||||||
|
</div>
|
||||||
|
<div class="table-item">
|
||||||
|
<div>LinkedIn</div>
|
||||||
|
<a
|
||||||
|
href={$re?.linkedIn.link ??
|
||||||
|
"https://www.youtube.com/watch?v=PaPotS8GSpc"}
|
||||||
|
>{$re?.linkedIn.text ?? "cool video lmao"}</a
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.container {
|
||||||
|
display: grid;
|
||||||
|
place-items: center;
|
||||||
|
width: 70%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container > div:first-child {
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
/* Bottom border stripe*/
|
||||||
|
border-bottom: 1mm solid var(--left-line-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-display {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-item {
|
||||||
|
display: flex;
|
||||||
|
justify-items: start;
|
||||||
|
|
||||||
|
width: 100%;
|
||||||
|
border-bottom: 0.25mm solid #000000;
|
||||||
|
|
||||||
|
> a {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
> div,
|
||||||
|
> a {
|
||||||
|
&:first-child {
|
||||||
|
width: 35%;
|
||||||
|
font-size: 4mm;
|
||||||
|
|
||||||
|
display: grid;
|
||||||
|
place-content: center start;
|
||||||
|
|
||||||
|
border-right: rgba(128, 128, 128, 0.4) dashed 0.1mm;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:nth-child(2) {
|
||||||
|
width: 65%;
|
||||||
|
|
||||||
|
font-size: 3.25mm;
|
||||||
|
display: grid;
|
||||||
|
place-content: center;
|
||||||
|
|
||||||
|
padding-left: 1mm;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
51
src/routes/cv/comps/Education.svelte
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
<script>
|
||||||
|
import SasLogo from "$lib/alex/cv-comps/SASLogo.png";
|
||||||
|
|
||||||
|
import IconAndText2 from "./IconAndText2.svelte";
|
||||||
|
import re from "@src/ts/Redaction/Redactor";
|
||||||
|
import env, { initEnv } from "@src/ts/EnvHandler";
|
||||||
|
import onMount from "@src/optimizers/onMount";
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
initEnv();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="container h-10">
|
||||||
|
<div>
|
||||||
|
<b style="text-align:left;"> Education </b>
|
||||||
|
</div>
|
||||||
|
<div class="flex justify-center p-2 w-full">
|
||||||
|
<IconAndText2
|
||||||
|
logo={$re?.education[0].imageId.replace("[PB]", env.POCKETBASE_URL) ?? ""}
|
||||||
|
>
|
||||||
|
<b>{$re?.education[0].name ?? ""}</b><br />
|
||||||
|
<p style="font-size: 0.5rem;">AI and data</p>
|
||||||
|
</IconAndText2>
|
||||||
|
<IconAndText2 logo={$re?.education[1].imageId ?? ""}>
|
||||||
|
<b>{$re?.education[0].name ?? ""}</b><br />
|
||||||
|
<p style="font-size: 0.5rem;">Computer science</p>
|
||||||
|
</IconAndText2>
|
||||||
|
<IconAndText2 logo={SasLogo}>
|
||||||
|
<b>Master class</b><br />
|
||||||
|
<p style="font-size: 0.5rem;">SAS Programming</p>
|
||||||
|
</IconAndText2>
|
||||||
|
<IconAndText2 logo={$re?.education[2].imageId ?? ""}>
|
||||||
|
<span class="font-semibold">{$re?.education[2].name ?? ""}</span><br />
|
||||||
|
<p style="font-size: 0.5rem;">VR development</p>
|
||||||
|
</IconAndText2>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.container {
|
||||||
|
display: grid;
|
||||||
|
place-items: center;
|
||||||
|
width: 90%;
|
||||||
|
|
||||||
|
> div:first-child {
|
||||||
|
border-bottom: black 1mm solid;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
72
src/routes/cv/comps/Experience.svelte
Normal file
|
|
@ -0,0 +1,72 @@
|
||||||
|
<script>
|
||||||
|
import re from "@src/ts/Redaction/Redactor";
|
||||||
|
import IconAndText from "./IconAndText.svelte";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
<div>
|
||||||
|
<b style="text-align:left;"> Experience </b>
|
||||||
|
</div>
|
||||||
|
<div class="table">
|
||||||
|
<div class="table-item">
|
||||||
|
<IconAndText logo={$re?.experience[0].imageId ?? ""}>
|
||||||
|
<b>Full-stack</b><br />
|
||||||
|
{$re?.experience[0].name}<br />
|
||||||
|
<i>Feb 2025 - Now</i>
|
||||||
|
</IconAndText>
|
||||||
|
</div>
|
||||||
|
<div class="table-item">
|
||||||
|
<IconAndText logo={$re?.experience[1].imageId ?? ""}>
|
||||||
|
<b>Data annotator</b><br />
|
||||||
|
{$re?.experience[1].name}<br />
|
||||||
|
<i>Jul 2024 - Now</i>
|
||||||
|
</IconAndText>
|
||||||
|
</div>
|
||||||
|
<div class="table-item">
|
||||||
|
<IconAndText logo={$re?.experience[2].imageId ?? ""}>
|
||||||
|
<b>3D printer manager</b> - Volunteer<br />
|
||||||
|
{$re?.experience[2].name}<br />
|
||||||
|
<i>Nov 2023 - Now</i>
|
||||||
|
</IconAndText>
|
||||||
|
</div>
|
||||||
|
<div class="table-item">
|
||||||
|
<IconAndText logo={$re?.experience[3].imageId ?? ""}>
|
||||||
|
<b>Machine Learning Engineer</b> - Short term intern<br />
|
||||||
|
{$re?.experience[3].name}<br />
|
||||||
|
<i>Apr 2024 - Apr 2024</i>
|
||||||
|
</IconAndText>
|
||||||
|
</div>
|
||||||
|
<div class="table-item">
|
||||||
|
<IconAndText logo={$re?.experience[4].imageId ?? ""}>
|
||||||
|
<b>Assistant</b> - Short term intern<br />
|
||||||
|
{$re?.experience[4].name}<br />
|
||||||
|
<i>Oct 2020 - Oct 2020</i>
|
||||||
|
</IconAndText>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.container {
|
||||||
|
display: grid;
|
||||||
|
place-items: center;
|
||||||
|
width: 90%;
|
||||||
|
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
& > div:first-child {
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
/* Bottom border stripe*/
|
||||||
|
border-bottom: 1mm solid black;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-item {
|
||||||
|
padding: 2mm;
|
||||||
|
|
||||||
|
&:not(:last-child) {
|
||||||
|
border-bottom: 0.25mm solid #000000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
44
src/routes/cv/comps/IconAndText.svelte
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
<script lang="ts">
|
||||||
|
export let logo: string;
|
||||||
|
export let logoWidths: string = "10%";
|
||||||
|
|
||||||
|
export let fontSize: string = "3mm";
|
||||||
|
export let lineHeight: string = "3.1mm";
|
||||||
|
|
||||||
|
import env, { initEnv } from "@src/ts/EnvHandler";
|
||||||
|
|
||||||
|
import onMount from "@e/onMount";
|
||||||
|
onMount(() => {
|
||||||
|
imageCaption = logo.split(/(\\|\/)/g).pop();
|
||||||
|
initEnv();
|
||||||
|
});
|
||||||
|
|
||||||
|
let imageCaption: undefined | string; // Not a high piority, you get the file name and thats it
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
<img
|
||||||
|
src={logo.replace("[PB]", env.POCKETBASE_URL) ?? ""}
|
||||||
|
class="bg-white w-10 h-10 object-contain rounded shadow"
|
||||||
|
alt={imageCaption}
|
||||||
|
width={logoWidths}
|
||||||
|
/>
|
||||||
|
<div style="line-height: {lineHeight};">
|
||||||
|
<span style="font-size: {fontSize};">
|
||||||
|
<slot />
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.container {
|
||||||
|
display: flex;
|
||||||
|
justify-items: start;
|
||||||
|
|
||||||
|
& > div {
|
||||||
|
padding-left: 3mm;
|
||||||
|
|
||||||
|
text-align: start;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
29
src/routes/cv/comps/IconAndText2.svelte
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
<script lang="ts">
|
||||||
|
export let logo: string;
|
||||||
|
export let logoWidths: string = "35%";
|
||||||
|
|
||||||
|
import onMount from "@e/onMount";
|
||||||
|
import env, { initEnv } from "@src/ts/EnvHandler";
|
||||||
|
onMount(() => {
|
||||||
|
imageCaption = logo.split(/(\\|\/)/g).pop();
|
||||||
|
initEnv();
|
||||||
|
});
|
||||||
|
|
||||||
|
let imageCaption: undefined | string; // Not a high piority, you get the file name and thats it
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class=" h-full container flex">
|
||||||
|
<div class="flex h-full w-6 items-center overflow-hidden rounded">
|
||||||
|
<img
|
||||||
|
src={logo.replace("[PB]", env.POCKETBASE_URL) ?? ""}
|
||||||
|
class=" w-6 h-6 object-cover shadow"
|
||||||
|
alt={imageCaption}
|
||||||
|
width={logoWidths}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="px-1 ml-1 h-full text-[0.5rem]">
|
||||||
|
<span class="inline">
|
||||||
|
<slot />
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
75
src/routes/cv/comps/LeftTopDecor.svelte
Normal file
|
|
@ -0,0 +1,75 @@
|
||||||
|
<script>
|
||||||
|
import RepeatedSkills from "./RepeatedSkills.svelte";
|
||||||
|
|
||||||
|
// Cedit
|
||||||
|
import LinkToSource from "./LinkToSource.svelte";
|
||||||
|
|
||||||
|
export let Style = "";
|
||||||
|
export let Class = "";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="container {Class}" style={Style}>
|
||||||
|
<div class=" text-center bg-[var(--left-grid-bg-color)]">
|
||||||
|
<RepeatedSkills
|
||||||
|
textOverride={["Hello", "你好", "Hej"]}
|
||||||
|
targetTextHeight={3}
|
||||||
|
targetTextWidth={50}
|
||||||
|
applyRotation={false}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div />
|
||||||
|
<div class="flex justify-center">
|
||||||
|
<div class="w-[6cm]">
|
||||||
|
<LinkToSource />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.container {
|
||||||
|
position: absolute;
|
||||||
|
transform: translate(-30mm, 7.5mm) rotate(-45deg);
|
||||||
|
display: grid;
|
||||||
|
justify-self: start;
|
||||||
|
vertical-align: top;
|
||||||
|
align-self: flex-start;
|
||||||
|
|
||||||
|
z-index: 0;
|
||||||
|
|
||||||
|
> div:nth-child(1) {
|
||||||
|
//background-color: #2f559622;
|
||||||
|
width: 100mm;
|
||||||
|
height: 17.5mm;
|
||||||
|
padding-bottom: 1mm;
|
||||||
|
padding-top: 1mm;
|
||||||
|
|
||||||
|
// Text inside
|
||||||
|
display: grid;
|
||||||
|
place-content: center;
|
||||||
|
border-bottom: var(--left-decor-line-color) dotted 0.5mm;
|
||||||
|
border-top: var(--left-decor-line-color) dotted 0.5mm;
|
||||||
|
|
||||||
|
&:first-child {
|
||||||
|
color: var(--left-decor-text-color);
|
||||||
|
font-size: 3mm;
|
||||||
|
//font-weight: bold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
> div:nth-child(2) {
|
||||||
|
padding-top: 4mm;
|
||||||
|
//border-bottom: #4472c4 dashed 2mm;
|
||||||
|
|
||||||
|
// background-color: var(--left-grid-bg-color);
|
||||||
|
|
||||||
|
background-image: linear-gradient(
|
||||||
|
to right,
|
||||||
|
var(--left-decor-line-color) 70%,
|
||||||
|
rgba(255, 255, 255, 0) 0%
|
||||||
|
);
|
||||||
|
background-position: bottom;
|
||||||
|
background-size: 6mm 1.5mm;
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
50
src/routes/cv/comps/LinkToSource.svelte
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
<script lang="ts">
|
||||||
|
import svelteLogo from "$lib/svelteLogos/svelte-logo-cutout.svg";
|
||||||
|
import onMount from "@src/optimizers/onMount";
|
||||||
|
import re from "@src/ts/Redaction/Redactor";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
<div class="flex justify-center">
|
||||||
|
<div class="corner-border-container p-1 m-1">
|
||||||
|
<div class="flex">
|
||||||
|
This CV was made using html, css and <a
|
||||||
|
class="grid place-content-center"
|
||||||
|
href="https://kit.svelte.dev/"
|
||||||
|
><img src={svelteLogo} class="w-2 h-2" alt="SvelteKit logo" /></a
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
Sources:
|
||||||
|
<a
|
||||||
|
href={$re?.cv.sourceLink ??
|
||||||
|
"https://www.youtube.com/watch?v=0TaNezk4wNQ"}>CV source code</a
|
||||||
|
>
|
||||||
|
and
|
||||||
|
<a href="/cv?hideOnPrint=1">My Website</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.container {
|
||||||
|
z-index: 1;
|
||||||
|
|
||||||
|
font-size: 0.5rem;
|
||||||
|
|
||||||
|
//white-space: nowrap;
|
||||||
|
|
||||||
|
color: #777777;
|
||||||
|
|
||||||
|
* a {
|
||||||
|
color: #3d6ddc;
|
||||||
|
padding-left: 1mm;
|
||||||
|
padding-right: 1mm;
|
||||||
|
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
div:nth-child(2) {
|
||||||
|
padding-bottom: 2mm;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
105
src/routes/cv/comps/LinkedInQR.svelte
Normal file
|
|
@ -0,0 +1,105 @@
|
||||||
|
<script lang="ts">
|
||||||
|
import re from "@src/ts/Redaction/Redactor";
|
||||||
|
|
||||||
|
// Gave up because a little drunk, so rest is chatgpt
|
||||||
|
|
||||||
|
function getHTML(url: string): Promise<string> {
|
||||||
|
return fetch(url, { method: "GET", headers: { Accept: "text/html" } }).then(
|
||||||
|
(res) => {
|
||||||
|
if (!res.ok)
|
||||||
|
throw new Error(`GET ${url} failed: ${res.status} ${res.statusText}`);
|
||||||
|
return res.text();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// recompute the promise when the (store-derived) URL changes
|
||||||
|
$: url = $re?.linkedIn?.imageId || "";
|
||||||
|
$: htmlPromise = url ? getHTML(url) : Promise.resolve("");
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
<div>LinkedIn</div>
|
||||||
|
<div class="qrcode corner-border-container p-4">
|
||||||
|
{#await htmlPromise}
|
||||||
|
<span>Loading…</span>
|
||||||
|
{:then html}
|
||||||
|
{@html html}
|
||||||
|
{:catch err}
|
||||||
|
<span class="text-red-600">{err.message}</span>
|
||||||
|
{/await}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.corner-border-container {
|
||||||
|
--length: 20px;
|
||||||
|
--width: 4px;
|
||||||
|
background-color: var(--left-grid-bg-color);
|
||||||
|
background-image:
|
||||||
|
linear-gradient(
|
||||||
|
var(--left-decor-line-color),
|
||||||
|
var(--left-decor-line-color)
|
||||||
|
),
|
||||||
|
linear-gradient(
|
||||||
|
var(--left-decor-line-color),
|
||||||
|
var(--left-decor-line-color)
|
||||||
|
),
|
||||||
|
linear-gradient(
|
||||||
|
var(--left-decor-line-color),
|
||||||
|
var(--left-decor-line-color)
|
||||||
|
),
|
||||||
|
linear-gradient(
|
||||||
|
var(--left-decor-line-color),
|
||||||
|
var(--left-decor-line-color)
|
||||||
|
),
|
||||||
|
linear-gradient(
|
||||||
|
var(--left-decor-line-color),
|
||||||
|
var(--left-decor-line-color)
|
||||||
|
),
|
||||||
|
linear-gradient(
|
||||||
|
var(--left-decor-line-color),
|
||||||
|
var(--left-decor-line-color)
|
||||||
|
),
|
||||||
|
linear-gradient(
|
||||||
|
var(--left-decor-line-color),
|
||||||
|
var(--left-decor-line-color)
|
||||||
|
),
|
||||||
|
linear-gradient(
|
||||||
|
var(--left-decor-line-color),
|
||||||
|
var(--left-decor-line-color)
|
||||||
|
);
|
||||||
|
background-size:
|
||||||
|
var(--length) var(--width),
|
||||||
|
var(--width) var(--length),
|
||||||
|
var(--length) var(--width),
|
||||||
|
var(--width) var(--length),
|
||||||
|
var(--length) var(--width),
|
||||||
|
var(--width) var(--length),
|
||||||
|
var(--length) var(--width),
|
||||||
|
var(--width) var(--length);
|
||||||
|
background-position:
|
||||||
|
top left,
|
||||||
|
top left,
|
||||||
|
top right,
|
||||||
|
top right,
|
||||||
|
bottom right,
|
||||||
|
bottom right,
|
||||||
|
bottom left,
|
||||||
|
bottom left;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qrcode {
|
||||||
|
transform: scale(0.9);
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
display: grid;
|
||||||
|
place-items: center;
|
||||||
|
|
||||||
|
& * {
|
||||||
|
font-size: 7.5mm;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
24
src/routes/cv/comps/NameAndImage.svelte
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
<script lang="ts">
|
||||||
|
import NamePlate from "./NamePlate.svelte";
|
||||||
|
import selfie from "$lib/alex/cv-comps/VRNerd.jpg";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="nameAndImageContainer">
|
||||||
|
<NamePlate />
|
||||||
|
<div
|
||||||
|
class="mt-4 w-48 h-48 overflow-hidden shadow-xl rounded-lg flex justify-center items-center"
|
||||||
|
>
|
||||||
|
<img src={selfie} class="selfie-constraints object-cover" alt="Selfie" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.nameAndImageContainer {
|
||||||
|
display: grid;
|
||||||
|
place-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selfie-constraints {
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
21
src/routes/cv/comps/NamePlate.svelte
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
<script lang="ts">
|
||||||
|
import re from "@ts/Redaction/Redactor";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="name-plate-container">
|
||||||
|
<span style="text-align: center;">
|
||||||
|
<b>{$re?.name ?? "BOTAlex"}</b><br />
|
||||||
|
(He/Him)
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.name-plate-container {
|
||||||
|
display: grid;
|
||||||
|
place-items: center;
|
||||||
|
width: 60%;
|
||||||
|
|
||||||
|
/* Bottom border stripe*/
|
||||||
|
border-bottom: 1mm solid var(--left-line-color);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
75
src/routes/cv/comps/OtherContact.svelte
Normal file
|
|
@ -0,0 +1,75 @@
|
||||||
|
<script lang="ts">
|
||||||
|
import re from "@ts/Redaction/Redactor";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
<div>
|
||||||
|
<b style="text-align:left;"> Other </b>
|
||||||
|
</div>
|
||||||
|
<div class="table-display">
|
||||||
|
<div class="table-item">
|
||||||
|
<div>Itch.io</div>
|
||||||
|
<a href={$re?.itch.link ?? "https://www.youtube.com/watch?v=PaPotS8GSpc"}
|
||||||
|
>{$re?.itch.text ?? "The same video"}</a
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<div class="table-item">
|
||||||
|
<div>Github</div>
|
||||||
|
<a href="https://github.com/MagicBOTAlex">@MagicBOTAlex</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.container {
|
||||||
|
display: grid;
|
||||||
|
place-items: center;
|
||||||
|
width: 70%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container > div:first-child {
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
/* Bottom border stripe*/
|
||||||
|
border-bottom: 1mm solid var(--left-line-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-display {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-item {
|
||||||
|
display: flex;
|
||||||
|
justify-items: start;
|
||||||
|
|
||||||
|
width: 100%;
|
||||||
|
border-bottom: 0.25mm solid #000000;
|
||||||
|
|
||||||
|
> a {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
> div,
|
||||||
|
> a {
|
||||||
|
&:first-child {
|
||||||
|
width: 35%;
|
||||||
|
font-size: 4mm;
|
||||||
|
|
||||||
|
display: grid;
|
||||||
|
place-content: center start;
|
||||||
|
|
||||||
|
border-right: rgba(128, 128, 128, 0.4) dashed 0.1mm;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:nth-child(2) {
|
||||||
|
width: 65%;
|
||||||
|
|
||||||
|
font-size: 3.25mm;
|
||||||
|
display: grid;
|
||||||
|
place-content: center;
|
||||||
|
|
||||||
|
padding-left: 1mm;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
37
src/routes/cv/comps/Profile.svelte
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
<div class="short-profile-container">
|
||||||
|
<div class="flex gap-1 items-baseline">
|
||||||
|
<b style="text-align:left;"> About me </b>
|
||||||
|
<div class="opacity-70 text-[0.5rem]">
|
||||||
|
I know the languages listed above in the decor!
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<span>
|
||||||
|
I love learning on my own. I've placed my education at the bottom of my CV.
|
||||||
|
This is because everything I've learnt is on my own, and I refuse to give
|
||||||
|
too much credit to my education. I encurage you to checkout which <span
|
||||||
|
class="font-semibold">Open-source</span
|
||||||
|
>
|
||||||
|
projects I've worked on, on my
|
||||||
|
<a href="https://github.com/MagicBOTAlex"
|
||||||
|
><span class="text-blue-500 underline">github</span></a
|
||||||
|
>.
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
Other than my github, I've listed some projects highlighted below. :)
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.short-profile-container {
|
||||||
|
display: grid;
|
||||||
|
place-items: center;
|
||||||
|
width: 90%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.short-profile-container > div:first-child {
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
/* Bottom border stripe*/
|
||||||
|
border-bottom: 1mm solid black;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
62
src/routes/cv/comps/RepeatedSkills.svelte
Normal file
|
|
@ -0,0 +1,62 @@
|
||||||
|
<script lang="ts">
|
||||||
|
// Width of num chars and height nom of chars
|
||||||
|
export let targetTextWidth: number;
|
||||||
|
export let targetTextHeight: number;
|
||||||
|
|
||||||
|
export let applyRotation: boolean = true;
|
||||||
|
|
||||||
|
export let textOverride: string[] | undefined = undefined;
|
||||||
|
|
||||||
|
// Assign default value if textOverride is undefined
|
||||||
|
let repeatingText : string[] = textOverride ?? [
|
||||||
|
"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 < targetTextWidth) {
|
||||||
|
outString +=
|
||||||
|
repeatingText[
|
||||||
|
getRandomInt(repeatingText.length)
|
||||||
|
] + " ";
|
||||||
|
}
|
||||||
|
|
||||||
|
return outString; // At about target size
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div {...$$restProps}>
|
||||||
|
{#each { length: targetTextHeight } as _, i}
|
||||||
|
<span class="{applyRotation ? "rotate45" : ""} SkillsText">
|
||||||
|
{GrabRandomString()}
|
||||||
|
</span>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.SkillsText {
|
||||||
|
text-align: start;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
white-space: nowrap;
|
||||||
|
|
||||||
|
width: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rotate45 {
|
||||||
|
transform: rotate(-45deg);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
32
src/routes/cv/comps/ShortProfile.svelte
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
<script lang="ts">
|
||||||
|
import re from "@ts/Redaction/Redactor";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="short-profile-container">
|
||||||
|
<div>
|
||||||
|
<b style="text-align:left;"> Short profile </b>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
◾ Full-stack at {$re?.shortProfileHiddenContent[0] ?? "Deprived devs"}
|
||||||
|
<br />
|
||||||
|
◾ "AI and data" at {$re?.shortProfileHiddenContent[1] ?? "some uni"}.
|
||||||
|
<br />
|
||||||
|
◾ Working at {$re?.shortProfileHiddenContent[2] ?? "somewhere"} <br />
|
||||||
|
◾ Volunteer at {$re?.shortProfileHiddenContent[3] ?? "Deprived devs"}.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.short-profile-container {
|
||||||
|
display: grid;
|
||||||
|
place-items: center;
|
||||||
|
width: 70%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.short-profile-container > div:first-child {
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
/* Bottom border stripe*/
|
||||||
|
border-bottom: 1mm solid var(--left-line-color);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
88
src/routes/cv/comps/TableOfProjects.svelte
Normal file
|
|
@ -0,0 +1,88 @@
|
||||||
|
<div class="container">
|
||||||
|
<div class="flex gap-1">
|
||||||
|
<b style="text-align:left;">
|
||||||
|
List of big projects
|
||||||
|
</b>
|
||||||
|
<div class="opacity-70 text-[0.5rem]">
|
||||||
|
It is likely I'm working on something new, as you're reading this.
|
||||||
|
<br/>
|
||||||
|
Contact me if you're curious! :D
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="table-display">
|
||||||
|
<div class="table-item">
|
||||||
|
<div>Computer vision</div>
|
||||||
|
<div>Implimented YoloV1 from scratch. (object detection)</div>
|
||||||
|
</div>
|
||||||
|
<div class="table-item">
|
||||||
|
<div>Arduino</div>
|
||||||
|
<div>Built my own claw machine from scratch.</div>
|
||||||
|
</div>
|
||||||
|
<div class="table-item">
|
||||||
|
<div>App dev</div>
|
||||||
|
<div>Made an Doulingo'ish app for learning chinese.</div>
|
||||||
|
</div>
|
||||||
|
<div class="table-item">
|
||||||
|
<div>Open-source</div>
|
||||||
|
<div>I contribute often to Open-source</div>
|
||||||
|
</div>
|
||||||
|
<div class="table-item">
|
||||||
|
<div>PCB designing</div>
|
||||||
|
<div>I am currently designing my own circuit board</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.container{
|
||||||
|
display: grid;
|
||||||
|
place-items: center;
|
||||||
|
width: 90%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container > div:first-child {
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
/* Bottom border stripe*/
|
||||||
|
border-bottom: 1mm solid black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-display {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-item {
|
||||||
|
display: flex;
|
||||||
|
justify-items: start;
|
||||||
|
|
||||||
|
width: 100%;
|
||||||
|
border-bottom: 0.25mm solid #000000;
|
||||||
|
|
||||||
|
> a {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
> div, > a {
|
||||||
|
color: #000000;
|
||||||
|
|
||||||
|
&:first-child {
|
||||||
|
width: 30%;
|
||||||
|
font-size: 4mm;
|
||||||
|
|
||||||
|
display: grid;
|
||||||
|
place-content: center start;
|
||||||
|
|
||||||
|
border-right: rgba(128, 128, 128, 0.4) dashed 0.1mm;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:nth-child(2) {
|
||||||
|
width: 70%;
|
||||||
|
|
||||||
|
font-size: 3.25mm;
|
||||||
|
display: grid;
|
||||||
|
|
||||||
|
padding-left: 1mm;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -1,53 +0,0 @@
|
||||||
<script>
|
|
||||||
import A4 from "../zhen/notes/physics/sharedComps/A4.svelte";
|
|
||||||
import ToolButton from "./comps/ToolButton.svelte";
|
|
||||||
import { BatteryMedium } from '@lucide/svelte';
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<div class="flex justify-center pt-10">
|
|
||||||
<A4
|
|
||||||
bottomBorder={false}
|
|
||||||
bgColor={"rounded-lg bg-base-300"}
|
|
||||||
class="cozette text-base-content h-full"
|
|
||||||
>
|
|
||||||
<div class="p-4 flex flex-col h-full">
|
|
||||||
<h1 class="text-5xl font-bold">Tools (NOT FINISHED. come back in the future.)</h1>
|
|
||||||
<span class="w-full text-xl"
|
|
||||||
>These are the tools collected from different places of the
|
|
||||||
internet</span
|
|
||||||
>
|
|
||||||
|
|
||||||
<!-- Spacing -->
|
|
||||||
<div class="pt-14"></div>
|
|
||||||
|
|
||||||
<div class="p-4 bg-base-200 rounded-lg">
|
|
||||||
<h2 class="text-2xl font-bolc">MPUs/SoCs</h2>
|
|
||||||
<span>Whatever acronym you want lol</span>
|
|
||||||
<div class="grid grid-cols-3 gap-4">
|
|
||||||
<ToolButton
|
|
||||||
title="Sleeping battery life"
|
|
||||||
desc="Calculates the battery life depending on sleep and non-sleep power usage."
|
|
||||||
btnText="To calculator"
|
|
||||||
toolIcon={BatteryMedium}
|
|
||||||
/>
|
|
||||||
<!-- <ToolButton
|
|
||||||
title="Sleeping battery life"
|
|
||||||
desc="Calculates the battery life depending on sleep and non-sleep power usage."
|
|
||||||
btnText="To calculator"
|
|
||||||
toolIcon={BatteryMedium}
|
|
||||||
/>
|
|
||||||
<ToolButton
|
|
||||||
title="Sleeping battery life"
|
|
||||||
desc="Calculates the battery life depending on sleep and non-sleep power usage."
|
|
||||||
btnText="To calculator"
|
|
||||||
toolIcon={BatteryMedium}
|
|
||||||
/> -->
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="mt-auto align-text-bottom">
|
|
||||||
I if you have tool suggestions, then either create an issue, create a pull request, or send an email. I probably wont add it though, since this is free work lol.
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</A4>
|
|
||||||
</div>
|
|
||||||
|
|
@ -1,76 +0,0 @@
|
||||||
<script>
|
|
||||||
import svelteLogo from "$lib/svelteLogos/svelte-logo-cutout.svg"
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<div class="container">
|
|
||||||
<div class="flex justify-center">
|
|
||||||
<div class="corner-border-container p-1 m-1">
|
|
||||||
<div class="flex">
|
|
||||||
This CV was made using html, css and <a class="grid place-content-center" href="https://kit.svelte.dev/"><img src={svelteLogo} class="w-2 h-2" alt="SvelteKit logo"/></a>
|
|
||||||
</div>
|
|
||||||
Sources:
|
|
||||||
<a href="https://gitea.deprived.dev/Sveskejuice/deprived-main-website/src/branch/dev/src/routes/zhen/cv/rev2/+page.svelte">CV source code</a>
|
|
||||||
and
|
|
||||||
<a href="/zhen/cv/rev2?hideOnPrint=1">My Website</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<style lang="scss">
|
|
||||||
.corner-border-container {
|
|
||||||
--length: 5px;
|
|
||||||
--width: 1px;
|
|
||||||
background-color: var(--left-grid-bg-color);
|
|
||||||
background-image:
|
|
||||||
linear-gradient(var(--left-decor-line-color), var(--left-decor-line-color)),
|
|
||||||
linear-gradient(var(--left-decor-line-color), var(--left-decor-line-color)),
|
|
||||||
linear-gradient(var(--left-decor-line-color), var(--left-decor-line-color)),
|
|
||||||
linear-gradient(var(--left-decor-line-color), var(--left-decor-line-color)),
|
|
||||||
linear-gradient(var(--left-decor-line-color), var(--left-decor-line-color)),
|
|
||||||
linear-gradient(var(--left-decor-line-color), var(--left-decor-line-color)),
|
|
||||||
linear-gradient(var(--left-decor-line-color), var(--left-decor-line-color)),
|
|
||||||
linear-gradient(var(--left-decor-line-color), var(--left-decor-line-color));
|
|
||||||
background-size:
|
|
||||||
var(--length) var(--width),
|
|
||||||
var(--width) var(--length),
|
|
||||||
var(--length) var(--width),
|
|
||||||
var(--width) var(--length),
|
|
||||||
var(--length) var(--width),
|
|
||||||
var(--width) var(--length),
|
|
||||||
var(--length) var(--width),
|
|
||||||
var(--width) var(--length);
|
|
||||||
background-position:
|
|
||||||
top left,
|
|
||||||
top left,
|
|
||||||
top right,
|
|
||||||
top right,
|
|
||||||
bottom right,
|
|
||||||
bottom right,
|
|
||||||
bottom left,
|
|
||||||
bottom left;
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
}
|
|
||||||
|
|
||||||
.container {
|
|
||||||
z-index: 1;
|
|
||||||
|
|
||||||
font-size: 0.5rem;
|
|
||||||
|
|
||||||
//white-space: nowrap;
|
|
||||||
|
|
||||||
color: #777777;
|
|
||||||
|
|
||||||
* a {
|
|
||||||
color: #3d6ddc;
|
|
||||||
padding-left: 1mm;
|
|
||||||
padding-right: 1mm;
|
|
||||||
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
div:nth-child(2){
|
|
||||||
padding-bottom: 2mm;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
54
src/ts/EnvHandler.ts
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
// used to deal with .env things, but with this instead because nix
|
||||||
|
// Drafted manually, then fed through chatgpt
|
||||||
|
// Idk what is going on anymore, but it isn't really an important aspect of the code, since this is just for changing from productiong to dev environment
|
||||||
|
|
||||||
|
type Env = { [K in keyof typeof env]: (typeof env)[K] } & Record<
|
||||||
|
string,
|
||||||
|
unknown
|
||||||
|
>;
|
||||||
|
|
||||||
|
export let env = {
|
||||||
|
POCKETBASE_URL: "https://pocket.deprived.dev",
|
||||||
|
} as const;
|
||||||
|
export default env;
|
||||||
|
|
||||||
|
let initialized = false;
|
||||||
|
|
||||||
|
// Load overrides from localstorage or url params
|
||||||
|
const isOverride = (k: string) => k.startsWith("-E");
|
||||||
|
const norm = (k: string) => k.slice(2); // strip "-E"
|
||||||
|
|
||||||
|
function apply(from: Record<string, string>, tag: string) {
|
||||||
|
for (const [rawK, rawV] of Object.entries(from)) {
|
||||||
|
env[rawK] = rawV;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function initEnv(): void {
|
||||||
|
if (initialized) return;
|
||||||
|
initialized = true;
|
||||||
|
window.env = env!;
|
||||||
|
|
||||||
|
// localStorage overrides: only keys starting with "-E"
|
||||||
|
const ls: Record<string, string> = {};
|
||||||
|
for (const [k, v] of Object.entries(env)) {
|
||||||
|
const val = localStorage.getItem(k);
|
||||||
|
if (val != null) ls[k] = val;
|
||||||
|
}
|
||||||
|
apply(ls, "localStorage");
|
||||||
|
|
||||||
|
// URL param overrides: ?-EKEY=value
|
||||||
|
const params = new URLSearchParams(location.search);
|
||||||
|
const url: Record<string, string> = {};
|
||||||
|
for (const [k, v] of params.entries()) url[k] = v;
|
||||||
|
apply(url, "url");
|
||||||
|
|
||||||
|
// (optional) persist URL overrides in localStorage with the "-E" prefix
|
||||||
|
for (const [k, v] of Object.entries(url)) {
|
||||||
|
if (isOverride(k)) localStorage.setItem(norm(k), String(v));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Object.assign(env as any, current);
|
||||||
|
// for (const [k, v] of Object.entries(env))
|
||||||
|
// console.log(`[env final] ${k}=${String(v)}`);
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { PUBLIC_URL_BASE } from "$env/static/public";
|
const PUBLIC_URL_BASE = "https://deprived.dev/";
|
||||||
|
|
||||||
// Absolute vibe coded. Idk if it works or not. Not important anyways
|
// Absolute vibe coded. Idk if it works or not. Not important anyways
|
||||||
// Assumes PUBLIC_URL_BASE is something like "https://deprived.dev"
|
// Assumes PUBLIC_URL_BASE is something like "https://deprived.dev"
|
||||||
|
|
|
||||||
57
src/ts/Redaction/Profile.ts
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
// npm i zod
|
||||||
|
import { z } from "zod";
|
||||||
|
|
||||||
|
const Link = z.object({
|
||||||
|
imageId: z.string().min(1).optional(),
|
||||||
|
text: z.string().min(1),
|
||||||
|
link: z.string().url(),
|
||||||
|
});
|
||||||
|
|
||||||
|
const Experience = z.object({
|
||||||
|
imageId: z.string().min(1),
|
||||||
|
name: z.string().min(1),
|
||||||
|
date: z.string().min(1),
|
||||||
|
});
|
||||||
|
|
||||||
|
const EducationLoose = z.object({
|
||||||
|
imageId: z.string().min(1).optional(),
|
||||||
|
name: z.string().min(1).optional(),
|
||||||
|
});
|
||||||
|
|
||||||
|
const CV = z.object({
|
||||||
|
sourceLink: z.string().url().min(1),
|
||||||
|
});
|
||||||
|
|
||||||
|
const ProfileSchema = z.object({
|
||||||
|
name: z.string().min(1),
|
||||||
|
nick: z.string().min(1),
|
||||||
|
shortProfileHiddenContent: z.array(z.string()),
|
||||||
|
email: z.string().email(),
|
||||||
|
phone: z.string().min(1),
|
||||||
|
linkedIn: Link,
|
||||||
|
itch: Link,
|
||||||
|
cv: CV,
|
||||||
|
experience: z.array(Experience),
|
||||||
|
education: z
|
||||||
|
.array(EducationLoose)
|
||||||
|
.transform((arr) =>
|
||||||
|
arr.filter(
|
||||||
|
(e): e is { imageId: string; name: string } => !!e.imageId && !!e.name,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
});
|
||||||
|
|
||||||
|
export type LinkT = z.infer<typeof Link>;
|
||||||
|
export type ExperienceT = z.infer<typeof Experience>;
|
||||||
|
export type EducationT = { imageId: string; name: string };
|
||||||
|
export type Profile = Omit<z.infer<typeof ProfileSchema>, "education"> & {
|
||||||
|
education: EducationT[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export function parseProfile(json: unknown): Profile {
|
||||||
|
return ProfileSchema.parse(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- usage ---
|
||||||
|
// const raw = JSON.parse(yourJsonString);
|
||||||
|
// const profile = parseProfile(raw);
|
||||||
71
src/ts/Redaction/Redactor.ts
Normal file
|
|
@ -0,0 +1,71 @@
|
||||||
|
// redactor.ts
|
||||||
|
import { parseProfile, type Profile } from "./Profile";
|
||||||
|
import env, { initEnv } from "@ts/EnvHandler";
|
||||||
|
import type { Readable, Subscriber, Unsubscriber } from "svelte/store";
|
||||||
|
|
||||||
|
class Redactor implements Readable<Profile | undefined> {
|
||||||
|
public unredactedProfile: Profile | undefined = undefined;
|
||||||
|
public wrongKey: boolean | undefined = undefined;
|
||||||
|
|
||||||
|
private subs = new Set<Subscriber<Profile | undefined>>();
|
||||||
|
subscribe(run: Subscriber<Profile | undefined>): Unsubscriber {
|
||||||
|
this.subs.add(run);
|
||||||
|
run(this.unredactedProfile);
|
||||||
|
return () => this.subs.delete(run);
|
||||||
|
}
|
||||||
|
private notify() {
|
||||||
|
this.subs.forEach((s) => s(this.unredactedProfile));
|
||||||
|
}
|
||||||
|
|
||||||
|
async TryGetUnredacter(): Promise<Profile | string> {
|
||||||
|
if (this.unredactedProfile) return this.unredactedProfile;
|
||||||
|
|
||||||
|
const storedKey = localStorage.getItem("key");
|
||||||
|
if (!storedKey) throw new Error("Missing key");
|
||||||
|
|
||||||
|
const hashResJson = await (
|
||||||
|
await fetch("https://api.deprived.dev/unredact", {
|
||||||
|
method: "POST",
|
||||||
|
headers: { "Content-Type": "application/json" },
|
||||||
|
body: JSON.stringify({ key: storedKey }),
|
||||||
|
})
|
||||||
|
).json();
|
||||||
|
|
||||||
|
const unredactHash = hashResJson.response;
|
||||||
|
initEnv();
|
||||||
|
if (unredactHash == "nawh") {
|
||||||
|
console.log("Wrong key, keeping info about alex secret");
|
||||||
|
return "Wrong key";
|
||||||
|
}
|
||||||
|
|
||||||
|
const url = `${env.POCKETBASE_URL}/api/collections/redacted_content/records/${unredactHash}`;
|
||||||
|
|
||||||
|
const res = await fetch(url, {
|
||||||
|
method: "GET",
|
||||||
|
headers: { Accept: "application/json" },
|
||||||
|
});
|
||||||
|
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
||||||
|
|
||||||
|
let data = await res.json();
|
||||||
|
const replaced = JSON.parse(
|
||||||
|
JSON.stringify(data).replaceAll("[PB]", env.POCKETBASE_URL),
|
||||||
|
);
|
||||||
|
this.unredactedProfile = parseProfile(replaced.json);
|
||||||
|
this.notify(); // <-- tell Svelte to update
|
||||||
|
return "success";
|
||||||
|
}
|
||||||
|
|
||||||
|
t(path: string, fallback: string): string {
|
||||||
|
try {
|
||||||
|
const src = this.unredactedProfile as Record<string, unknown> | undefined;
|
||||||
|
if (!src) return fallback;
|
||||||
|
const v = path.split(".").reduce<any>((o, k) => (o as any)?.[k], src);
|
||||||
|
return (v ?? "") !== "" ? String(v) : fallback;
|
||||||
|
} catch {
|
||||||
|
return fallback;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const re = new Redactor();
|
||||||
|
export default re;
|
||||||
|
|
@ -2,8 +2,8 @@
|
||||||
// It is meant to be called from stores.ts
|
// It is meant to be called from stores.ts
|
||||||
|
|
||||||
import PocketBase from "pocketbase";
|
import PocketBase from "pocketbase";
|
||||||
import { ShopItem } from "./classes/ShopItem";
|
import ShopItem from "./classes/ShopItem";
|
||||||
import { PUBLIC_POCKET_URL, PUBLIC_URL_BASE } from "$env/static/public";
|
const PUBLIC_POCKET_URL = "https://pocket.deprived.dev/";
|
||||||
|
|
||||||
export let pb = new PocketBase(PUBLIC_POCKET_URL);
|
export let pb = new PocketBase(PUBLIC_POCKET_URL);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
import { PUBLIC_POCKET_URL, PUBLIC_URL_BASE } from "$env/static/public";
|
|
||||||
import { ParseAssetUrl } from "@src/ts/Helper";
|
import { ParseAssetUrl } from "@src/ts/Helper";
|
||||||
|
|
||||||
export class ShopItem {
|
export class ShopItem {
|
||||||
|
|
@ -48,3 +47,5 @@ export class ShopItem {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default ShopItem;
|
||||||
|
|
|
||||||