More website content updates #10
@@ -26,8 +26,4 @@ COPY --from=build /app/dist /usr/share/nginx/html
|
|||||||
|
|
||||||
RUN chown -R nginx:nginx /usr/share/nginx/html
|
RUN chown -R nginx:nginx /usr/share/nginx/html
|
||||||
|
|
||||||
#COPY entrypoint.sh /entrypoint.sh
|
EXPOSE 80
|
||||||
|
|
||||||
EXPOSE 80
|
|
||||||
|
|
||||||
#ENTRYPOINT ["/entrypoint.sh"]
|
|
||||||
@@ -3,11 +3,14 @@ import {defineConfig} from 'astro/config';
|
|||||||
import sitemap from "@astrojs/sitemap";
|
import sitemap from "@astrojs/sitemap";
|
||||||
import tailwindcss from "@tailwindcss/vite";
|
import tailwindcss from "@tailwindcss/vite";
|
||||||
|
|
||||||
|
// We don't have access to short imports this early in the build chain
|
||||||
|
// noinspection ES6PreferShortImport
|
||||||
import {siteLayout, getPaths} from "./src/data/site-layout.ts";
|
import {siteLayout, getPaths} from "./src/data/site-layout.ts";
|
||||||
|
|
||||||
const disabledPaths = getPaths(siteLayout, [], true)
|
const disabledPaths = getPaths(siteLayout, [], true)
|
||||||
|
|
||||||
// https://astro.build/config
|
// https://astro.build/config
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
site: "https://caperren.com",
|
site: "https://caperren.com",
|
||||||
prefetch: {
|
prefetch: {
|
||||||
@@ -20,6 +23,9 @@ export default defineConfig({
|
|||||||
})
|
})
|
||||||
],
|
],
|
||||||
vite: {
|
vite: {
|
||||||
plugins: [tailwindcss()],
|
plugins: [
|
||||||
|
// @ts-ignore
|
||||||
|
tailwindcss()
|
||||||
|
],
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
#!/usr/bin/env sh
|
|
||||||
set -e
|
|
||||||
|
|
||||||
# Generate a unique token per container launch
|
|
||||||
TOKEN="$(cat /proc/sys/kernel/random/uuid)" # or: TOKEN="$(date +%s%N)"
|
|
||||||
|
|
||||||
# Write it into a file NGINX will include
|
|
||||||
cat >/etc/nginx/conf.d/_release_token.conf <<EOF
|
|
||||||
# auto-generated at container start
|
|
||||||
set \$release_token "$TOKEN";
|
|
||||||
EOF
|
|
||||||
|
|
||||||
# Then exec nginx
|
|
||||||
exec nginx -g 'daemon off;'
|
|
||||||
@@ -14,12 +14,6 @@ http {
|
|||||||
root /usr/share/nginx/html;
|
root /usr/share/nginx/html;
|
||||||
index index.html index.htm;
|
index index.html index.htm;
|
||||||
include /etc/nginx/mime.types;
|
include /etc/nginx/mime.types;
|
||||||
#include /etc/nginx/conf.d/_release_token.conf;
|
|
||||||
|
|
||||||
#etag off;
|
|
||||||
|
|
||||||
#add_header ETag "\"W/$release_token\"" always;
|
|
||||||
#add_header Cache-Control "max-age=0, must-revalidate" always;
|
|
||||||
|
|
||||||
gzip on;
|
gzip on;
|
||||||
gzip_proxied any;
|
gzip_proxied any;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
---
|
---
|
||||||
---
|
---
|
||||||
|
|
||||||
<footer class="fixed bottom-0 left-0 z-20 w-full px-6 py-2 bg-black border-t border-t-caperren-green-dark text-caperren-green-dark text-sm flex items-center justify-between">
|
<footer class="z-50 w-full max-w-full px-6 py-2 bg-black border-t border-t-caperren-green-dark text-caperren-green-dark text-sm flex items-center justify-between">
|
||||||
<span>{import.meta.env.PUBLIC_BUILD_ENVIRONMENT || "development"}</span>
|
<span>{import.meta.env.PUBLIC_BUILD_ENVIRONMENT || "development"}</span>
|
||||||
<span>{import.meta.env.PUBLIC_REPO_VERSION_HASH || "invalid"}</span>
|
<span>{import.meta.env.PUBLIC_REPO_VERSION_HASH || "invalid"}</span>
|
||||||
</footer>
|
</footer>
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ const paddingClasses: string = `px-${columnPadding} py-${rowPadding}`;
|
|||||||
---
|
---
|
||||||
|
|
||||||
<div class="relative max-w-full overflow-x-auto">
|
<div class="relative max-w-full overflow-x-auto">
|
||||||
<table class="w-full text-sm text-left">
|
<table class="text-sm text-left">
|
||||||
<thead class="text-xs border-b-3 border-caperren-green uppercase bg-black">
|
<thead class="text-xs border-b-3 border-caperren-green uppercase bg-black">
|
||||||
<tr>
|
<tr>
|
||||||
{data.header.map(headingText => (
|
{data.header.map(headingText => (
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ const timeline: timelineEntry[] = Astro.props.timeline || [];
|
|||||||
---
|
---
|
||||||
|
|
||||||
<custom-timeline>
|
<custom-timeline>
|
||||||
|
|
||||||
<div class="relative z-10 grid gap-6 grid-flow-row sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 3xl:grid-cols-6"
|
<div class="relative z-10 grid gap-6 grid-flow-row sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 3xl:grid-cols-6"
|
||||||
data-timeline>
|
data-timeline>
|
||||||
{timeline.map((entry, index) => (
|
{timeline.map((entry, index) => (
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ class CustomTimeline extends HTMLElement {
|
|||||||
super();
|
super();
|
||||||
this._eventElements = this._getNodeElements();
|
this._eventElements = this._getNodeElements();
|
||||||
|
|
||||||
|
|
||||||
window.addEventListener("load", this._paintLeaderLines);
|
window.addEventListener("load", this._paintLeaderLines);
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -26,17 +25,20 @@ class CustomTimeline extends HTMLElement {
|
|||||||
}
|
}
|
||||||
}).filter(pair => pair !== undefined)
|
}).filter(pair => pair !== undefined)
|
||||||
|
|
||||||
|
let contentBodyScrolling = document.getElementById("content-body-scrolling")
|
||||||
|
|
||||||
pairs.forEach(pair => {
|
pairs.forEach(pair => {
|
||||||
new LeaderLine({
|
let line = new LeaderLine({
|
||||||
start: pair[0],
|
start: pair[0],
|
||||||
end: pair[1],
|
end: pair[1],
|
||||||
color: '#10ac25',
|
color: '#10ac25',
|
||||||
size: 3,
|
size: 3,
|
||||||
startSocket: "right",
|
startSocket: "right",
|
||||||
endSocket: "left",
|
endSocket: "left",
|
||||||
startPlug: "square",
|
startPlug: "square",
|
||||||
endPlug: "arrow3"
|
endPlug: "arrow3"
|
||||||
});
|
});
|
||||||
|
contentBodyScrolling?.addEventListener("scroll", () => line.position())
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,22 +4,18 @@ export const siteLayout: navLink[] = [
|
|||||||
{navText: "About", path: ""},
|
{navText: "About", path: ""},
|
||||||
{navText: "Education", path: "education"},
|
{navText: "Education", path: "education"},
|
||||||
{
|
{
|
||||||
enabled: false,
|
|
||||||
navText: "Experiences",
|
navText: "Experiences",
|
||||||
path: "experience",
|
path: "experience",
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
enabled: false,
|
|
||||||
navText: "SpaceX",
|
navText: "SpaceX",
|
||||||
path: "spacex",
|
path: "spacex",
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
enabled: false,
|
|
||||||
navText: "Hardware Test Engineer I/II",
|
navText: "Hardware Test Engineer I/II",
|
||||||
path: "hardware-test-engineer-i-ii"
|
path: "hardware-test-engineer-i-ii"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
enabled: false,
|
|
||||||
navText: "Avionics Test Engineering Internship",
|
navText: "Avionics Test Engineering Internship",
|
||||||
path: "avionics-test-engineering-internship"
|
path: "avionics-test-engineering-internship"
|
||||||
}
|
}
|
||||||
@@ -151,8 +147,9 @@ export const siteLayout: navLink[] = [
|
|||||||
navText: "Projects",
|
navText: "Projects",
|
||||||
path: "projects",
|
path: "projects",
|
||||||
children: [
|
children: [
|
||||||
{navText: "Shed Solar", path: "shed-solar", enabled: false},
|
|
||||||
{navText: "OSSM Overkill Edition", path: "ossm-overkill-edition", enabled: false},
|
{navText: "OSSM Overkill Edition", path: "ossm-overkill-edition", enabled: false},
|
||||||
|
{navText: "Rachael Ray Light Box", path: "rachael-ray-light-box", enabled: false},
|
||||||
|
{navText: "Shed Solar", path: "shed-solar", enabled: false},
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{enabled: false, navText: "NixOS", path: "nixos"},
|
{enabled: false, navText: "NixOS", path: "nixos"},
|
||||||
|
|||||||
@@ -16,20 +16,23 @@ const pageEnabled = pathToMetadata(Astro.url.pathname).enabled ?? true;
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8"/>
|
<meta charset="UTF-8"/>
|
||||||
<link rel="icon" href="/favicon-solid.png" type="image/png"/>
|
<link rel="icon" href="/favicon-solid.png" type="image/png"/>
|
||||||
|
<!--suppress HtmlUnknownTarget -->
|
||||||
<link rel="sitemap" href="/sitemap-index.xml"/>
|
<link rel="sitemap" href="/sitemap-index.xml"/>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||||
<title>{pageEnabled ? pageTitle : "Corwin Perren"}</title>
|
<title>{pageEnabled ? pageTitle : "Corwin Perren"}</title>
|
||||||
</head>
|
</head>
|
||||||
<body class="bg-black text-white">
|
<body class="flex flex-col bg-black text-white h-dvh">
|
||||||
<Navbar/>
|
<div id="content-body-scrolling" class="grow overflow-y-scroll">
|
||||||
<main class="mx-6 mt-6 mb-14">
|
<Navbar/>
|
||||||
{(Astro.props.title && showTitle && pageEnabled) && (
|
<main class="mx-6 my-6">
|
||||||
<h1 class="font-extrabold md:text-3xl md:mb-6">{Astro.props.title}</h1>
|
{(Astro.props.title && showTitle && pageEnabled) && (
|
||||||
)}
|
<h1 class="font-extrabold md:text-3xl md:mb-6">{Astro.props.title}</h1>
|
||||||
{pageEnabled && (
|
)}
|
||||||
<slot/>
|
{pageEnabled && (
|
||||||
)}
|
<slot/>
|
||||||
</main>
|
)}
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
<Footer/>
|
<Footer/>
|
||||||
<script src="../scripts/main.ts"></script>
|
<script src="../scripts/main.ts"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
@@ -68,7 +68,6 @@ const headerCarouselGroup: carouselGroup = {
|
|||||||
While my first iteration was sized appropriately and went together with no issues, the ball mount neck ended up
|
While my first iteration was sized appropriately and went together with no issues, the ball mount neck ended up
|
||||||
snapping due to a low infill percentage. After changing that area to 100% infill, including a handful of the
|
snapping due to a low infill percentage. After changing that area to 100% infill, including a handful of the
|
||||||
rear mount layers that it attached to, a second iteration has worked perfectly for a few years now! If you're
|
rear mount layers that it attached to, a second iteration has worked perfectly for a few years now! If you're
|
||||||
interested in printing this yourself, feel free to download the model and print it yourself using the button
|
interested in printing this yourself, feel free to download the model using the button under the photos!
|
||||||
under the photos!
|
|
||||||
</p>
|
</p>
|
||||||
</HobbyLayout>
|
</HobbyLayout>
|
||||||
@@ -39,7 +39,7 @@ const headerCarouselGroup: carouselGroup = {
|
|||||||
Through college, I learned electronics and PCB design, embedded and pc programming, basic mechanical design and
|
Through college, I learned electronics and PCB design, embedded and pc programming, basic mechanical design and
|
||||||
fabrication, on top of learning how to work well with others in a team.
|
fabrication, on top of learning how to work well with others in a team.
|
||||||
I quickly realized that robotics was an ideal focus due to its inherent multi-disciplinary nature, and joined
|
I quickly realized that robotics was an ideal focus due to its inherent multi-disciplinary nature, and joined
|
||||||
the OSU Robotics club, which introduced me to people who are still my best friends today.
|
the OSU Robotics Club, which introduced me to people who are still my best friends today.
|
||||||
Through student engineering jobs, I had the unique opportunity to work on some incredible projects such as the
|
Through student engineering jobs, I had the unique opportunity to work on some incredible projects such as the
|
||||||
<a class="text-blue-500 hover:text-blue-300"
|
<a class="text-blue-500 hover:text-blue-300"
|
||||||
href="/experience/osu-ceoas-ocean-mixing-group/robotic-oceanographic-surface-sampler">robotic oceanographic
|
href="/experience/osu-ceoas-ocean-mixing-group/robotic-oceanographic-surface-sampler">robotic oceanographic
|
||||||
|
|||||||
5
src/pages/sitemap-index.xml
Normal file
5
src/pages/sitemap-index.xml
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<sitemapindex>
|
||||||
|
<sitemap>
|
||||||
|
<loc>https://caperren.com/sitemap-0.xml</loc>
|
||||||
|
</sitemap>
|
||||||
|
</sitemapindex>
|
||||||
@@ -11,7 +11,6 @@ for (const pagePath of getPaths()) {
|
|||||||
|
|
||||||
test(`${pagePath}: Has Title`, async ({page}) => {
|
test(`${pagePath}: Has Title`, async ({page}) => {
|
||||||
await page.goto(pagePath);
|
await page.goto(pagePath);
|
||||||
console.log(await page.title());
|
|
||||||
expect(await page.title()).not.toBe("Corwin Perren")
|
expect(await page.title()).not.toBe("Corwin Perren")
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
import { experimental_AstroContainer as AstroContainer } from 'astro/container';
|
|
||||||
import { expect, test } from 'vitest';
|
|
||||||
import Navbar from "@components/Navbar.astro"
|
|
||||||
|
|
||||||
test('Card with slots', async () => {
|
|
||||||
const container = await AstroContainer.create();
|
|
||||||
const result = await container.renderToString(Navbar, {
|
|
||||||
slots: {
|
|
||||||
default: 'Card content',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
// expect(result).toContain('This is a card');
|
|
||||||
// expect(result).toContain('Card content');
|
|
||||||
});
|
|
||||||
32
test/endpoints.spec.ts
Normal file
32
test/endpoints.spec.ts
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
import {expect, test} from "vitest";
|
||||||
|
|
||||||
|
import {siteLayout, getPaths} from "@data/site-layout.ts";
|
||||||
|
|
||||||
|
// Paths that should be known to Astro statically
|
||||||
|
const astroStaticPaths = new Set(
|
||||||
|
Object.keys(import.meta.glob("/src/pages/**/*.astro"))
|
||||||
|
.map((path) =>
|
||||||
|
path
|
||||||
|
.replace("/src/pages", "")
|
||||||
|
.replace(/index\.astro$/, "")
|
||||||
|
.replace(/\.astro$|\.md$/, "")
|
||||||
|
.replace(/\/$/, "")
|
||||||
|
|| "/"
|
||||||
|
));
|
||||||
|
|
||||||
|
// Paths that exist in the site layout
|
||||||
|
const siteLayoutPaths = new Set([...getPaths(siteLayout), ...getPaths(siteLayout, [], true)]);
|
||||||
|
|
||||||
|
// Paths that exist in Astro's static paths, but not in site layout
|
||||||
|
const astroNotLayoutPaths = astroStaticPaths.difference(siteLayoutPaths);
|
||||||
|
|
||||||
|
// Paths that exist in site layout, but not in Astro's static paths
|
||||||
|
const siteLayoutNotAstroPaths = siteLayoutPaths.difference(astroStaticPaths);
|
||||||
|
|
||||||
|
test('Pages Missing from Site Layout', async () => {
|
||||||
|
expect(astroNotLayoutPaths).toHaveLength(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Pages Missing from Astro Paths', async () => {
|
||||||
|
expect(siteLayoutNotAstroPaths).toHaveLength(0);
|
||||||
|
});
|
||||||
@@ -3,6 +3,7 @@ import {getViteConfig} from 'astro/config';
|
|||||||
|
|
||||||
export default getViteConfig(
|
export default getViteConfig(
|
||||||
{
|
{
|
||||||
|
// @ts-ignore
|
||||||
test: {
|
test: {
|
||||||
exclude: [
|
exclude: [
|
||||||
"test-e2e/**",
|
"test-e2e/**",
|
||||||
@@ -13,8 +14,6 @@ export default getViteConfig(
|
|||||||
'@': path.resolve(__dirname, './src')
|
'@': path.resolve(__dirname, './src')
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
/* for example, use global to avoid globals imports (describe, test, expect): */
|
|
||||||
// globals: true,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user