Use markdoc for songs, basic list pages
This commit is contained in:
parent
b67105736e
commit
8cddb5706e
|
@ -5,6 +5,7 @@ import remarkEmoji from 'remark-emoji';
|
||||||
import mdx from '@astrojs/mdx';
|
import mdx from '@astrojs/mdx';
|
||||||
import remarkRuby from './src/assets/ruby';
|
import remarkRuby from './src/assets/ruby';
|
||||||
import solid from '@astrojs/solid-js';
|
import solid from '@astrojs/solid-js';
|
||||||
|
import markdoc from '@astrojs/markdoc';
|
||||||
|
|
||||||
|
|
||||||
// https://astro.build/config
|
// https://astro.build/config
|
||||||
|
@ -26,6 +27,7 @@ export default defineConfig({
|
||||||
},
|
},
|
||||||
integrations: [
|
integrations: [
|
||||||
mdx(),
|
mdx(),
|
||||||
solid()
|
solid(),
|
||||||
|
markdoc(undefined),
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
14
markdoc.config.mjs
Normal file
14
markdoc.config.mjs
Normal 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 },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
|
@ -10,6 +10,7 @@
|
||||||
"astro": "astro"
|
"astro": "astro"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@astrojs/markdoc": "^0.1.1",
|
||||||
"@astrojs/mdx": "^0.19.0",
|
"@astrojs/mdx": "^0.19.0",
|
||||||
"@astrojs/solid-js": "^2.1.0",
|
"@astrojs/solid-js": "^2.1.0",
|
||||||
"astro": "^2.3.1",
|
"astro": "^2.3.1",
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
lockfileVersion: '6.0'
|
lockfileVersion: '6.0'
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
|
'@astrojs/markdoc':
|
||||||
|
specifier: ^0.1.1
|
||||||
|
version: 0.1.1(astro@2.3.1)
|
||||||
'@astrojs/mdx':
|
'@astrojs/mdx':
|
||||||
specifier: ^0.19.0
|
specifier: ^0.19.0
|
||||||
version: 0.19.0(astro@2.3.1)(rollup@3.21.0)
|
version: 0.19.0(astro@2.3.1)(rollup@3.21.0)
|
||||||
|
@ -118,6 +121,23 @@ packages:
|
||||||
vscode-uri: 3.0.7
|
vscode-uri: 3.0.7
|
||||||
dev: false
|
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):
|
/@astrojs/markdown-remark@2.1.4(astro@2.3.1):
|
||||||
resolution: {integrity: sha512-z5diCcFo2xkBAJ11KySAIKpZZkULZmzUvWsZ2VWIOrR6QrEgEfVl5jTpgPSedx4m+xUPuemlUviOotGB7ItNsQ==}
|
resolution: {integrity: sha512-z5diCcFo2xkBAJ11KySAIKpZZkULZmzUvWsZ2VWIOrR6QrEgEfVl5jTpgPSedx4m+xUPuemlUviOotGB7ItNsQ==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
|
@ -702,6 +722,21 @@ packages:
|
||||||
resolution: {integrity: sha512-4/RWEeXDO6bocPONheFe6gX/oQdP/bEpv0oL4HqjPP5DCenBSt0mHgahppY49N0CpsaqffdwPq+TlX9CYOq2Dw==}
|
resolution: {integrity: sha512-4/RWEeXDO6bocPONheFe6gX/oQdP/bEpv0oL4HqjPP5DCenBSt0mHgahppY49N0CpsaqffdwPq+TlX9CYOq2Dw==}
|
||||||
dev: false
|
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:
|
/@mdx-js/mdx@2.3.0:
|
||||||
resolution: {integrity: sha512-jLuwRlz8DQfQNiUCJR50Y09CGPq3fLtmtUQfVrj79E0JWu3dvsVcxVIcfhR5h0iXu+/z++zDrYeiJqifRynJkA==}
|
resolution: {integrity: sha512-jLuwRlz8DQfQNiUCJR50Y09CGPq3fLtmtUQfVrj79E0JWu3dvsVcxVIcfhR5h0iXu+/z++zDrYeiJqifRynJkA==}
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -873,16 +908,35 @@ packages:
|
||||||
'@types/geojson': 7946.0.10
|
'@types/geojson': 7946.0.10
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/@types/linkify-it@3.0.2:
|
||||||
|
resolution: {integrity: sha512-HZQYqbiFVWufzCwexrvh694SOim8z2d+xJl5UNamcvQFejLY/2YUtzXHYi3cHdI7PMlS8ejH2slRAOJQ32aNbA==}
|
||||||
|
dev: false
|
||||||
|
optional: true
|
||||||
|
|
||||||
/@types/lunr@2.3.4:
|
/@types/lunr@2.3.4:
|
||||||
resolution: {integrity: sha512-j4x4XJwZvorEUbA519VdQ5b9AOU9TSvfi8tvxMAfP8XzNLtFex7A8vFQwqOx3WACbV0KMXbACV3cZl4/gynQ7g==}
|
resolution: {integrity: sha512-j4x4XJwZvorEUbA519VdQ5b9AOU9TSvfi8tvxMAfP8XzNLtFex7A8vFQwqOx3WACbV0KMXbACV3cZl4/gynQ7g==}
|
||||||
dev: true
|
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:
|
/@types/mdast@3.0.11:
|
||||||
resolution: {integrity: sha512-Y/uImid8aAwrEA24/1tcRZwpxX3pIFTSilcNDKSPn+Y2iDywSEachzRuvgAYYLR3wpGXAsMbv5lvKLDZLeYPAw==}
|
resolution: {integrity: sha512-Y/uImid8aAwrEA24/1tcRZwpxX3pIFTSilcNDKSPn+Y2iDywSEachzRuvgAYYLR3wpGXAsMbv5lvKLDZLeYPAw==}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/unist': 2.0.6
|
'@types/unist': 2.0.6
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/@types/mdurl@1.0.2:
|
||||||
|
resolution: {integrity: sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA==}
|
||||||
|
dev: false
|
||||||
|
optional: true
|
||||||
|
|
||||||
/@types/mdx@2.0.4:
|
/@types/mdx@2.0.4:
|
||||||
resolution: {integrity: sha512-qCYrNdpKwN6YO6FVnx+ulfqifKlE3lQGsNhvDaW9Oxzyob/cRLBJWow8GHBBD4NxQ7BVvtsATgLsX0vZAWmtrg==}
|
resolution: {integrity: sha512-qCYrNdpKwN6YO6FVnx+ulfqifKlE3lQGsNhvDaW9Oxzyob/cRLBJWow8GHBBD4NxQ7BVvtsATgLsX0vZAWmtrg==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
|
@ -30,11 +30,10 @@ function toStack(html: string): Stack {
|
||||||
nodes.reduce((lang, node) => {
|
nodes.reduce((lang, node) => {
|
||||||
switch (node.rawTagName) {
|
switch (node.rawTagName) {
|
||||||
case 'h1': {
|
case 'h1': {
|
||||||
const lang: string = node.id.replace(/-.+/, '');
|
return node.text;
|
||||||
createVerse(stack, lang);
|
|
||||||
return lang;
|
|
||||||
}
|
}
|
||||||
case 'ul': {
|
case 'ul': {
|
||||||
|
createVerse(stack, lang);
|
||||||
const lines = extractLines(node.childNodes);
|
const lines = extractLines(node.childNodes);
|
||||||
stack[lang].at(-1)!.push(...lines);
|
stack[lang].at(-1)!.push(...lines);
|
||||||
return lang;
|
return lang;
|
||||||
|
@ -62,26 +61,6 @@ function reduceStack(stack: Stack): Verse[] {
|
||||||
return verses.reverse();
|
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) {
|
export function transform(html: string) {
|
||||||
return reduceStack(toStack(html));
|
return reduceStack(toStack(html));
|
||||||
}
|
}
|
|
@ -25,5 +25,16 @@ export const collections = {
|
||||||
date: z.date(),
|
date: z.date(),
|
||||||
tags: z.array(z.string()).optional(),
|
tags: z.array(z.string()).optional(),
|
||||||
})
|
})
|
||||||
|
}),
|
||||||
|
songs: defineCollection({
|
||||||
|
schema: z.object({
|
||||||
|
title: z.string(),
|
||||||
|
album: z.record(
|
||||||
|
z.string(),
|
||||||
|
z.object({
|
||||||
|
track: z.number()
|
||||||
|
})
|
||||||
|
)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
34
src/content/songs/black-eyes.mdoc
Normal file
34
src/content/songs/black-eyes.mdoc
Normal 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 %}
|
|
@ -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>
|
|
|
@ -4,13 +4,15 @@ import { getCollection } from "astro:content";
|
||||||
|
|
||||||
export async function getStaticPaths() {
|
export async function getStaticPaths() {
|
||||||
return (await getCollection('songs'))
|
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 { song } = Astro.props;
|
||||||
const { Content } = await entry.render();
|
const { Content } = await song.render();
|
||||||
---
|
---
|
||||||
|
|
||||||
<Lyrics frontmatter={entry.data}>
|
<Lyrics frontmatter={song.data}>
|
||||||
<Content />
|
<Content />
|
||||||
</Lyrics>
|
</Lyrics>
|
||||||
|
|
24
src/pages/songs/[cat].astro
Normal file
24
src/pages/songs/[cat].astro
Normal 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} />
|
|
@ -1,14 +1,13 @@
|
||||||
---
|
---
|
||||||
import List from "../../layouts/List.astro";
|
import List from "../../layouts/List.astro";
|
||||||
import { getCollection } from 'astro:content';
|
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)
|
const pages = [...getAllCats(await getCollection('songs'))]
|
||||||
.map(entry => ({
|
.sort((a, b) => a < b ? 1 : -1)
|
||||||
title: entry.data.title,
|
.map(catalog => ({ title: catalog, slug: `/songs/${catalog}/` }));
|
||||||
slug: `/songs/${entry.slug}/`,
|
|
||||||
}))
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<List title="Songs" pages={posts} />
|
<List title="Songs" pages={pages} />
|
||||||
|
|
15
src/utils/songs.ts
Normal file
15
src/utils/songs.ts
Normal 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>()
|
||||||
|
);
|
||||||
|
}
|
Loading…
Reference in a new issue