From c588c946b8d9d2a932a0cc7f5730a235bacb7d10 Mon Sep 17 00:00:00 2001 From: Andrew Valencik Date: Thu, 9 Apr 2026 08:59:18 -0400 Subject: [PATCH 1/2] Add WebJar class for accessing WebJar files --- build.scala | 48 ++++++++++++++++++++++++++++++++++++------------ 1 file changed, 36 insertions(+), 12 deletions(-) diff --git a/build.scala b/build.scala index 03f19da7..e665faa8 100644 --- a/build.scala +++ b/build.scala @@ -405,13 +405,9 @@ object LaikaCustomizations { } val Icons = { - def loadFaIcon(prefix: String, name: String) = { - val resourcePath = - "/META-INF/resources/webjars/fortawesome__fontawesome-free/7.2.0" - val inputStream = - getClass.getResourceAsStream(s"$resourcePath/svgs/$prefix/$name.svg") - String(inputStream.readAllBytes()) - } + val fa = WebJar("fortawesome__fontawesome-free") + def loadFaIcon(prefix: String, name: String) = + fa.load(s"svgs/$prefix/$name.svg") Map( // brands @@ -439,11 +435,9 @@ object KaTeX { import org.graalvm.polyglot.* import scala.jdk.CollectionConverters.* - private def loadKaTeX(): String = { - val resourcePath = "/META-INF/resources/webjars/katex/0.16.44/dist/katex.js" - val inputStream = getClass.getResourceAsStream(resourcePath) - String(inputStream.readAllBytes()) - } + private val katexJar = WebJar("katex") + + private def loadKaTeX(): String = katexJar.load("dist/katex.js") private lazy val katex = { val ctx = Context @@ -476,6 +470,36 @@ object KaTeX { } +// Provides access to resources of a bundled WebJar. +class WebJar(artifactId: String) { + private val version: String = + val propsPath = s"META-INF/maven/org.webjars.npm/$artifactId/pom.properties" + val stream = Thread + .currentThread() + .getContextClassLoader + .getResourceAsStream(propsPath) + if stream == null then + throw IllegalStateException( + s"Could not find pom.properties for webjar '$artifactId' on the classpath." + ) + val props = java.util.Properties() + props.load(stream) + props.getProperty("version") + + // Load a resource from this WebJar as a String, uses relative paths. + def load(path: String): String = + val resourcePath = s"META-INF/resources/webjars/$artifactId/$version/$path" + val stream = Thread + .currentThread() + .getContextClassLoader + .getResourceAsStream(resourcePath) + if stream == null then + throw IllegalStateException( + s"Could not find resource '$path' in webjar '$artifactId' ($version)." + ) + String(stream.readAllBytes()) +} + object Redirects { import laika.io.model.InputTree import laika.ast.Path.Root From 7f4153207ef03e11ca67ebea3efaa231e7855f21 Mon Sep 17 00:00:00 2001 From: Andrew Valencik Date: Fri, 10 Apr 2026 10:55:10 -0400 Subject: [PATCH 2/2] Make classLoader a property of WebJar --- build.scala | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/build.scala b/build.scala index e665faa8..f7cac4e4 100644 --- a/build.scala +++ b/build.scala @@ -472,12 +472,11 @@ object KaTeX { // Provides access to resources of a bundled WebJar. class WebJar(artifactId: String) { + private val classLoader = classOf[WebJar].getClassLoader + private val version: String = val propsPath = s"META-INF/maven/org.webjars.npm/$artifactId/pom.properties" - val stream = Thread - .currentThread() - .getContextClassLoader - .getResourceAsStream(propsPath) + val stream = classLoader.getResourceAsStream(propsPath) if stream == null then throw IllegalStateException( s"Could not find pom.properties for webjar '$artifactId' on the classpath." @@ -489,10 +488,7 @@ class WebJar(artifactId: String) { // Load a resource from this WebJar as a String, uses relative paths. def load(path: String): String = val resourcePath = s"META-INF/resources/webjars/$artifactId/$version/$path" - val stream = Thread - .currentThread() - .getContextClassLoader - .getResourceAsStream(resourcePath) + val stream = classLoader.getResourceAsStream(resourcePath) if stream == null then throw IllegalStateException( s"Could not find resource '$path' in webjar '$artifactId' ($version)."