summaryrefslogtreecommitdiff
path: root/contrib/playlib/src/mill/playlib/Static.scala
blob: a9289c56e3742e65ac247d3f0639fd5b7579ec6c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
package mill.playlib

import java.net.URI
import java.nio.file._
import java.nio.file.attribute.BasicFileAttributes
import java.util

import mill.{PathRef, T}
import mill.scalalib.{Lib, ScalaModule}

trait Static extends ScalaModule {
  /**
    * project resources including configuration, webjars and static assets
    */
  override def resources = T.sources {
    super.resources() :+ webJarResources() :+ staticAssets()
  }

  /**
    * Resource base path of packaged assets (path they will appear in in the jar)
    */
  def assetsPath = T{ "public" }

  /**
    *  Directories to include assets from
    */
  def assetSources = T.sources{ millSourcePath / assetsPath() }

  /*
  Collected static assets for the project
   */
  def staticAssets = T {
    val toPath = os.Path(assetsPath(), T.ctx().dest)
    assetSources().foreach{ pathRef =>
      val fromPath = pathRef.path
      if (os.isDir(fromPath)) {
        os.walk(fromPath).filter(os.isFile(_)).foreach{ p =>
          os.copy(p, toPath / p.relativeTo(fromPath), createFolders = true)
        }
      }
    }
    PathRef(T.ctx().dest)
  }

  /**
    * webjar dependencies - created from transitive ivy deps
    */
  def webJarDeps = T{
    transitiveIvyDeps().filter(_.dep.module.organization.value == "org.webjars")
  }

  /**
    * jar files of web jars
    */
  def webJars = T{
    Lib.resolveDependencies(repositories, Lib.depToDependency(_, scalaVersion()), webJarDeps())
  }

  /**
    * webjar resources extracted from their source jars with version from path removed
    */
  def webJarResources = T {
    extractWebJars(webJars().toSeq, os.Path(assetsPath(), T.ctx().dest) / 'lib)
    PathRef(T.ctx().dest)
  }

  private def extractWebJars(jars: Seq[PathRef], webJarBase: os.Path): Unit = {
    import scala.collection.JavaConverters._
    val prefix = "/META-INF/resources/webjars/"

    jars.foreach{ jarRef =>
      val uri = s"jar:file:${jarRef.path}"
      val env = Map.empty[String,String].asJava

      val zipFs = FileSystems.newFileSystem(URI.create(uri), env)
      try {
        for(root <- zipFs.getRootDirectories.asScala) {
          Files.walkFileTree(root, util.EnumSet.noneOf(classOf[FileVisitOption]), Int.MaxValue,
            new SimpleFileVisitor[Path] {
              override def visitFile(file: Path, attrs: BasicFileAttributes) = {
                if (file.startsWith(prefix)) {
                  val rel = os.RelPath(file.toString.substring(prefix.length))
                  val toFile = webJarBase / os.RelPath(rel.segments(0) +: rel.segments.drop(2), 0)
                  //println(s"$file -> $toFile")
                  os.makeDir.all(toFile / os.up)
                  Files.copy(file, toFile.toNIO)
                }
                FileVisitResult.CONTINUE
              }
            }
          )
        }
      }
      finally {
        zipFs.close()
      }
    }
  }
}