Revert "custom shiki highlighter from dominikg"

This reverts commit 9b976986d7.
This commit is contained in:
matthieu42morin 2024-04-28 01:42:44 +02:00
parent 9b976986d7
commit dc948269b9
29 changed files with 81 additions and 818 deletions

1
src/app.d.ts vendored
View File

@ -1,7 +1,6 @@
// See https://kit.svelte.dev/docs/types#app // See https://kit.svelte.dev/docs/types#app
// for information about these interfaces // for information about these interfaces
// and what to do when importing types // and what to do when importing types
declare namespace App { declare namespace App {
// interface Locals {} // interface Locals {}
// interface PageData {} // interface PageData {}

View File

@ -24,12 +24,6 @@ body {
src: url('/fonts/Quicksand.ttf'); src: url('/fonts/Quicksand.ttf');
font-display: swap; font-display: swap;
} }
.prose {
font-family: 'Cooper Hewitt', sans-serif;
letter-spacing: 0.25px;
}
/* /*
@font-face { @font-face {
font-family: 'Magilio'; font-family: 'Magilio';

View File

@ -1,12 +0,0 @@
tldr:
I started by containerizing my SvelteKit and Strapi apps, then Pushed these to Docker Hub and AWS ECR,
leveraging 1 free private image on docker hub and free-tier 500mb limit on AWS ECR, thereby minimizing costs and exploring each option.
1. Conteinerization
a. Sveltekit
Keeping in mind that dev, build, test and lint, etc. scripts are handled by turborepo, we use these when containerizing.
Step 1.
b. Strapi

View File

@ -1,7 +0,0 @@
choosing a package manager
I tried to abstain from the community battles between pms and looked at the performance of the top 3 used - npm, yarn and pnpm. https://pnpm.io/benchmarks
I've got experience with each and would like to use pnpm as it is the much faster than NPM,
however Strapi doesn't officialy support it so I ended up choosing yarn as in most cases it is a bit faster than npm, has some better handling with monorepos and I personally like it.
I used Turborepo with npm and there were some problems with setting dependencies in workspaces vs the root of monorepo and private packages, which required workarounds.
In terms of CI performance can have significant consequences.

View File

@ -1,15 +0,0 @@
AWS set up
A thing I learned using linux is user management, specifically don't do everything as root :D.
When using AWS first I didn't care about IAM roles, but I think I learned the same lesson...
Anyways I used this process, when configuring accounts:
When starting login as root user and access IAM dashboard,
Set up Multi-factor Auth as root user (prefferably with Yubikey or some OTP in a secure device)
Later on, like in linux, the root account access can be minimized for a better decentralized privilege system, even when being the only admin.
Go to services then IAM Identity center
Select identity source -> In my case stick with the default Identity Center directory, bigger organizations or ones using other sources can connect to external ones.
In Multi-account permissions select permission sets and create a permission set.
Then go to AWS accounts, select the account you wish and assign the permission set to them.

View File

@ -1,62 +0,0 @@
Namecheap
Saw mattmor.in and just bought it, no questions asked.
I immediately created a cloudflare account, because of their great certificate management, security checks, analytics and mostly DNS.
Setting up AWS EC2 & RDS instances
EC2 setup
I've got a great opportunity to set up a "free-tier" instance, of course the limitations are quite interesting - 750 hrs/m and some compute limiting factors.
Let's use this opportunity, it is a better deal than GCP with 300$/3mos and my experience with GCP while dealing with Auth API was pretty bad.
Made SSH keys
got an Elastic IP and connected it with my EC2 instance to be accessible publicly on a stable IP.
added DNS records to cloudflare
Log in via SSH, update, upgrade everything, restart.
Then I configured fail2ban with some custom responses and enabled it, I also configured the seemingly redundant ufw and allowed ssh, https
And with that I am ready to roll onto installing necessary software like nginx, jenkins, docker for now.
RDS setup
I've already configured Strapi for my backend, I selected PostgreSQL, because while theoretically the default SQLite db would be sufficient and very easy to manage.
I know it's scalability is limited and is not suitable for multiple user access, which I might need in other projects with the same tech stack.
The main reason for choosing PostgreSQL is I can showcase it and learn with it on a project using AWS.
I've worked mainly with MariaDB before, and used PostgreSQL only on some ancient Wordpress projects back in the day.
As I already set up a free-tier EC2 instance, I can also setup AWS RDS with Aurora(PostgreSQL compatible) or PostgreSQL also on free-tier, which is awesome!
Let's choose PostgreSQL, because that's simpler and more than sufficient.
The Free Tier is limited to the same time frame for RDS...
If I really wanted to make this completely free I could use AWS Lambda, which is also free up to 1 million requests/month :D, to turn off both the EC2 and RDS instances at night. Gotta think when do recruiters go to sleep...
Now seriously, to actualy set this up:
Select:
burstable class db.t4g.micro
General Purpose SSD (gp3) 20GiB
I disabled autoscaling as it's not possible I would use more than this in this use-case.
Strapi recommends PostgreSQL v14.0 at the time of writing
AWS offers 14.5 above, let's choose 14.9 R1, should be backwards compatible.
Template -> Free tier
Security:
As my OpSec dictates I choose passwords with high entropy so you can't hack me.
Backup & Maintenance:
Setup Backup and Amazon auto-maintenance windows, I am not a maniac to not backup.
Connectivity:
I will not connect this to my EC2 instance, because I will be testing this on localhost.
I need public access and in this case I do not think accessing by a private network is necessary.
I will make a new VPC security group, then we can access it via an internet gateway.
https://docs.aws.amazon.com/images/AmazonRDS/latest/UserGuide/images/GS-VPC-network.png

View File

@ -1,26 +1,18 @@
--- ---
title: First post title: First post
type: blog
excerpt: First post excerpt: First post
date: 2021-01-01
tags: tags:
- Blog - first
- Linux - post
- Declarative published: true
image: Feature.jpg image: Feature.jpg
postTitle: 'Best Medium Format Camera for Starting Out'
focusKeyphrase: 'best medium format camera'
datePublished: '2023-04-07T16:04:42.000+0100'
lastUpdated: '2023-04-14T10:17:52.000+0100'
seoMetaDescription: "Let's take a look."
featuredImage: ''
featuredImageAlt: 'Our own pcb'
publicImageId: ''
--- ---
## Svelte ## Svelte
Media inside the **Svelte** folder is served from the `static` folder. Media inside the **Svelte** folder is served from the `static` folder.
```python showLines ```python
input_text = ''' "yahooapis.com", input_text = ''' "yahooapis.com",
"hotmail.com", "hotmail.com",
@ -38,112 +30,3 @@ output_text = '\n'.join(formatted_lines)
print(output_text) print(output_text)
``` ```
## Turborepo [see 1st source]
I will use turborepo as I have experience with it from previous projects, I prefer the centralized, more orderly handling of repositories.
Because our CMS and webapp are workspaces that need to be configured differently, we need to extend the root config of Turborepo to each app individually by creating a turbo.json in each workspace.
For Strapi this will be:
$root/apps/cms/turbo.json
``` json
{
"extends": ["//"],
"pipeline": {
"build": {
// custom configuration for the build task in this workspace
},
// new tasks only available in this workspace
"special-task": {},
}
}
```
For Sveltekit Webapp:
$root/apps/web/turbo.json
``` json
{
"extends": ["//"],
"pipeline": {
"build": {
"outputs": [".svelte-kit/**"]
}
}
}
```
Key notes about this setup:
Docker:
Base Layer: Installs container dependencies and Turborepo globally.
Pruned Layer: Copies project files and runs turbo prune to exclude unnecessary dependencies.
Installer Layer: Copies pruned workspace and runs yarn to install dependencies.
Runner Layer: Starts the app.
## Docker
Alpine is more lightweight than Ubuntu, I will stick to the inspiration blog post [see 2nd source], which has a similar setup.
The blog post creates intermediate images 'base', 'pruned' etc. that can be used in subsequent stages.
To push images to docker hub:
```docker push mando42/portfolio:tagname```
Learned
Used sources:
1. https://turbo.build/repo/docs
2. https://dev.to/moofoo/creating-a-development-dockerfile-and-docker-composeyml-for-yarn-122-monorepos-using-turborepo-896
## Docker
Alpine is more lightweight than Ubuntu, I will stick to the inspiration blog post [see 2nd source], which has a similar setup.
The blog post creates intermediate images 'base', 'pruned' etc. that can be used in subsequent stages.
To push images to docker hub:
```docker push mando42/portfolio:tagname```
## Docker
Alpine is more lightweight than Ubuntu, I will stick to the inspiration blog post [see 2nd source], which has a similar setup.
The blog post creates intermediate images 'base', 'pruned' etc. that can be used in subsequent stages.
To push images to docker hub:
```docker push mando42/portfolio:tagname```
## Docker
Alpine is more lightweight than Ubuntu, I will stick to the inspiration blog post [see 2nd source], which has a similar setup.
The blog post creates intermediate images 'base', 'pruned' etc. that can be used in subsequent stages.
To push images to docker hub:
```docker push mando42/portfolio:tagname```
## Docker
Alpine is more lightweight than Ubuntu, I will stick to the inspiration blog post [see 2nd source], which has a similar setup.
The blog post creates intermediate images 'base', 'pruned' etc. that can be used in subsequent stages.
To push images to docker hub:
```docker push mando42/portfolio:tagname```
## Docker
Alpine is more lightweight than Ubuntu, I will stick to the inspiration blog post [see 2nd source], which has a similar setup.
The blog post creates intermediate images 'base', 'pruned' etc. that can be used in subsequent stages.
To push images to docker hub:
```docker push mando42/portfolio:tagname```
## Docker
Alpine is more lightweight than Ubuntu, I will stick to the inspiration blog post [see 2nd source], which has a similar setup.
The blog post creates intermediate images 'base', 'pruned' etc. that can be used in subsequent stages.
To push images to docker hub:
```docker push mando42/portfolio:tagname```

View File

@ -1,18 +0,0 @@
install Grafana, Prometheus, ELK Stack, and Jenkins on a single server and use them to monitor other EC2 instances or cloud resources. There are trade-offs:
Pros:
Simplified Management: All tools in one place.
Lower Costs: Fewer servers to maintain.
Cons:
Resource Contention: These tools can be resource-intensive.
Single Point of Failure: If the server goes down, all tools are affected.
Security Risks: Multiple services on one server can increase the attack surface.
Recommendations:
Use containerization (Docker) for easier management and isolation.
Set up a robust backup and recovery strategy.
Ensure adequate resource allocation and scaling capabilities.

View File

@ -1,19 +1,12 @@
--- ---
title: First post title: w post
type: blog excerpt: w post
excerpt: First post date: 2021-01-01
tags: tags:
- NixOS - first
- Linux - post
- Declarative published: true
image: Feature.jpg image: Feature.jpg
postTitle: 'Best Medium Format Camera for Starting Out'
focusKeyphrase: 'best medium format camera'
datePublished: '2022-04-07T16:04:42.000+0100'
lastUpdated: '2022-04-14T10:17:52.000+0100'
seoMetaDescription: "Let's take a look."
featuredImage: ''
featuredImageAlt: 'Our own pcb'
publicImageId: ''
--- ---
## Svelte ## Svelte

View File

@ -1,76 +0,0 @@
The goal of this project is to showcase my skillset both as a portfolio site and showcase how I used devops and web development practices to build it.
The tech stack and feature set is meant to:
legitimize the goal of the portfolio site, which is mentioned above
Use modern DevOps and web development practices that I know of so I can build it as fast as possible.
minimize costs and be potentially scalable and feature-upgradeable.
be secure and be build using my evolving OpSec and limited cybersecurity knowledge.
show proficiency in using new tools.
As such the current cloud stack is:
1. AWS EC2 t3.micro
For: Jenkins
Why: CI/CD pipeline, free tier, 1GB RAM sufficient for Jenkins.
2. AWS EC2 t3.micro
For: docker-compose SvelteKit app
Why: Frontend, free tier, 1GB RAM sufficient for SvelteKit.
3. Amazon ECS Anywhere
For: docker-compose Strapi
Why: Container orchestration, 2200 free hours, scalable.
4. AWS Lambda
For: Automated tasks
Why: 1 million free requests, event-driven architecture.
5. Amazon RDS
For: Database
Why: 750 free hours, managed service, 20GB storage.
6. Amazon S3
For: File storage, backups
Why: 5GB free storage, durable.
7. Amazon CloudWatch
For: Monitoring
Why: 10 free custom metrics and alarms.
8. AWS Secrets Manager
For: Secrets
Why: Secure, but consider alternatives due to cost.
9. Amazon API Gateway
For: APIs
Why: 1 million free API calls, secure.
10. Terraform and Ansible
For: IaC and Configuration
Why: Version control, automation.
11. Documentation
For: READMEs
Why: Clarity, onboarding, and best practices.
12. GitHub and AWS ECR
For: Code and container repositories
Why: Version control, Docker Hub limitations.
Cost Analysis
EC2 t3.micro: Free tier
ECS Anywhere: Free tier (2200 hours)
Lambda: Free tier (1 million requests)
RDS: Free tier (750 hours)
S3: Free tier (5GB)
CloudWatch: Free tier (10 metrics)
Secrets Manager: $0.40/secret, consider alternatives
API Gateway: Free tier (1 million calls)

View File

@ -1,20 +1,13 @@
--- ---
title: First post title: Second post
type: blog excerpt: Second post
excerpt: First post date: 2023-01-01
tags: tags:
- NixOS - first
- Linux - post
- Declarative published: true
image: Feature.jpg image: Feature.jpg
postTitle: 'Best Medium Format Camera for Starting Out'
focusKeyphrase: 'best medium format camera'
datePublished: '2024-04-07T16:04:42.000+0100'
lastUpdated: '2021-04-14T10:17:52.000+0100'
seoMetaDescription: "Let's take a look."
featuredImage: ''
featuredImageAlt: 'Our own pcb'
publicImageId: ''
--- ---
@ -30,4 +23,5 @@ Media inside the **Svelte** folder is server from the `static` folder.
I am ditching the societal value of having a contributions table on my profile, you should view it on git.mattmor.in I am ditching the societal value of having a contributions table on my profile, you should view it on git.mattmor.in
--- If my contributions in 3d do not work, Github made breaking changes to their frontend and I can't scrape it anymore. --- If my contributions in 3d do not work, Github made breaking changes to their frontend and I can't scrape it anymore.

View File

@ -1,74 +0,0 @@
Hard skills in SW:
HTML, CSS, JS, TS, Svelte, Sveltekit, Vite,
WebDev (meta)frameworks: Svelte (and sveltekit), a theoretical knowledge of reactjs (and next.js) and vue (and nuxt)
WebDev langs: HTML, CSS, tailwindcss, postcss (basics), JS, TS (basics), multiple ui libraries and billions of packages :D
WebDev linting: eslint
WebDev testing: Playwright
Languages: JS, Python, Micropython, C and C++ (both basics with microcontrollers), I really want to code in OstraJava and Brainf*ck
OS:
Linux [Ubuntu, Debian (Rpi OS, Kali - basics), QubesOS, Arch (Manjaro)], WSL,
Windows :D, advanced as a power user of XP,Vista,7,8,10,11 in my life, caused deep trauma. Haven't used win servers and don't plan to.
Terminal:
Process Monitoring
Performance Monitoring
Networking Tools
Text Manipulation
Scripting:
Bash
Power Shell (for user tasks)
Editors:
Nano, Emacs, VS Code, Notepad :D and Jupyter notebook
Version control: Git
VCS Hosting: Github, Gitlab
CI/CD:
Jenkins In progress
Gitlab CI In progress
Infrastructure Provisioning:
Terraform: In progress
Cloud Providers:
AWS - Preffered
DigitalOcean
Google Cloud (I did auth, api, company set up and some bots with spreadsheet)
CDN: Cloudinary
Networking, Security and Protocols:
FTP / SFTP
SSL / TLS
HTTP / HTTPS
DNS
SSH (putty and linux)
Serverless: AWS Lambda (0), Cloudflare, Vercel
Monorepo (with pipelines): all yarn, npm, pnpm with turborepo
Containerization: docker (dockerfile, docker-compose, ran many apps with it), DockerHub, AWS RCD
Container Orchestration: Docker swarm(basics)
K8s/K3s: In progress...
Orchestration: Terraform (0)
GitOps: In progress ArgoCD
Application monitoring: New Relic, Prometheus, Grafana, Elk stack
Logs Management:

View File

@ -1,56 +0,0 @@
## Turborepo [see 1st source]
I will use turborepo as I have experience with it from previous projects, I prefer the centralized, more orderly handling of repositories.
Because our CMS and webapp are workspaces that need to be configured differently, we need to extend the root config of Turborepo to each app individually by creating a turbo.json in each workspace.
For Strapi this will be:
$root/apps/cms/turbo.json
```
{
"extends": ["//"],
"pipeline": {
"build": {
// custom configuration for the build task in this workspace
},
// new tasks only available in this workspace
"special-task": {},
}
}
```
For Sveltekit Webapp:
$root/apps/web/turbo.json
```
{
"extends": ["//"],
"pipeline": {
"build": {
"outputs": [".svelte-kit/**"]
}
}
}
```
Key notes about this setup:
Docker:
Base Layer: Installs container dependencies and Turborepo globally.
Pruned Layer: Copies project files and runs turbo prune to exclude unnecessary dependencies.
Installer Layer: Copies pruned workspace and runs yarn to install dependencies.
Runner Layer: Starts the app.
## Docker
Alpine is more lightweight than Ubuntu, I will stick to the inspiration blog post [see 2nd source], which has a similar setup.
The blog post creates intermediate images 'base', 'pruned' etc. that can be used in subsequent stages.
To push images to docker hub:
```docker push mando42/portfolio:tagname```
Learned
Used sources:
1. https://turbo.build/repo/docs
2. https://dev.to/moofoo/creating-a-development-dockerfile-and-docker-composeyml-for-yarn-122-monorepos-using-turborepo-896

View File

@ -1,40 +0,0 @@
.code-highlight {
position: relative;
font-family: 'Fira Mono', monospace;
overflow-x: hidden;
overflow-y: auto;
max-height: 60vh;
margin: 1rem auto;
box-shadow: var(--shadow);
border-radius: 0.5rem;
font-size: 1.5rem;
max-width: 90%;
}
.code-highlight > .code-language {
position: absolute;
top: 0;
right: 0;
border-top-right-radius: 0.5rem;
border-bottom-left-radius: 0.5rem;
background: rgba(127, 127, 127, 0.3);
padding: 0 0.25rem;
}
.code-highlight > code {
display: inline-block;
padding: 1rem;
}
.code-highlight > code.numbered {
margin-left: 2rem;
padding-left: 0.5rem;
border-left: 1px solid rgba(127, 127, 127, 0.5);
counter-reset: line;
}
.code-highlight > code > .line-of-code {
white-space: pre-wrap;
display: inline-block;
min-height: 1em;
}

View File

@ -1,120 +0,0 @@
:root {
--light: #f1f4f8;
--dark: #2c2d2f;
--primary: #ff3e00;
--fg: var(--light);
--bg: var(--dark);
--color-scrollbar: rgba(0, 0, 0, 0.3);
--shadow: 0 0.5rem 0.5rem 0 rgba(0, 0, 0, 0.2), 0 0.25rem 1rem 0 rgba(0, 0, 0, 0.2),
0 0.5rem 0.25rem -0.25rem rgba(0, 0, 0, 0.2);
}
@media only screen and (prefers-color-scheme: dark) {
:root {
--fg: var(--light);
--bg: var(--dark);
--color-scrollbar: rgba(255, 255, 255, 0.3);
}
body.light {
--fg: var(--dark);
--bg: var(--light);
--color-scrollbar: rgba(0, 0, 0, 0.3);
}
}
@media only screen and (prefers-color-scheme: light) {
:root {
--fg: var(--dark);
--bg: var(--light);
--color-scrollbar: rgba(0, 0, 0, 0.3);
}
body.dark {
--fg: var(--light);
--bg: var(--dark);
--color-scrollbar: rgba(255, 255, 255, 0.3);
}
}
body {
color: var(--fg);
background-color: var(--bg);
font-family: 'Fira Mono', monospace;
font-size: 1.5rem;
height: 1080px;
}
h1,
h2,
h3,
h4,
h5,
h6 {
font-family: 'Fira Mono', monospace;
}
p,
.prose {
font-family: 'Cooper Hewitt', sans-serif;
letter-spacing: 0.25px;
}
.container {
margin: 0 auto;
padding: 0;
width: calc(100vw - 2rem);
max-width: 1920px;
}
a {
color: currentColor;
transition: color 200ms ease-in-out;
}
* {
scrollbar-width: thin;
scrollbar-color: var(--color-scrollbar) transparent;
-webkit-overflow-scrolling: touch;
}
*::-webkit-scrollbar {
width: 0.5rem;
}
*::-webkit-scrollbar-track {
background: transparent;
}
*::-webkit-scrollbar-thumb {
background-color: var(--color-scrollbar);
border-radius: 0.25rem;
}
html {
height: 100%;
}
body {
height: 100%;
}
.shadow {
box-shadow: var(--shadow);
}
h1,
h2,
h3,
h4 {
margin-top: 0;
}
h1 {
margin-bottom: 0.5rem;
}
h2 {
margin-bottom: 0.25rem;
}
h3 {
margin-bottom: 0.1rem;
}

View File

@ -1,12 +0,0 @@
// src/lib/cloudinary.ts
import { v2 as cloudinary } from 'cloudinary';
import { PUBLIC_CLOUDINARY_NAME } from '$env/static/public';
import { CLOUDINARY_API_KEY, CLOUDINARY_API_SECRET } from '$env/static/private';
cloudinary.config({
cloud_name: PUBLIC_CLOUDINARY_NAME,
api_key: CLOUDINARY_API_KEY,
api_secret: CLOUDINARY_API_SECRET
});
export default cloudinary;

View File

@ -1,26 +1,26 @@
<section class="grid grid-cols-1 md:grid-cols-3 gap-4 lg:gap-8" data-svelte-h="svelte-1u9sn7t"> <section class="grid grid-cols-1 md:grid-cols-3 gap-4 lg:gap-8" data-svelte-h="svelte-1u9sn7t">
<div class="card variant-ringed-hollow p-4 md:p-8 space-y-4"> <div class="card variant-ringed-hollow p-4 md:p-8 space-y-4">
<i class="fa-solid fa-screwdriver-wrench text-4xl text-primary-500" /> <i class="fa-solid fa-screwdriver-wrench text-4xl text-primary-500" />
<h3 class="h3">Development</h3> <h3 class="h3">Development</h3>
<p class="opacity-75"> <p class="opacity-75">
I hone my problem solving and coding skills all the time. I try to learn the underlying I possess a wide range of skills that enable me to develop visually appealing and
mechanics and use abstractions where relevant. interactive user interfaces for web applications.
</p> </p>
</div> </div>
<div class="card variant-ringed-hollow p-4 md:p-8 space-y-4"> <div class="card variant-ringed-hollow p-4 md:p-8 space-y-4">
<i class="fa-solid fa-palette text-4xl text-primary-500" /> <i class="fa-solid fa-palette text-4xl text-primary-500" />
<h3 class="h3">Creativity & Presentation</h3> <h3 class="h3">Design</h3>
<p class="opacity-75"> <p class="opacity-75">
I try to create better, novel ways to approach problems and give my best to present them Over the years, I have honed my ability to create visually appealing interfaces that
in a clear and concise manner. are both user-friendly and intuitive.
</p> </p>
</div> </div>
<div class="card variant-ringed-hollow p-4 md:p-8 space-y-4"> <div class="card variant-ringed-hollow p-4 md:p-8 space-y-4">
<i class="fa-solid fa-users text-4xl text-primary-500" /> <i class="fa-solid fa-users text-4xl text-primary-500" />
<h3 class="h3">Teamwork & Stakeholders</h3> <h3 class="h3">User Experience</h3>
<p class="opacity-75"> <p class="opacity-75">
From my experience with a wide range of roles I understand the how to communication with I understand the importance of creating a seamless UX for end-users. Which includes
stakeholders across an organization. a solid understanding user behavior.
</p> </p>
</div> </div>
</section> </section>

View File

@ -1,9 +0,0 @@
import { promises as fsp } from 'fs';
export async function makeDirectory(directoryPath) {
fsp.mkdir(directoryPath, { recursive: true }, (err) => {
if (err) {
return console.error(err);
}
});
}

View File

@ -1,115 +0,0 @@
import { getHighlighter } from 'shiki';
import { getTheme, loadTheme } from 'shiki-themes';
const escapeChars = {
'<': '&lt;',
'>': '&gt;',
'&': '&amp;',
'{': '&#123;',
'}': '&#125;'
};
const escapeRE = new RegExp(`[${Object.keys(escapeChars).join('')}]`, 'g');
function escape(str) {
if (str && str.length !== 0) {
return str.replace(escapeRE, (c) => escapeChars[c]);
}
return '';
}
function render(lines, options) {
const { fg, bg } = options;
const lineNumbers = options.showLineNumbers(lines.length, options.lang);
const lang = options.lang ? `<span class="code-language">${options.lang}</span>` : '';
return `<pre class="code-highlight" style="color: ${fg}; background-color: ${bg}">${lang}<code class="${
lineNumbers ? 'numbered' : 'simple'
}">${lines.map(lineRenderer(options)).join('\n')}\n</code></pre>`;
}
const lineRenderer = (options) => (line) => {
const output = line.map(tokenRenderer(options)).join('');
const { leadingWS, content, trailingWS } = splitLeadingAndTrailingWS(output);
return `${leadingWS || ''}<span class="line-of-code">${content || ''}</span>${
trailingWS || ''
}`;
};
const tokenRenderer = (options) => (token) => {
if (!token.color || token.color.toLowerCase() === options.fg) {
return escape(token.content);
}
const { leadingWS, content, trailingWS } = splitLeadingAndTrailingWS(token.content);
if (!content) {
return leadingWS;
}
return `${leadingWS}<span style="color: ${token.color}">${escape(content)}</span>${trailingWS}`;
};
function splitLeadingAndTrailingWS(content) {
const len = content.length;
let start = 0;
let end = len;
while (start < end && isWS(content.charAt(start))) {
start++;
}
if (start === end) {
return {
leadingWS: content || ''
};
}
while (end > start && isWS(content.charAt(end - 1))) {
end--;
}
return {
leadingWS: content.slice(0, start),
content: content.slice(start, end),
trailingWS: end < content.length ? content.slice(end) : ''
};
}
function isWS(char) {
return char === ' ' || char === '\t';
}
function isPlaintext(lang) {
return !lang || ['plaintext', 'txt', 'text'].indexOf(lang) !== -1;
}
const defaultOpts = {
theme: 'nord',
fg: undefined,
bg: undefined,
showLineNumbers: (numberOfLines) => numberOfLines > 5
};
export default async function createHighlighter(opts) {
const options = { ...defaultOpts, ...opts };
if (options.theme.endsWith('.json')) {
options.theme = loadTheme(options.theme);
} else {
options.theme = getTheme(options.theme);
}
const baseSettings = (
(options.theme['tokenColors'] || []).find((x) => !x.scope) || { settings: {} }
).settings;
const colors = options.theme.colors || {};
const getThemeColor = (name) => baseSettings[name] || colors[`editor.${name}`] || colors[name];
const fg = (options.fg || getThemeColor('foreground') || '#eeeeee').toLowerCase();
const bg = (options.bg || getThemeColor('background') || '#222222').toLowerCase();
return getHighlighter(options).then(
(highlighter) => (code, lang) =>
render(
isPlaintext(lang)
? [[{ content: code }]]
: highlighter.codeToTokensBase(code, lang),
{ ...options, fg, bg, lang }
)
);
}

View File

@ -1,26 +1,48 @@
<script lang="ts"> <script lang="ts">
import SkillContainer from '$lib/components/skills/SkillContainer.svelte'; import SkillContainer from '$lib/components/SkillContainer.svelte';
import HeroSection from '$lib/components/home/HeroSection.svelte'; import HeroSection from '$lib/components/home/HeroSection.svelte';
import QuickCards from '$lib/components/home/QuickCards.svelte'; import QuickCards from '$lib/components/home/QuickCards.svelte';
import { website } from '$lib/config';
import * as conf from '$lib/config';
</script> </script>
<svelte:head> <svelte:head>
<title>Matt Morin</title> <title>Matt Morin</title>
<meta property="og:type" content="website" /> <meta property="og:type" content="website" />
<meta name="description" content={website.description} /> <meta name="description" content={conf.description} />
<meta property="og:title" content={website.siteTitle} /> <meta property="og:title" content={conf.title} />
<meta property="og:type" content="article" /> <meta property="og:type" content="article" />
<meta property="og:description" content={website.description} /> <meta property="og:description" content={conf.description} />
<meta property="og:url" content={website.url} /> <meta property="og:url" content={conf.url} />
<meta property="og:image" content="/images/profile-pic.png" /> <meta property="og:image" content="/images/profile-pic.png" />
</svelte:head> </svelte:head>
<div class="mt-24 container h-full mx-auto flex-col justify-center items-center md:w-3/4 space-y-8"> <div class="mt-24 container h-full mx-auto flex-col justify-center items-center md:w-3/4">
<!-- <div class="space-y-10 mt-4 text-center flex flex-col items-center">
<h1 class="h1">I make the wheels turn.</h1>
<figure>
<section class="img-bg" />
<img
src="/images/profile-pic.png"
class="w-8 h-8 md:h-[200px] md:w-[200px]"
alt="Profile picture"
/>
</figure>
<img
src="/animations/infinity-loop-icon.svg"
alt="Icon"
class="w-16 md:w-32 lg:w-48 h-full rounded-full"
/>
<h2 class="h2">My github contributions</h2>
</div> -->
<HeroSection /> <HeroSection />
<QuickCards />
<SkillContainer /> <SkillContainer />
</div> </div>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 122 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 147 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

View File

@ -1 +0,0 @@
{"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}

View File

@ -4,9 +4,8 @@ import forms from '@tailwindcss/forms';
import typography from '@tailwindcss/typography'; import typography from '@tailwindcss/typography';
import { skeleton } from '@skeletonlabs/tw-plugin'; import { skeleton } from '@skeletonlabs/tw-plugin';
const defineConfig: Config = { export default {
darkMode: 'media', darkMode: 'class',
content: [ content: [
'./src/**/*.{html,js,svelte,ts}', './src/**/*.{html,js,svelte,ts}',
join(require.resolve('@skeletonlabs/skeleton'), '../**/*.{html,js,svelte,ts}') join(require.resolve('@skeletonlabs/skeleton'), '../**/*.{html,js,svelte,ts}')
@ -28,6 +27,4 @@ const defineConfig: Config = {
} }
}) })
] ]
}; } satisfies Config;
export default defineConfig;

View File

@ -3,7 +3,6 @@ import { purgeCss } from 'vite-plugin-tailwind-purgecss';
import { sveltekit } from '@sveltejs/kit/vite'; import { sveltekit } from '@sveltejs/kit/vite';
import { defineConfig } from 'vitest/config'; import { defineConfig } from 'vitest/config';
import { threeMinifier } from '@yushijinhun/three-minifier-rollup'; import { threeMinifier } from '@yushijinhun/three-minifier-rollup';
import { imagetools } from 'vite-imagetools';
import path from 'path'; import path from 'path';
export default defineConfig({ export default defineConfig({
@ -31,8 +30,7 @@ export default defineConfig({
greedy: [/^hljs-/] greedy: [/^hljs-/]
} }
}), }),
{ ...threeMinifier(), enforce: 'pre' }, { ...threeMinifier(), enforce: 'pre' }
imagetools({ removeMetadata: true })
], ],
define: { define: {
'process.env.VITE_BUILD_TIME': JSON.stringify(new Date().toISOString()) 'process.env.VITE_BUILD_TIME': JSON.stringify(new Date().toISOString())