diff --git a/components/groovy/com/jessebrault/site/icon/ExternalIcon.groovy b/components/groovy/com/jessebrault/site/icon/ExternalIcon.groovy
new file mode 100644
index 0000000..4de4904
--- /dev/null
+++ b/components/groovy/com/jessebrault/site/icon/ExternalIcon.groovy
@@ -0,0 +1,17 @@
+package com.jessebrault.site.icon
+
+import com.jessebrault.ssg.view.SkipTemplate
+import groowt.view.View
+import groowt.view.component.web.lib.DelegatingWebViewComponent
+
+@SkipTemplate
+class ExternalIcon extends DelegatingWebViewComponent {
+
+ private static final String externalText = ExternalIcon.getResource('External.txt').text
+
+ @Override
+ protected View getDelegate() {
+ return { Writer w -> w << externalText }
+ }
+
+}
diff --git a/components/groovy/com/jessebrault/site/util/MaybeExternalLink.groovy b/components/groovy/com/jessebrault/site/util/MaybeExternalLink.groovy
new file mode 100644
index 0000000..497c922
--- /dev/null
+++ b/components/groovy/com/jessebrault/site/util/MaybeExternalLink.groovy
@@ -0,0 +1,21 @@
+package com.jessebrault.site.util
+
+import groowt.view.component.web.BaseWebViewComponent
+
+class MaybeExternalLink extends BaseWebViewComponent {
+
+ final String href
+
+ MaybeExternalLink(Map attr) {
+ href = attr.href
+ }
+
+ Object getLinkChildren() {
+ children
+ }
+
+ boolean getIsExternal() {
+ href.startsWith('https://')
+ }
+
+}
diff --git a/components/groovy/com/jessebrault/site/util/WhenExternal.groovy b/components/groovy/com/jessebrault/site/util/WhenExternal.groovy
new file mode 100644
index 0000000..da249ff
--- /dev/null
+++ b/components/groovy/com/jessebrault/site/util/WhenExternal.groovy
@@ -0,0 +1,29 @@
+package com.jessebrault.site.util
+
+import com.jessebrault.ssg.view.SkipTemplate
+import groowt.view.View
+import groowt.view.component.runtime.DefaultComponentWriter
+import groowt.view.component.web.lib.DelegatingWebViewComponent
+
+@SkipTemplate
+class WhenExternal extends DelegatingWebViewComponent {
+
+ private final String href
+ private final Closure render
+
+ WhenExternal(Map attr) {
+ href = attr.href
+ render = attr.render
+ }
+
+ @Override
+ protected View getDelegate() {
+ return { Writer w ->
+ if (href.startsWith('https://')) {
+ def cw = new DefaultComponentWriter(w, context.renderContext, context)
+ cw << render.call()
+ }
+ }
+ }
+
+}
diff --git a/components/resources/com/jessebrault/site/icon/External.txt b/components/resources/com/jessebrault/site/icon/External.txt
new file mode 100644
index 0000000..c477d91
--- /dev/null
+++ b/components/resources/com/jessebrault/site/icon/External.txt
@@ -0,0 +1,2 @@
+
+
diff --git a/components/resources/com/jessebrault/site/util/MaybeExternalLinkTemplate.wvc b/components/resources/com/jessebrault/site/util/MaybeExternalLinkTemplate.wvc
new file mode 100644
index 0000000..10572b1
--- /dev/null
+++ b/components/resources/com/jessebrault/site/util/MaybeExternalLinkTemplate.wvc
@@ -0,0 +1,11 @@
+---
+package com.jessebrault.site.util
+
+import com.jessebrault.site.icon.ExternalIcon
+---
+
+
+ <% children -> children.addAll(linkChildren) %>
+ } />
+
+
diff --git a/pages/resources/com/jessebrault/site/composition/CompositionPageTemplate.wvc b/pages/resources/com/jessebrault/site/composition/CompositionPageTemplate.wvc
index de06eb7..7b98ccc 100644
--- a/pages/resources/com/jessebrault/site/composition/CompositionPageTemplate.wvc
+++ b/pages/resources/com/jessebrault/site/composition/CompositionPageTemplate.wvc
@@ -2,6 +2,7 @@
package com.jessebrault.site.composition
import com.jessebrault.site.StandardPage
+import com.jessebrault.site.util.MaybeExternalLink
---
@@ -17,11 +18,37 @@ import com.jessebrault.site.StandardPage
$it
} />
$composition.instrumentation
+ Premiere: $it} />
+
+
+
+
+
+
-
Alternate versions:
+
Alternate versions:
diff --git a/src/main/groovy/com/jessebrault/site/composition/Composition.groovy b/src/main/groovy/com/jessebrault/site/composition/Composition.groovy
index ba62813..99f190b 100644
--- a/src/main/groovy/com/jessebrault/site/composition/Composition.groovy
+++ b/src/main/groovy/com/jessebrault/site/composition/Composition.groovy
@@ -16,6 +16,10 @@ class Composition {
@Nullable String subTitle
@Nullable String version
String instrumentation
+ @Nullable String premiere
+ @Nullable String pdfUrl
+ Map recordings
+ Map externalLinks
@Nullable String shortInfo
LocalDate date
Set categories
diff --git a/src/main/groovy/com/jessebrault/site/composition/CompositionContainer.groovy b/src/main/groovy/com/jessebrault/site/composition/CompositionContainer.groovy
index 6631f64..f0ec458 100644
--- a/src/main/groovy/com/jessebrault/site/composition/CompositionContainer.groovy
+++ b/src/main/groovy/com/jessebrault/site/composition/CompositionContainer.groovy
@@ -20,6 +20,10 @@ class CompositionContainer {
subTitle: text.frontMatter.subTitle,
version: text.frontMatter.version,
instrumentation: text.frontMatter.instrumentation,
+ premiere: text.frontMatter.premiere,
+ pdfUrl: text.frontMatter.pdfUrl,
+ recordings: text.frontMatter.recordings ?: [:],
+ externalLinks: text.frontMatter.externalLinks ?: [:],
shortInfo: text.frontMatter.shortInfo,
date: LocalDate.parse(text.frontMatter.date),
categories: text.frontMatter.categories as Set
diff --git a/static/main.css b/static/main.css
index 04fe7c1..b0789cb 100644
--- a/static/main.css
+++ b/static/main.css
@@ -306,16 +306,28 @@ article.compositions {
font-size: 1.5em;
}
-.composition-info .alternate-versions {
+.composition-info :is(.recordings, .external-links, .alternate-versions) {
display: flex;
flex-direction: column;
row-gap: 10px;
}
-.composition-info .alternate-versions ul {
+.composition-info :is(.recordings, .external-links, .alternate-versions) ul {
margin: 0;
}
+.composition-info :is(.recordings, .external-links, .alternate-versions) a span {
+ display: flex;
+ align-items: center;
+ column-gap: 5px;
+}
+
+.composition-info :is(.recordings, .external-links, .alternate-versions) span svg {
+ pointer-events: none;
+ height: 0.8em;
+ fill: var(--petrol);
+}
+
.composition-text p:first-child {
margin-block-start: 2em;
}
diff --git a/texts/compositions/Arcadia.md b/texts/compositions/Arcadia.md
index a0f94a0..578390b 100644
--- a/texts/compositions/Arcadia.md
+++ b/texts/compositions/Arcadia.md
@@ -2,6 +2,13 @@
title: Arcadia
slug: arcadia
instrumentation: For violin and piano.
+premiere: November 2, 2020. (Online)
+recordings:
+ Premiere: https://www.youtube.com/watch?v=pUx57krZ41E
+ Audio: /compositions/arcadia/arcadia.mp3
+externalLinks:
+ 'Musaics of the Bay': https://www.musaics.org/stayathomesymposium/20-arcadia
+ Discussion: https://www.youtube.com/watch?v=y52TU2u1BnU
shortInfo: 'Commissioned by Musaics of the Bay.'
date: 2020-10-01
categories: