docspell/project/StylesPlugin.scala

133 lines
4.0 KiB
Scala
Raw Normal View History

2021-01-29 19:44:36 +00:00
package docspell.build
import sbt._
import sbt.Keys._
import scala.sys.process._
/** Integrates the tailwind build into sbt.
*
2021-08-19 06:50:30 +00:00
* It assumes the required config (postcss.conf.js, tailwind.config.js) files in the base
* directory. It requires to have nodejs installed and the npx command available (or
2021-01-29 19:44:36 +00:00
* configured).
*/
object StylesPlugin extends AutoPlugin {
object autoImport {
sealed trait StylesMode
object StylesMode {
case object Prod extends StylesMode
2021-09-22 15:23:24 +00:00
case object Dev extends StylesMode
2021-01-29 19:44:36 +00:00
}
2021-09-22 15:23:24 +00:00
val stylesDirectory = settingKey[File]("The directory containing source styles")
val stylesOutputDir = settingKey[File]("The directory to put the final outcome")
val stylesMode = settingKey[StylesMode]("The compile mode, dev or production")
2024-03-10 19:13:41 +00:00
val stylesTwCommand = settingKey[String]("The tailwindcss executable")
2021-01-29 19:44:36 +00:00
val stylesNpmCommand =
settingKey[String]("The npm executable for installing dependencies")
val stylesBuild = taskKey[Seq[File]](
"Build the css without minifying and purging."
)
val stylesInstall = taskKey[Unit]("Run npm install to install dependencies")
}
import autoImport._
def stylesSettings: Seq[Setting[_]] =
Seq(
stylesDirectory := (Compile / sourceDirectory).value / "styles",
stylesOutputDir := (Compile / resourceManaged).value /
"META-INF" / "resources" / "webjars" / name.value / version.value,
2024-03-10 19:13:41 +00:00
stylesTwCommand := "tailwindcss",
2021-01-29 19:44:36 +00:00
stylesNpmCommand := "npm",
2021-09-22 15:23:24 +00:00
stylesMode := StylesMode.Dev,
2021-01-29 19:44:36 +00:00
stylesBuild := {
val logger = streams.value.log
2024-03-10 19:13:41 +00:00
val tw = stylesTwCommand.value
2021-09-22 15:23:24 +00:00
val npm = stylesNpmCommand.value
val inDir = stylesDirectory.value
2021-01-29 19:44:36 +00:00
val outDir = stylesOutputDir.value
2021-09-22 15:23:24 +00:00
val wd = (Compile / baseDirectory).value
val mode = stylesMode.value
2021-01-29 19:44:36 +00:00
npmInstall(npm, wd, logger)
2024-03-10 19:13:41 +00:00
val files = runTailwind(tw, inDir, outDir, wd, mode, logger) ++
2021-03-26 21:16:10 +00:00
copyWebfonts(wd, outDir, logger) ++
copyFlags(wd, outDir, logger)
2021-10-24 12:45:03 +00:00
logger.info(s"Styles built at $outDir")
2021-01-29 19:44:36 +00:00
files
},
stylesInstall := {
val logger = streams.value.log
2021-09-22 15:23:24 +00:00
val npm = stylesNpmCommand.value
val wd = (LocalRootProject / baseDirectory).value
2021-01-29 19:44:36 +00:00
npmInstall(npm, wd, logger)
}
)
override def projectSettings: Seq[Setting[_]] =
stylesSettings
def npmInstall(npm: String, wd: File, logger: Logger): Unit = {
val modulesDir = wd / "node_modules"
if (!modulesDir.exists) {
logger.info("Running npm install …")
Cmd.run(Seq(npm, "install"), wd, logger)
}
}
2024-03-10 19:13:41 +00:00
def runTailwind(
tailwind: String,
2021-01-29 19:44:36 +00:00
inDir: File,
outDir: File,
wd: File,
mode: StylesMode,
logger: Logger
): Seq[File] = {
val env = mode match {
2024-03-10 19:13:41 +00:00
case StylesMode.Dev => Seq.empty
case StylesMode.Prod => Seq("--minify")
2021-01-29 19:44:36 +00:00
}
val target = outDir / "css" / "styles.css"
IO.createDirectory(target.getParentFile)
logger.info("Compiling css stylesheets…")
2024-03-10 19:13:41 +00:00
val cmd = Seq(
tailwind,
"--input",
s"$inDir/index.css",
"-o",
target.absolutePath
) ++ env
Cmd.run(cmd, wd, logger)
2021-01-29 19:44:36 +00:00
val gz = file(target.toString + ".gz")
IO.gzip(target, gz)
Seq(target, gz)
}
def copyWebfonts(baseDir: File, outDir: File, logger: Logger): Seq[File] = {
val fontDir =
baseDir / "node_modules" / "@fortawesome" / "fontawesome-free" / "webfonts"
val targetDir = outDir / "webfonts"
IO.createDirectory(targetDir)
IO.copy(fontDir.listFiles().map(f => f -> targetDir / f.name).toSeq)
IO.listFiles(targetDir).toSeq
}
2021-03-26 21:16:10 +00:00
def copyFlags(baseDir: File, outDir: File, logger: Logger): Seq[File] = {
val flagDir =
2024-03-10 19:13:41 +00:00
baseDir / "node_modules" / "flag-icons" / "flags"
2021-03-26 21:16:10 +00:00
val targetDir = outDir / "flags"
IO.createDirectory(targetDir)
val files = (flagDir ** "*")
.filter(_.isFile)
.get
.pair(Path.relativeTo(flagDir))
.map(t => (t._1, targetDir / t._2))
IO.copy(files)
(targetDir ** "*.svg").get()
}
2021-01-29 19:44:36 +00:00
}