Better slugs, improvements to projects, some fixes
All checks were successful
Build and Deploy to Web Server / deploy (push) Successful in 14m57s

This commit is contained in:
2025-08-14 11:11:10 +09:30
parent 1f45a74b2a
commit 778490bed8
25 changed files with 134 additions and 69 deletions

View File

@@ -3,6 +3,7 @@ title: Awoken
role: Principal Orchestrator
type: Feature Film
date: 2019-07-01
slug: awoken
description: A young medical student attempts to cure her brother from a terminal sleep illness, called fatal familial insomnia, where you are unable to sleep until you die. On her quest to help him, a more sinister reason for his condition is revealed.
images:
{

View File

@@ -3,6 +3,7 @@ title: Barbecue
role: Additional Orchestration
type: Feature Film
date: 2017-07-01
slug: barbecue
description: The rituals, stories and traditions surrounding the process of cooking meat over an open flame are shared by numerous cultures around the world.
images:
{

View File

@@ -3,6 +3,7 @@ title: Down To Earth
role: Composer
type: Short Film
date: 2020-07-01
slug: down-to-earth
description: Three young misfits venture into the Australian outback to find what they believe is a meteorite that has crash landed near their country town, only to discover it's something far more mysterious.
images:
{

View File

@@ -3,6 +3,7 @@ title: Dungeons and Dining Tables
role: Composer and Sound Designer
type: Video Game
date: 2026-07-01
slug: dungeons-and-dining-tables
ongoing: true
description: "Delve dungeons to collect rare furniture, take that furniture back to your home to decorate and the cosier your house is, the higher your stats! 🪑🏡⚔️ Go forth and drive the grumpiness from the land: Your perfect home is just a dungeon away! Oh, and you play as an Axolotl 🥳"
frontPage: { "order": 1 }

View File

@@ -3,6 +3,7 @@ title: Ella
role: Composer
type: Short Film
date: 2013-07-01
slug: ella
description: When Ella learns that her sister Gracie is sick, Ella must turn to the stars to help heal her sister.
images:
{

View File

@@ -3,6 +3,7 @@ title: Frontier Quest
role: Composer and Sound Designer
type: Video Game
date: 2021-02-01
slug: frontier-quest
description: Rebuild a frontier town and become acquainted with its community in puzzle-RPG Frontier Quest! Explore the frontier, collect materials and defeat monsters with the right equipment in order to restore the town and uncover the secrets of the frontier.
images:
{

View File

@@ -3,6 +3,7 @@ title: Lucie's Potager
role: Composer and Sound Designer
type: Video Game
date: 2023-02-01
slug: lucies-potager
description: Farm and sell exotic plants with Lucie in this shopkeeping RPG!
images:
{

View File

@@ -3,6 +3,7 @@ title: Meowing Point
role: Additional Music
type: Video Game
date: 2023-10-01
slug: meowing-point
description: Point and meow. 3D hidden cat game. These creatures have been turned into stone. Find and save them all.
images:
{

View File

@@ -3,6 +3,7 @@ title: "Music With Motion: Down Under"
role: Conductor / Artistic Director
type: Concert
date: 2025-11-15
slug: music-with-motion-down-under
description: "Music With Motion: Down Under is a dynamic celebration of Australia's video game soundtracks—performed live by a full wind orchestra and synchronised in real time with stunning visuals on the big screen. Premiering all-new orchestrations created especially for this event by award-winning Artistic Director Dr Nathan Cummins, the performance showcases music from games developed across the country, including several from right here in South Australia. Many of these games have never had their music performed live, and you'll be among the very first to hear it."
frontPage: { "order": 2 }
images:

View File

@@ -3,6 +3,7 @@ title: Pixelated Symphonies
role: Conductor / Artistic Director
type: Concert
date: 2025-03-09
slug: pixelated-symphonies
description: "Experience the magic of these legendary symphonic video game soundtracks like never before! Join [the Adelaide Wind Orchestra] for an unforgettable concert of musical enchantment as video game industry insider and composer Dr Nathan Cummins and AWO take you on a wild ride through this iconic music. From the epic adventures of Super Mario to the heartwarming melodies of The Legend of Zelda, immerse yourself and be swept away by the brilliance of Australia's leading symphonic wind orchestra."
frontPage: { "order": 3 }
images:

View File

@@ -3,6 +3,7 @@ title: Roc's Odyssey
role: Composer and Sound Designer
type: Video Game
date: 2025-02-21
slug: rocs-odyssey
description: Explore vast landscapes and get lost in a beautiful yet dangerous world in Roc's Odyssey. Filled with intense combat, strange allies, platforming, enemies, treasures, secrets, upgrades, friendships and lore this hand drawn action adventure will have you hooked!
frontPage: { "order": 4 }
images:

View File

@@ -3,6 +3,7 @@ title: Scooter
role: Composer
type: Short Film
date: 2022-02-21
slug: scooter
description: An eccentric senior citizen who would like to visit his daughter one last time sets him off on an epic 250km journey from the outback to the city on his trusty scooter.
images:
{

View File

@@ -3,6 +3,7 @@ title: "Submerged: Hidden Depths"
role: Music Transcription & Preparation
type: Video Game
date: 2020-10-22
slug: submerged-hidden-depths
description: Boat, climb, interact and explore in the beautiful ruins of a sunken world.
images:
{

View File

@@ -3,6 +3,7 @@ title: The Lion and the Mouse
role: Composer
type: Concert Music
date: 2024-10-12
slug: the-lion-and-the-mouse
description: "A piece for narrator and orchestra (or wind orchestra) that aims to teach children about music and the instruments of the orchestra. Experience the beloved Aesop fable come to life, through wind instruments and storytelling designed to inspire the imagination of children and families."
frontPage: { "order": 5 }
images:

View File

@@ -3,6 +3,7 @@ title: TOHU
role: Brass Arrangement (Junkle), Orchestration (Circus)
type: Video Game
date: 2021-10-22
slug: tohu
description: Experience a brand new adventure game set amongst a world of weird and wonderful fish planets. Explore beautiful environments, solve intricate puzzles and discover the truth about a mysterious little girl and her mechanical alter-ego, Cubus.
images:
{

View File

@@ -23,19 +23,23 @@ const languageIcons: Record<string, string> = {
const languageIcon = languageIcons[props["data-language"]];
const title = meta.title;
const copyID = Math.random().toString(36);
---
<figure class="my-4 rounded-b">
{
title && (
<figcaption>
<div class="bg-primary w-full rounded-t-md border-1 border-black px-4 py-2 text-white">
<div class="bg-primary w-full rounded-t-md border-1 border-gray-600 px-4 py-2 text-white">
<div class="flex justify-between">
<div class="flex items-center justify-between gap-2 font-bold">
{languageIcon && <Icon name={languageIcon} />}
<p>{title}</p>
</div>
<button id="copy__code">Copy Code</button>
<button class="font-bold" id=`copy-${copyID}`>
Copy <Icon name="mdi:content-copy" class="ml-0.5 inline-block" />
</button>
</div>
</div>
</figcaption>
@@ -44,8 +48,7 @@ const title = meta.title;
<pre
class:list={[
"py-2",
"border-x border-b",
"border-x border-b border-gray-600",
"rounded-b",
!title ? "rounded-t border-t" : "",
className
@@ -53,59 +56,11 @@ const title = meta.title;
{...props}><slot /></pre>
</figure>
<style is:global>
.astro-code {
overflow-x: auto;
}
.astro-code code {
/* Define a counter for each <code> inside .astro-code */
counter-reset: step;
/* Start from zero, increment the counter */
counter-increment: step 0;
font-size: 14px;
width: fit-content;
min-width: 100%;
display: block;
}
.astro-code code .line {
display: inline-block;
width: 100%;
padding-right: 2rem;
}
.astro-code code .line::before {
content: counter(step);
counter-increment: step;
width: 2rem;
margin-right: 1.25rem;
display: inline-block;
margin-left: auto;
text-align: right;
/* Fix element position during horizontal scroll */
position: sticky;
left: 0;
z-index: 1;
/* Give a bit of space to counter on horizontal scroll */
padding-right: 0.25rem;
/* Illustrative purpose, please extract the value from the theme instead */
background-color: white;
color: hsla(0, 0%, 0%, 0.5);
}
</style>
<script define:vars={{ dataCode }}>
<script define:vars={{ dataCode, copyID }}>
if (typeof navigator.clipboard !== undefined) {
const trigger = document.querySelector("#copy__code");
const trigger = document.getElementById(`copy-${copyID}`);
trigger.addEventListener("click", () => {
// Write the code to clipboard
navigator.clipboard.writeText(dataCode);
});
}

View File

@@ -1 +1 @@
<h5 class="font-base text-base font-bold"><slot /></h5>
<h5 class="text-lg font-bold"><slot /></h5>

View File

@@ -1 +1 @@
<h6 class="font-base text-base underline"><slot /></h6>
<h6 class="text-base font-bold"><slot /></h6>

View File

@@ -0,0 +1,10 @@
---
import Image from "astro/components/Image.astro";
const { src, alt } = Astro.props;
import { getImageByPath } from "@lib/utils";
const imageSRC = getImageByPath(src)!;
---
<Image src={imageSRC} alt={alt} />

View File

@@ -112,10 +112,18 @@ const { navbarDisplay = "normal" } = Astro.props as Props;
</script>
<script>
let nav: HTMLElement;
let toggle: HTMLElement;
let nav: HTMLElement | null;
let toggle: HTMLElement | null;
const checkScroll = () => {
if (!nav) {
nav = document.getElementById("nav");
}
if (!nav) {
return;
}
nav.setAttribute(
"data-transparency",
window.scrollY === 0 && window.navbarDisplay === "transparent"
@@ -125,14 +133,19 @@ const { navbarDisplay = "normal" } = Astro.props as Props;
};
document.addEventListener("astro:page-load", () => {
nav = document.getElementById("nav")!;
toggle = document.getElementById("menu-toggle")!;
nav = document.getElementById("nav");
toggle = document.getElementById("menu-toggle");
toggle.addEventListener("click", () => {
const visible = nav.getAttribute("data-mobile-menu") === "visible";
nav.setAttribute("data-mobile-menu", visible ? "hidden" : "visible");
checkScroll();
});
if (toggle) {
toggle.addEventListener("click", () => {
if (nav) {
const visible = nav.getAttribute("data-mobile-menu") === "visible";
nav.setAttribute("data-mobile-menu", visible ? "hidden" : "visible");
}
checkScroll();
});
}
checkScroll();
});

View File

@@ -8,6 +8,8 @@ import { Icon } from "astro-icon/components";
import { Image } from "astro:assets";
import type { CollectionEntry } from "astro:content";
import { slugify } from '@lib/utils';
interface Props {
project: CollectionEntry<"projects">;
textOn?: "left" | "right";
@@ -130,7 +132,7 @@ const projectHasBody = project.body && project.body.trim().length > 0;
>
<span
><h2 class="font-header-alt inline-block text-lg font-semibold">
{projectHasBody && <TextLink href=`/projects/${project.id}/`>{project.data.title}</TextLink>}{!projectHasBody && project.data.title }{!project.data.ongoing && <span class="italic text-sm font-light"> ({project.data.date.getFullYear()})</span>}</h2></span
{projectHasBody && <TextLink href=`/projects/${slugify(project.data.type)}/${slugify(project.data.slug)}/`>{project.data.title}</TextLink>}{!projectHasBody && project.data.title }{!project.data.ongoing && <span class="italic text-sm font-light"> ({project.data.date.getFullYear()})</span>}</h2></span
>
<h3 class="font-header-alt font-base font-medium">
{project.data.role}

View File

@@ -9,6 +9,7 @@ const projects = defineCollection({
type: z.string(),
date: z.date(),
description: z.string(),
slug: z.string(),
ongoing: z.boolean().optional().default(false),
frontPage: z
.object({

View File

@@ -14,6 +14,23 @@ const allProjectHeros = import.meta.glob<{ default: ImageMetadata }>(
{ eager: true }
);
const allImages = import.meta.glob<{ default: ImageMetadata }>(
"/**/*.{jpeg,jpg,png,gif}",
{
eager: true
}
);
export function getImageByPath(path: string): ImageMetadata | null {
for (const [imagePath, mod] of Object.entries(allImages)) {
if (imagePath.includes(path)) {
return mod.default;
}
}
return null;
}
export function getProjectHero(project: Project): ImageMetadata {
let image: ImageMetadata = Object.values(allProjectHeros)[0].default;
for (const [path, mod] of Object.entries(allProjectHeros)) {
@@ -110,3 +127,13 @@ export async function getFullExternalURLOfImage(
return new URL((await getImage({ src: image })).src, import.meta.env.SITE)
.href;
}
export function slugify(input: string): string {
if (!input) return "";
let slug = input.toLowerCase().trim();
slug = slug.normalize("NFD").replace(/[\u0300-\u036f]/g, "");
slug = slug.replace(/[^a-z0-9\s-]/g, " ");
slug = slug.replace(/[\s-]+/g, "-");
slug = slug.replace(/^-+|-+$/g, "");
return slug;
}

View File

@@ -7,7 +7,8 @@ import { getCollection, render } from "astro:content";
import {
getAllProjectImages,
getFullExternalURLOfImage,
getProjectHero
getProjectHero,
slugify
} from "@/lib/utils";
export async function getStaticPaths() {
@@ -16,7 +17,9 @@ export async function getStaticPaths() {
});
return projects.map((project) => ({
params: { slug: project.id },
params: {
slug: `${slugify(project.data.type)}/${slugify(project.data.slug)}`
},
props: { project }
}));
}
@@ -44,6 +47,7 @@ import H3 from "@components/MDX/H3.astro";
import H4 from "@components/MDX/H4.astro";
import H5 from "@components/MDX/H5.astro";
import H6 from "@components/MDX/H6.astro";
import IMG from "@components/MDX/IMG.astro";
import P from "@components/MDX/P.astro";
---
@@ -83,7 +87,8 @@ import P from "@components/MDX/P.astro";
h5: H5,
h6: H6,
blockquote: Blockquote,
pre: CodeSnippet
pre: CodeSnippet,
img: IMG
}}
/>
</div>

View File

@@ -78,4 +78,41 @@
font-family: "Roboto", sans-serif;
@apply text-gray-600 dark:text-white;
}
.astro-code {
@apply overflow-auto;
}
.astro-code code {
counter-reset: step;
counter-increment: step 0;
@apply text-sm;
@apply block;
@apply w-fit min-w-full;
}
.astro-code code .line {
@apply inline-block;
@apply w-full;
@apply pr-8;
@apply first:pt-2 last:pb-2;
@apply bg-white dark:bg-gray-100;
}
.astro-code code .line::before {
content: counter(step);
counter-increment: step;
@apply w-10;
@apply mr-5 ml-auto pr-2;
@apply inline-block;
@apply text-right;
@apply sticky;
@apply left-0;
@apply z-10;
@apply bg-gray-200;
}
}