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: [
mdx(),
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;
cat: string;
track: number;
circle: string;
name: string;
composer?: string;
lyrics?: string;
vocal?: string[];
@ -33,7 +33,7 @@ const { metadata } = Astro.props;
</tr>
<tr>
<td>Circle</td>
<td>{metadata.circle}</td>
<td>{metadata.name}</td>
</tr>
<tr>
<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"
origin:
- 亡き王女の為のセプテット
album:
ARCD0054:
track: 7
vocal:
- nomico
---
# Japanese

View file

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

View file

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

View file

@ -1,5 +1,6 @@
{
"Alstroemeria Records": {
"alstroemeria-records": {
"name": "Alstroemeria Records",
"albums": {
"ARCD0051": {
"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 Header from '../../components/headers/Base.astro';
import Base from "@layouts/Base.astro";
import Header from '@components/headers/Base.astro';
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() {
@ -10,11 +10,15 @@ export async function getStaticPaths() {
const cats = getAllCats(songs);
return [...cats].map(cat => ({
params: {cat},
params: { circle: ALBUMS[cat].circle, cat },
props: {
songs: songs
.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>
<main class="l-songs-cat">
<article class="l-songs-cat__article">
<Header title={`${cat} - ${album.title}`} />
<Header title={album.title} />
<div class="l-songs-cat__list">
{songs.map(song => [
<span>{song.frontmatter.album[cat!].track}</span>

View file

@ -1,15 +1,18 @@
---
import Base from "../../layouts/Base.astro";
import Song from "../../components/markdown/Song.astro";
import Lyrics from "../../components/markdown/Lyrics.astro";
import Base from "@layouts/Base.astro";
import Song from "@components/markdown/Song.astro";
import Lyrics from "@components/markdown/Lyrics.astro";
import { CollectionEntry, getCollection } from "astro:content";
import { ALBUMS } from "../../utils/songs/data";
import { ALBUMS } from "@utils/songs/data";
export async function getStaticPaths() {
return (await getCollection('songs'))
.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()
}

View file

@ -1,16 +1,11 @@
---
import List from "../../layouts/List.astro";
import { getCollection } from 'astro:content';
import { ALBUMS, getAllCats } from "../../utils/songs/data";
import { CIRCLES } from "../../utils/songs/data";
const pages = [...getAllCats(await getCollection('songs'))]
.sort((a, b) => a < b ? 1 : -1)
.map(catalog => ({
title: `${catalog} - ${ALBUMS[catalog].title}`,
slug: `/songs/${catalog}/`
}));
const pages = Object.keys(CIRCLES)
.map(slug => ({ title: CIRCLES[slug].name, slug: `/songs/${slug}/` }))
.sort((a, b) => a.title < b.title ? -1 : 1)
---
<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 */
interface CirclesSchema {
/** Circle name */
/** slug */
[key: string]: {
name: string,
albums: {
/** Catalog number */
/** catalog number */
[key: string]: {
title: 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 {
padding: 1.5em;

View file

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

View file

@ -6,8 +6,10 @@ type Song = CollectionEntry<'songs'>;
interface Metadata {
[key: string]: {
/** Circle slug */
circle: string;
/** Circle name */
circle: string,
name: string,
/** Album title */
title: string,
/** 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> {
return songs.reduce(
(cats, next) => (
@ -32,10 +38,10 @@ function createMetadata(circles: CirclesSchema): Metadata {
for (const circle of Object.keys(circles)) {
const data = circles[circle];
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;
}
export const CIRCLES: CirclesSchema = circles;
export const ALBUMS: Metadata = createMetadata(circles);

View file

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

View file

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