Use markdoc for songs, basic list pages

This commit is contained in:
Maciej Jur 2023-04-26 21:36:34 +02:00
parent b67105736e
commit 8cddb5706e
13 changed files with 170 additions and 68 deletions

View file

@ -5,6 +5,7 @@ import remarkEmoji from 'remark-emoji';
import mdx from '@astrojs/mdx';
import remarkRuby from './src/assets/ruby';
import solid from '@astrojs/solid-js';
import markdoc from '@astrojs/markdoc';
// https://astro.build/config
@ -26,6 +27,7 @@ export default defineConfig({
},
integrations: [
mdx(),
solid()
solid(),
markdoc(undefined),
],
});

14
markdoc.config.mjs Normal file
View file

@ -0,0 +1,14 @@
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

@ -10,6 +10,7 @@
"astro": "astro"
},
"dependencies": {
"@astrojs/markdoc": "^0.1.1",
"@astrojs/mdx": "^0.19.0",
"@astrojs/solid-js": "^2.1.0",
"astro": "^2.3.1",

View file

@ -1,6 +1,9 @@
lockfileVersion: '6.0'
dependencies:
'@astrojs/markdoc':
specifier: ^0.1.1
version: 0.1.1(astro@2.3.1)
'@astrojs/mdx':
specifier: ^0.19.0
version: 0.19.0(astro@2.3.1)(rollup@3.21.0)
@ -118,6 +121,23 @@ packages:
vscode-uri: 3.0.7
dev: false
/@astrojs/markdoc@0.1.1(astro@2.3.1):
resolution: {integrity: sha512-NJgMTZWTCcL+4qmDim/wi53Mc6X7hk12hyI3JHWW7oiWVchdrvbdvG5i3c2bmT73+bMtG8XOEt2vvapQRixAKw==}
engines: {node: '>=16.12.0'}
peerDependencies:
astro: ^2.2.0
dependencies:
'@markdoc/markdoc': 0.2.2
astro: 2.3.1(sass@1.62.1)
esbuild: 0.17.18
gray-matter: 4.0.3
kleur: 4.1.5
zod: 3.21.4
transitivePeerDependencies:
- '@types/react'
- react
dev: false
/@astrojs/markdown-remark@2.1.4(astro@2.3.1):
resolution: {integrity: sha512-z5diCcFo2xkBAJ11KySAIKpZZkULZmzUvWsZ2VWIOrR6QrEgEfVl5jTpgPSedx4m+xUPuemlUviOotGB7ItNsQ==}
peerDependencies:
@ -702,6 +722,21 @@ packages:
resolution: {integrity: sha512-4/RWEeXDO6bocPONheFe6gX/oQdP/bEpv0oL4HqjPP5DCenBSt0mHgahppY49N0CpsaqffdwPq+TlX9CYOq2Dw==}
dev: false
/@markdoc/markdoc@0.2.2:
resolution: {integrity: sha512-0TiD9jmA5h5znN4lxo7HECAu3WieU5g5vUsfByeucrdR/x88hEilpt16EydFyJwJddQ/3w5HQgW7Ovy62r4cyw==}
engines: {node: '>=14.7.0'}
peerDependencies:
'@types/react': '*'
react: '*'
peerDependenciesMeta:
'@types/react':
optional: true
react:
optional: true
optionalDependencies:
'@types/markdown-it': 12.2.3
dev: false
/@mdx-js/mdx@2.3.0:
resolution: {integrity: sha512-jLuwRlz8DQfQNiUCJR50Y09CGPq3fLtmtUQfVrj79E0JWu3dvsVcxVIcfhR5h0iXu+/z++zDrYeiJqifRynJkA==}
dependencies:
@ -873,16 +908,35 @@ packages:
'@types/geojson': 7946.0.10
dev: true
/@types/linkify-it@3.0.2:
resolution: {integrity: sha512-HZQYqbiFVWufzCwexrvh694SOim8z2d+xJl5UNamcvQFejLY/2YUtzXHYi3cHdI7PMlS8ejH2slRAOJQ32aNbA==}
dev: false
optional: true
/@types/lunr@2.3.4:
resolution: {integrity: sha512-j4x4XJwZvorEUbA519VdQ5b9AOU9TSvfi8tvxMAfP8XzNLtFex7A8vFQwqOx3WACbV0KMXbACV3cZl4/gynQ7g==}
dev: true
/@types/markdown-it@12.2.3:
resolution: {integrity: sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==}
requiresBuild: true
dependencies:
'@types/linkify-it': 3.0.2
'@types/mdurl': 1.0.2
dev: false
optional: true
/@types/mdast@3.0.11:
resolution: {integrity: sha512-Y/uImid8aAwrEA24/1tcRZwpxX3pIFTSilcNDKSPn+Y2iDywSEachzRuvgAYYLR3wpGXAsMbv5lvKLDZLeYPAw==}
dependencies:
'@types/unist': 2.0.6
dev: false
/@types/mdurl@1.0.2:
resolution: {integrity: sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA==}
dev: false
optional: true
/@types/mdx@2.0.4:
resolution: {integrity: sha512-qCYrNdpKwN6YO6FVnx+ulfqifKlE3lQGsNhvDaW9Oxzyob/cRLBJWow8GHBBD4NxQ7BVvtsATgLsX0vZAWmtrg==}
dev: false

View file

@ -30,11 +30,10 @@ function toStack(html: string): Stack {
nodes.reduce((lang, node) => {
switch (node.rawTagName) {
case 'h1': {
const lang: string = node.id.replace(/-.+/, '');
createVerse(stack, lang);
return lang;
return node.text;
}
case 'ul': {
createVerse(stack, lang);
const lines = extractLines(node.childNodes);
stack[lang].at(-1)!.push(...lines);
return lang;
@ -62,26 +61,6 @@ function reduceStack(stack: Stack): Verse[] {
return verses.reverse();
}
// function toHtml(verses: Verse[]): string {
// const keys = Object.keys(verses[0]);
// const head = keys.map(lang => `<th>${lang}</th>`);
// const rows = verses.map(verse =>
// `<tr>${keys.map(lang =>
// `<td>${verse[lang].map(line =>
// `<span>${line}</span><br/>`).join('')}
// </td>`).join('')}
// </tr>`
// )
// .join('');
// return [
// "<table>",
// `<tr>${head.join('')}</tr>`,
// rows,
// "</table>",
// ].join('');
// }
export function transform(html: string) {
return reduceStack(toStack(html));
}

View file

@ -25,5 +25,16 @@ export const collections = {
date: z.date(),
tags: z.array(z.string()).optional(),
})
}),
songs: defineCollection({
schema: z.object({
title: z.string(),
album: z.record(
z.string(),
z.object({
track: z.number()
})
)
})
})
}

View file

@ -0,0 +1,34 @@
---
title: Black Eyes
album:
ARCD0051:
track: 7
---
{% lyrics %}
# Japanese
- 瞬きをして 切り取る時間
- 何気なくても 大切な今を
- 忘れないで 居られるように
- いつか 頭の中
- 掻き消して しまっても
# Romaji
- Matataki wo shite kiritoru jikan
- Nanigenakutemo taisetsuna ima wo
- Wasurenaide irareru you ni
- Itsuka atama no naka
- Kakikeshite shimattemo
---
# Japanese
- 瞬きをして 焼き付ける空
- 永遠の折り 縁取らせたら
- 綺麗なまま 残されてく
- いつか 思い出して
- 色褪せて しまっても
# Romaji
- Matataki wo shite yakitsukeru sora
- Eien no ori fuchidorasetara
- Kireina mama nokosareteku
- Itsuka omoidashite
- Iroasete shimattemo
{% /lyrics %}

View file

@ -1,33 +0,0 @@
---
title: Black Eyes
---
import Lyrics from '../../components/lyrics/Lyrics.astro';
<Lyrics>
# Japanese
- 瞬きをして 切り取る時間
- 何気なくても 大切な今を
- 忘れないで 居られるように
- いつか 頭の中
- 掻き消して しまっても
# Romaji
- fddsfsaf
- fdsfadsf
- test
- test
---
# Japanese
- 瞬きをして 切り取る時間ff
- 何気なくても 大切な今を
- 忘れないで 居られるように
- いつか 頭の中
- 掻き消して しまっても
# Romaji
- fddsfsaf
- fdsfadsf
- test
- test
</Lyrics>

View file

@ -4,13 +4,15 @@ import { getCollection } from "astro:content";
export async function getStaticPaths() {
return (await getCollection('songs'))
.map(entry => ({params: {slug: entry.slug}, props: {entry}}));
.map(song => Object.keys(song.data.album)
.map(cat => ({ params: {slug: `${cat}/${song.slug}`}, props: {song} })))
.flat()
}
const { entry } = Astro.props;
const { Content } = await entry.render();
const { song } = Astro.props;
const { Content } = await song.render();
---
<Lyrics frontmatter={entry.data}>
<Lyrics frontmatter={song.data}>
<Content />
</Lyrics>

View file

@ -0,0 +1,24 @@
---
import List from "../../layouts/List.astro";
import { getCollection } from 'astro:content';
import { getAllCats } from "../../utils/songs";
export async function getStaticPaths() {
const songs = await getCollection('songs');
const cats = getAllCats(songs);
return [...cats].map(cat => ({
params: {cat},
props: {
songs: songs
.filter(entry => cat in entry.data.album)
.map(song => ({ title: song.data.title, slug: `/songs/${cat}/${song.slug}/` })) }
}))
}
const { cat } = Astro.params;
const { songs } = Astro.props;
---
<List title={cat!} pages={songs} />

View file

@ -1,14 +1,13 @@
---
import List from "../../layouts/List.astro";
import { getCollection } from 'astro:content';
import { getAllCats } from "../../utils/songs";
const posts = (await getCollection('songs'))
.sort((a, b) => a.data.date < b.data.date ? 1 : -1)
.map(entry => ({
title: entry.data.title,
slug: `/songs/${entry.slug}/`,
}))
const pages = [...getAllCats(await getCollection('songs'))]
.sort((a, b) => a < b ? 1 : -1)
.map(catalog => ({ title: catalog, slug: `/songs/${catalog}/` }));
---
<List title="Songs" pages={posts} />
<List title="Songs" pages={pages} />

15
src/utils/songs.ts Normal file
View file

@ -0,0 +1,15 @@
import type { CollectionEntry } from "astro:content";
type Song = CollectionEntry<'songs'>;
export function getAllCats(songs: Song[]): Set<string> {
return songs.reduce(
(cats, next) => (
Object.keys(next.data.album).forEach(cat => cats.add(cat)),
cats
),
new Set<string>()
);
}