Nest songs under circles

This commit is contained in:
Maciej Jur 2023-04-29 21:00:17 +02:00
parent e8b653f8f3
commit 28bde28f46
21 changed files with 170 additions and 46 deletions

View file

@ -27,5 +27,5 @@ export default defineConfig({
integrations: [ integrations: [
mdx(), mdx(),
solid(), solid(),
], ]
}); });

View file

@ -1,14 +0,0 @@
import { defineMarkdocConfig } from '@astrojs/markdoc/config';
import Lyrics from './src/components/markdown/lyrics/Lyrics.astro';
export default defineMarkdocConfig({
tags: {
lyrics: {
render: Lyrics,
attributes: {
type: { type: String },
}
}
}
})

View file

@ -0,0 +1,15 @@
---
interface Props {
album: {
title: string;
cover: string;
url: string;
}
}
const { album } = Astro.props;
---
<a class="c-album" href={album.url}>
<img class="c-album__image" src={album.cover} alt=""/>
<div class="c-album__title">{album.title}</div>
</a>

View file

@ -5,7 +5,7 @@ interface Props {
title: string; title: string;
cat: string; cat: string;
track: number; track: number;
circle: string; name: string;
composer?: string; composer?: string;
lyrics?: string; lyrics?: string;
vocal?: string[]; vocal?: string[];
@ -33,7 +33,7 @@ const { metadata } = Astro.props;
</tr> </tr>
<tr> <tr>
<td>Circle</td> <td>Circle</td>
<td>{metadata.circle}</td> <td>{metadata.name}</td>
</tr> </tr>
<tr> <tr>
<td>Composer</td> <td>Composer</td>

View file

@ -0,0 +1,12 @@
---
title: Title
composer: Composer
lyrics: Lirycist
origin:
- Original title
album:
ARCD0051:
track: 7
vocal:
- Vocalist
---

View file

@ -0,0 +1,13 @@
---
slug: beautiful-sky
title: Beautiful Sky
composer: Masayoshi Minoshima
lyrics: Mei Ayakura
origin:
- U.N.オーエンは彼女なのか?
album:
ARCD0054:
track: 2
vocal:
- nachi
---

View file

@ -1,10 +1,13 @@
--- ---
slug: dont-lose
title: "Don't lose" title: "Don't lose"
origin: origin:
- 亡き王女の為のセプテット - 亡き王女の為のセプテット
album: album:
ARCD0054: ARCD0054:
track: 7 track: 7
vocal:
- nomico
--- ---
# Japanese # Japanese

View file

@ -1,12 +1,22 @@
--- ---
slug: dream-again
title: "Dream Again" title: "Dream Again"
composer: Camellia
lyrics: Camellia
origin: origin:
- the Last Judgment - the Last Judgment
album: album:
ARCD0054: ARCD0054:
track: 5 track: 5
vocal:
- Mei Ayakura
--- ---
# Japanese # Japanese
- 秒針の音が響空間 狭くて安心するほど
- 割り込んだ感覚に目を閉じる 光がまた眩かしすぎて
- どこまでも続いていく階段 [降]{くだ}った途方もないほど - どこまでも続いていく階段 [降]{くだ}った途方もないほど
- 行きたい場所はもう決まっている 幻想の声のする所 - 行きたい場所はもう決まっている 幻想の声のする所
- 夢溢れる海へ

View file

@ -1,4 +1,5 @@
--- ---
slug: black-eyes
title: Black Eyes title: Black Eyes
composer: Kirin (EastNewSound) composer: Kirin (EastNewSound)
lyrics: Mei Ayakura lyrics: Mei Ayakura

View file

@ -1,5 +1,6 @@
{ {
"Alstroemeria Records": { "alstroemeria-records": {
"name": "Alstroemeria Records",
"albums": { "albums": {
"ARCD0051": { "ARCD0051": {
"title": "Engaged Dancehall", "title": "Engaged Dancehall",

View file

@ -0,0 +1,39 @@
---
import Base from "@layouts/Base.astro";
import Album from "@components/markdown/Album.astro";
import Header from "@components/headers/Base.astro";
import { CIRCLES } from "@utils/songs/data";
export async function getStaticPaths() {
return Object.keys(CIRCLES)
.map(circle => ({
params: { circle },
props: { albums: CIRCLES[circle].albums }
}))
}
interface Props {
albums: typeof CIRCLES[string]['albums'];
}
const circle = Astro.params.circle!;
const albums = Astro.props.albums;
const items = Object.keys(albums)
.map(slug => ({
title: albums[slug].title,
cover: albums[slug].cover,
url: `/songs/${circle}/${slug}/`
}))
---
<Base>
<main>
<article>
<Header title={CIRCLES[circle].name} />
<section class="l-album-grid">
{items.map(album => <Album album={album} />)}
</section>
</article>
</main>
</Base>

View file

@ -1,8 +1,8 @@
--- ---
import Base from "../../layouts/Base.astro"; import Base from "@layouts/Base.astro";
import Header from '../../components/headers/Base.astro'; import Header from '@components/headers/Base.astro';
import { CollectionEntry, getCollection } from 'astro:content'; import { CollectionEntry, getCollection } from 'astro:content';
import { ALBUMS, getAllCats } from "../../utils/songs/data"; import { ALBUMS, getAllCats, order } from "@utils/songs/data";
export async function getStaticPaths() { export async function getStaticPaths() {
@ -10,11 +10,15 @@ export async function getStaticPaths() {
const cats = getAllCats(songs); const cats = getAllCats(songs);
return [...cats].map(cat => ({ return [...cats].map(cat => ({
params: {cat}, params: { circle: ALBUMS[cat].circle, cat },
props: { props: {
songs: songs songs: songs
.filter(entry => cat in entry.data.album) .filter(entry => cat in entry.data.album)
.map(song => ({ frontmatter: song.data, slug: `/songs/${cat}/${song.slug}/` })) .sort(order(cat))
.map(song => ({
frontmatter: song.data,
slug: `/songs/${ALBUMS[cat].circle}/${cat}/${song.slug}/`
}))
} }
})) }))
} }
@ -34,7 +38,7 @@ const album = ALBUMS[cat!];
<Base> <Base>
<main class="l-songs-cat"> <main class="l-songs-cat">
<article class="l-songs-cat__article"> <article class="l-songs-cat__article">
<Header title={`${cat} - ${album.title}`} /> <Header title={album.title} />
<div class="l-songs-cat__list"> <div class="l-songs-cat__list">
{songs.map(song => [ {songs.map(song => [
<span>{song.frontmatter.album[cat!].track}</span> <span>{song.frontmatter.album[cat!].track}</span>

View file

@ -1,15 +1,18 @@
--- ---
import Base from "../../layouts/Base.astro"; import Base from "@layouts/Base.astro";
import Song from "../../components/markdown/Song.astro"; import Song from "@components/markdown/Song.astro";
import Lyrics from "../../components/markdown/Lyrics.astro"; import Lyrics from "@components/markdown/Lyrics.astro";
import { CollectionEntry, getCollection } from "astro:content"; import { CollectionEntry, getCollection } from "astro:content";
import { ALBUMS } from "../../utils/songs/data"; import { ALBUMS } from "@utils/songs/data";
export async function getStaticPaths() { export async function getStaticPaths() {
return (await getCollection('songs')) return (await getCollection('songs'))
.map(song => Object.keys(song.data.album) .map(song => Object.keys(song.data.album)
.map(cat => ({ params: {slug: `${cat}/${song.slug}`}, props: {song, cat} }))) .map(cat => ({
params: { circle: ALBUMS[cat].circle, cat, song: song.slug},
props: { song, cat }
})))
.flat() .flat()
} }

View file

@ -1,16 +1,11 @@
--- ---
import List from "../../layouts/List.astro"; import List from "../../layouts/List.astro";
import { getCollection } from 'astro:content'; import { CIRCLES } from "../../utils/songs/data";
import { ALBUMS, getAllCats } from "../../utils/songs/data";
const pages = [...getAllCats(await getCollection('songs'))] const pages = Object.keys(CIRCLES)
.sort((a, b) => a < b ? 1 : -1) .map(slug => ({ title: CIRCLES[slug].name, slug: `/songs/${slug}/` }))
.map(catalog => ({ .sort((a, b) => a.title < b.title ? -1 : 1)
title: `${catalog} - ${ALBUMS[catalog].title}`,
slug: `/songs/${catalog}/`
}));
--- ---
<List title="Albums" pages={pages} /> <List title="Circles" pages={pages}/>

5
src/schema.d.ts vendored
View file

@ -1,9 +1,10 @@
/** @file src/data/circles.json */ /** @file src/data/circles.json */
interface CirclesSchema { interface CirclesSchema {
/** Circle name */ /** slug */
[key: string]: { [key: string]: {
name: string,
albums: { albums: {
/** Catalog number */ /** catalog number */
[key: string]: { [key: string]: {
title: string; title: string;
cover: string; cover: string;

View file

@ -0,0 +1,16 @@
.c-album {
padding: 0.5em;
background-color: white;
border-radius: 0.5em;
box-shadow: var(--shadow-l);
transition: box-shadow ease-in-out 0.2s;
text-decoration: none;
&:hover {
box-shadow: var(--shadow-m);
}
&__image {
width: 16em;
}
}

View file

@ -1,3 +1,14 @@
.l-album-grid {
display: flex;
flex-wrap: wrap;
gap: 2em;
&__item img {
width: 20em;
height: 20em;
}
}
.l-songs-cat { .l-songs-cat {
padding: 1.5em; padding: 1.5em;

View file

@ -11,6 +11,7 @@
@use 'components/tab'; @use 'components/tab';
@use 'components/lyrics'; @use 'components/lyrics';
@use 'components/song'; @use 'components/song';
@use 'components/album';
// Partials // Partials
@use 'partials/nav'; @use 'partials/nav';

View file

@ -6,8 +6,10 @@ type Song = CollectionEntry<'songs'>;
interface Metadata { interface Metadata {
[key: string]: { [key: string]: {
/** Circle slug */
circle: string;
/** Circle name */ /** Circle name */
circle: string, name: string,
/** Album title */ /** Album title */
title: string, title: string,
/** Path to album cover image */ /** Path to album cover image */
@ -16,6 +18,10 @@ interface Metadata {
} }
export function order(cat: string) {
return (a: Song, b: Song) => a.data.album[cat].track < b.data.album[cat].track ? -1 : 1;
}
export function getAllCats(songs: Song[]): Set<string> { export function getAllCats(songs: Song[]): Set<string> {
return songs.reduce( return songs.reduce(
(cats, next) => ( (cats, next) => (
@ -32,10 +38,10 @@ function createMetadata(circles: CirclesSchema): Metadata {
for (const circle of Object.keys(circles)) { for (const circle of Object.keys(circles)) {
const data = circles[circle]; const data = circles[circle];
for (const cat of Object.keys(data.albums)) for (const cat of Object.keys(data.albums))
metadata[cat] = { circle, ...data.albums[cat] } metadata[cat] = { circle, name: data.name, ...data.albums[cat] }
} }
return metadata; return metadata;
} }
export const CIRCLES: CirclesSchema = circles;
export const ALBUMS: Metadata = createMetadata(circles); export const ALBUMS: Metadata = createMetadata(circles);

View file

@ -15,6 +15,7 @@ function increaseStack(data: Stack, lang: string) {
function fromMarkdown(markdown: string): Stack { function fromMarkdown(markdown: string): Stack {
const stack: Stack = {}; const stack: Stack = {};
if (!markdown) return stack;
let space = true; let space = true;
let lang = ''; let lang = '';

View file

@ -3,6 +3,12 @@
"compilerOptions": { "compilerOptions": {
"allowJs": true, "allowJs": true,
"jsx": "preserve", "jsx": "preserve",
"jsxImportSource": "solid-js" "jsxImportSource": "solid-js",
"baseUrl": "src",
"paths": {
"@layouts/*": ["layouts/*"],
"@components/*": ["components/*"],
"@utils/*": ["utils/*"],
} }
},
} }