Skip to content

Commit

Permalink
Merge pull request #529 from 47degrees/dep/scrimage-4
Browse files Browse the repository at this point in the history
Update scrimage to 4.x from 2.x & fix copying resources
  • Loading branch information
sloshy authored Jan 26, 2021
2 parents f26a61f + 20a7418 commit 289f229
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 78 deletions.
2 changes: 1 addition & 1 deletion build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ lazy val pluginSettings: Seq[Def.Setting[_]] = Seq(
"com.47deg" %% "github4s" % "0.24.0",
"net.jcazevedo" %% "moultingyaml" % "0.4.2",
"com.lihaoyi" %% "scalatags" % "0.9.3",
"com.sksamuel.scrimage" %% "scrimage-core" % "2.1.8",
"com.sksamuel.scrimage" %% "scrimage-scala" % "4.0.12",
"org.scalatestplus" %% "scalacheck-1-14" % "3.1.4.0" % Test
),
scriptedLaunchOpts ++= Seq(
Expand Down
8 changes: 4 additions & 4 deletions project/dependencies.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ unmanagedResourceDirectories in Compile +=
baseDirectory.in(ThisBuild).value.getParentFile / "src" / "main" / "resources"

libraryDependencies ++= Seq(
"com.47deg" %% "github4s" % "0.24.0",
"net.jcazevedo" %% "moultingyaml" % "0.4.2",
"com.lihaoyi" %% "scalatags" % "0.9.3",
"com.sksamuel.scrimage" %% "scrimage-core" % "2.1.8"
"com.47deg" %% "github4s" % "0.24.0",
"net.jcazevedo" %% "moultingyaml" % "0.4.2",
"com.lihaoyi" %% "scalatags" % "0.9.3",
"com.sksamuel.scrimage" %% "scrimage-scala" % "4.0.12"
)
67 changes: 24 additions & 43 deletions src/main/scala/microsites/ioops/FileWriter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,13 @@

package microsites.ioops

import java.io.{File, FileOutputStream}
import java.io.File
import java.net.URL
import java.nio.file.Files.{copy => fcopy}
import java.nio.file.Path
import java.nio.file.{FileSystem, Files, Path}
import java.nio.file.StandardCopyOption.REPLACE_EXISTING
import java.util.zip.ZipInputStream
import java.{util => ju}

import cats.instances.either._
import cats.instances.list._
import cats.syntax.either._
import cats.syntax.traverse._
import cats.implicits._
import microsites.Exceptions._
import syntax._

Expand Down Expand Up @@ -67,7 +63,7 @@ class FileWriter {

def safeCopy: Either[Throwable, Path] =
Either
.catchNonFatal(fcopy(input.toPath, output.toPath, REPLACE_EXISTING))
.catchNonFatal(Files.copy(input.toPath, output.toPath, REPLACE_EXISTING))

(for {
result <- createFile(output)
Expand All @@ -92,45 +88,30 @@ class FileWriter {
} yield paths
}

def copyJARResourcesTo(
jarUrl: URL,
output: String,
filter: String = ""
): Either[IOException, Unit] =
/** Copies files from an arbitrary FileSystem (dir, JAR, ZIP) defined at the listed URL */
def copyResourcesFromFileSystem(
fs: FileSystem,
outputPath: Path,
filters: List[String]
) = {
Either
.catchNonFatal {
output.fixPath.toFile.mkdir()

val zipIn = new ZipInputStream(jarUrl.openStream())

val buffer = new Array[Byte](1024)
Stream.continually(zipIn.getNextEntry).takeWhile(_ != null).foreach { entry =>
val newFile = IOUtils.file(output + File.separator + entry.getName)

(
entry.isDirectory,
!newFile.exists() &&
newFile.getAbsolutePath.startsWith(s"$output$filter")
) match {
case (true, true) => createDir(newFile)
case (true, _) =>
case (false, true) =>
createFile(newFile)

val fos = new FileOutputStream(newFile)

Stream.continually(zipIn.read(buffer)).takeWhile(_ != -1).foreach { count =>
fos.write(buffer, 0, count)
}

fos.close()
case _ =>
filters.foreach { filter =>
val fsPath = fs.getPath(filter)
if (Files.exists(fsPath)) {
Files.walk(fsPath).forEachOrdered { path =>
val dest = outputPath.resolve(path.toString.stripPrefix("/"))
try Option(dest.getParent()).foreach(Files.createDirectories(_))
finally Files.copy(path, dest, REPLACE_EXISTING)
}
}
}
}
.leftMap(e =>
IOException(s"Error copying resources from $jarUrl to directory $output", Some(e))
)
.leftMap { e =>
e.printStackTrace()
IOException(s"Error copying resources from JAR to directory $outputPath", Some(e))
}
}
}

object FileWriter extends FileWriter
98 changes: 68 additions & 30 deletions src/main/scala/microsites/util/MicrositeHelper.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,14 @@
package microsites.util

import java.io.File
import java.net.URL

import cats.syntax.either._
import com.sksamuel.scrimage._
import java.net.{URI, URL}
import java.nio.file.{FileSystem, FileSystems, Paths}
import java.util.HashMap

import cats.implicits._
import com.sksamuel.scrimage.nio.ImageReader
import com.sksamuel.scrimage.ImmutableImage
import com.sksamuel.scrimage.implicits._
import microsites.util.YamlFormats._
import microsites._
import microsites.layouts._
Expand Down Expand Up @@ -55,31 +59,52 @@ class MicrositeHelper(config: MicrositeSettings) {
MicrositeFavicon(filename, s"${width}x$height")
}

def copyJAROrFolder(
jarUrl: URL,
output: String,
filter: String = ""
): Either[Exceptions.IOException, Any] =
copyJARResourcesTo(jarUrl, output, filter)
.orElse(copyFilesRecursively(jarUrl.getFile + filter, output + filter))
def copyResources(
resourcesJarFSOrPath: Either[FileSystem, java.nio.file.Path],
outputPath: java.nio.file.Path,
filters: List[String]
): Either[Exceptions.IOException, Any] = resourcesJarFSOrPath match {
case Left(fs) =>
println(s"Copying resources from sbt-microsite JAR")
val result = copyResourcesFromFileSystem(fs, outputPath, filters)
fs.close()
result
case Right(path) =>
println(s"Copying resources from local path $path")
filters.traverse { filter =>
copyFilesRecursively(path.toString, outputPath.toString)
}
}

def createResources(resourceManagedDir: File): List[File] = {

val targetDir: String = resourceManagedDir.getAbsolutePath.ensureFinalSlash
val pluginURL: URL = getClass.getProtectionDomain.getCodeSource.getLocation

copyJAROrFolder(pluginURL, s"$targetDir$jekyllDir/", "_sass")
copyJAROrFolder(pluginURL, s"$targetDir$jekyllDir/", "css")
copyJAROrFolder(pluginURL, s"$targetDir$jekyllDir/", "img")
copyJAROrFolder(pluginURL, s"$targetDir$jekyllDir/", "js")
copyJAROrFolder(pluginURL, s"$targetDir$jekyllDir/", "highlight/highlight.pack.js")
copyJAROrFolder(pluginURL, s"$targetDir$jekyllDir/", "highlight/LICENSE")
copyJAROrFolder(
pluginURL,
s"$targetDir$jekyllDir/",
s"highlight/styles/${config.visualSettings.highlightTheme}.css"
val pluginPath = Paths.get(pluginURL.getPath)
val outputPath = Paths.get(s"$targetDir$jekyllDir/")

val filters = List(
"_sass",
"css",
"img",
"js",
"highlight/highlight.pack.js",
"highlight/LICENSE",
s"highlight/styles/${config.visualSettings.highlightTheme}.css",
"plugins"
)
copyJAROrFolder(pluginURL, s"$targetDir$jekyllDir/", "plugins")

//If resources are in a JAR, we want to expose that as a FileSystem
//Otherwise we will just use the raw path
val pathOrFS: Either[FileSystem, java.nio.file.Path] =
if (pluginPath.getFileName.toString.endsWith(".jar")) {
val uri = URI.create("jar:file:" + pluginPath.toString)
FileSystems.newFileSystem(uri, new HashMap[String, Any]()).asLeft
} else {
pluginPath.asRight
}

copyResources(pathOrFS, outputPath, filters)

copyFilesRecursively(
config.fileLocations.micrositeImgDirectory.getAbsolutePath,
Expand Down Expand Up @@ -229,13 +254,26 @@ class MicrositeHelper(config: MicrositeSettings) {

createFile(sourceFile)

(faviconFilenames zip faviconSizes)
.map { case (name, size) =>
(new File(s"$targetDir$jekyllDir/img/$name"), size)
}
.map { case (file, (width, height)) =>
Image.fromFile(sourceFile.toFile).scaleTo(width, height).output(file)
}
//This is a dirty classloader hack to allow the latest version of Scrimage to work.
//This plugin's default classloader is limited and cannot load ImageReader instances.
//We get a different ClassLoader that will work, replace it, and then set it back after we're done.
//Will be fixed in Scrimage 4.1.0, see: https://github.com/sksamuel/scrimage/issues/217
val desiredCL: ClassLoader = classOf[ImageReader].getClassLoader
val currentCL = Thread.currentThread.getContextClassLoader()

try {
Thread.currentThread.setContextClassLoader(desiredCL)

(faviconFilenames zip faviconSizes)
.map { case (name, size) =>
(new File(s"$targetDir$jekyllDir/img/$name"), size)
}
.map { case (file, (width, height)) =>
ImmutableImage.loader.fromFile(sourceFile.toFile).scaleTo(width, height).output(file)
}
} finally
//Reset the classloader to what it was previously
Thread.currentThread.setContextClassLoader(currentCL)
}

def copyConfigurationFile(sourceDir: File, targetDir: File): Unit = {
Expand Down

0 comments on commit 289f229

Please sign in to comment.