Setup tailwind with docspell build

This commit is contained in:
Eike Kettner 2021-01-29 20:44:36 +01:00
parent b3075cc6dc
commit 442b76c5af
7 changed files with 2965 additions and 3 deletions

View File

@ -59,7 +59,7 @@ lazy val noPublish = Seq(
val elmSettings = Seq(
elmCompileMode := ElmCompileMode.Debug,
Compile / resourceGenerators += Def.task {
openapiCodegen.value
val _ = openapiCodegen.value
compileElm(
streams.value.log,
(Compile / baseDirectory).value,
@ -75,6 +75,10 @@ val elmSettings = Seq(
HiddenFileFilter
)
)
val stylesSettings = Seq(
stylesMode := StylesMode.Dev,
Compile / resourceGenerators += stylesBuild.taskValue
)
val webjarSettings = Seq(
Compile / resourceGenerators += Def.task {
@ -406,9 +410,10 @@ val backend = project
val webapp = project
.in(file("modules/webapp"))
.disablePlugins(RevolverPlugin)
.enablePlugins(OpenApiSchema)
.enablePlugins(OpenApiSchema, StylesPlugin)
.settings(sharedSettings)
.settings(elmSettings)
.settings(stylesSettings)
.settings(webjarSettings)
.settings(
name := "docspell-webapp",
@ -717,7 +722,7 @@ def packageTools(logger: Logger, dir: File, version: String): Seq[File] = {
addCommandAlias(
"make",
";set webapp/elmCompileMode := ElmCompileMode.Production ;root/openapiCodegen ;root/test:compile"
";set webapp/elmCompileMode := ElmCompileMode.Production; set webapp/stylesMode := StylesMode.Prod ;root/openapiCodegen ;root/test:compile"
)
addCommandAlias("make-zip", ";restserver/universal:packageBin ;joex/universal:packageBin")
addCommandAlias("make-deb", ";restserver/debian:packageBin ;joex/debian:packageBin")

View File

@ -0,0 +1,70 @@
@import "@fortawesome/fontawesome-free/css/all";
/* all @import must be above this line */
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer components {
.label {
@apply flex flex-row items-center px-2 py-0.5 rounded border ;
}
.button {
@apply py-2 px-4 bg-blue-500 font-semibold rounded-lg shadow-md focus:outline-none focus:ring-2 focus:ring-opacity-75;
}
}
@layer utilities {
.h-screen-10 {
height: calc(100vh - 2.5rem);
}
.h-screen-11 {
height: calc(100vh - 2.75rem);
}
.h-screen-12 {
height: calc(100vh - 3rem);
}
.h-full-10 {
height: calc(100% - 2.5rem);
}
.h-full-11 {
height: calc(100% - 2.75rem);
}
.h-full-12 {
height: calc(100% - 3rem);
}
.scrollbar-none {
scrollbar-width: none;
}
.tag::before {
position: absolute;
transform: translateY(-50%) translateX(50%) rotate(-45deg);
top: 50%;
right: 100%;
content: '';
background-color: inherit;
background-image: none;
border-color: inherit;
width: 1.2em;
height: 1.2em;
border-radius: 4px;
}
.tag::after {
position: absolute;
content: '';
top: 50%;
left: -.25em;
margin-top: -.25em;
background-color: #fff;
width: .4em;
height: .4em;
box-shadow: 0 -1px 1px 0 rgba(0,0,0,.3);
border-radius: 500rem;
}
}

2701
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

14
package.json Normal file
View File

@ -0,0 +1,14 @@
{
"name": "docspell-css",
"version": "1.0.0",
"private": true,
"dependencies": {
"@fortawesome/fontawesome-free": "^5.15.2",
"autoprefixer": "^10.2.4",
"cssnano": "^4.1.10",
"postcss": "^8.2.4",
"postcss-cli": "^8.3.1",
"postcss-import": "^14.0.0",
"tailwindcss": "^2.0.2"
}
}

30
postcss.config.js Normal file
View File

@ -0,0 +1,30 @@
//postcss.config.js
const tailwindcss = require("tailwindcss");
const devPlugins =
[
require('postcss-import'),
tailwindcss("./tailwind.config.js"),
require("autoprefixer")
];
const prodPlugins =
[
require('postcss-import'),
tailwindcss("./tailwind.config.js"),
require("autoprefixer"),
require("@fullhuman/postcss-purgecss")({
content: [
"./modules/webapp/src/main/elm/**/*.elm",
"./modules/restserver/src/main/templates/*.html"
],
defaultExtractor: content => content.match(/[A-Za-z0-9-_:/\.]+/g) || []
}),
require('cssnano')({
preset: 'default'
})
]
module.exports = (ctx) => ({
plugins: ctx.env === 'production' ? prodPlugins : devPlugins
});

121
project/StylesPlugin.scala Normal file
View File

@ -0,0 +1,121 @@
package docspell.build
import sbt._
import sbt.Keys._
import scala.sys.process._
/** Integrates the tailwind build into sbt.
*
* 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
* configured).
*/
object StylesPlugin extends AutoPlugin {
object autoImport {
sealed trait StylesMode
object StylesMode {
case object Prod extends StylesMode
case object Dev extends StylesMode
}
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")
val stylesNpxCommand = settingKey[String]("The npx executable")
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,
stylesNpxCommand := "npx",
stylesNpmCommand := "npm",
stylesMode := StylesMode.Dev,
stylesBuild := {
val logger = streams.value.log
val npx = stylesNpxCommand.value
val npm = stylesNpmCommand.value
val inDir = stylesDirectory.value
val outDir = stylesOutputDir.value
val wd = (LocalRootProject / baseDirectory).value
val mode = stylesMode.value
npmInstall(npm, wd, logger)
val files = postCss(npx, inDir, outDir, wd, mode, logger) ++
copyWebfonts(wd, outDir, logger)
logger.info("Styles built")
files
},
stylesInstall := {
val logger = streams.value.log
val npm = stylesNpmCommand.value
val wd = (LocalRootProject / baseDirectory).value
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)
}
}
def postCss(
npx: String,
inDir: File,
outDir: File,
wd: File,
mode: StylesMode,
logger: Logger
): Seq[File] = {
val env = mode match {
case StylesMode.Dev => "development"
case StylesMode.Prod => "production"
}
val target = outDir / "css" / "styles.css"
IO.createDirectory(target.getParentFile)
logger.info("Compiling css stylesheets…")
Cmd.run(
Seq(
npx,
"postcss",
s"${inDir}/*.css",
"-o",
target.absolutePath,
"--env",
env
),
wd,
logger
)
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
}
}

21
tailwind.config.js Normal file
View File

@ -0,0 +1,21 @@
// tailwind.config.js
const colors = require('tailwindcss/colors')
module.exports = {
purge: false,
darkMode: 'class', // or 'media' or 'class'
theme: {
extend: {
colors: {
bluegray: colors.blueGray,
amber: colors.amber,
teal: colors.teal
}
}
},
variants: {},
plugins: [
]
// prefix: 'tw-'
}