This commit is contained in:
2021-08-15 08:36:23 +02:00
parent 1dc6f6cf9f
commit d4a8b18ec2
10 changed files with 272 additions and 55 deletions

View File

@@ -1,10 +1,10 @@
plugins {
kotlin("multiplatform") version "1.4.32"
kotlin("multiplatform") version "1.5.21"
`maven-publish`
}
group = "nl.astraeus"
version = "0.4.28"
version = "0.4.29-SNAPSHOT"
repositories {
maven { setUrl("https://dl.bintray.com/kotlin/kotlin-eap") }
@@ -73,11 +73,4 @@ publishing {
}
}
}
/*
publications {
val kotlinMultiplatform by getting {
artifactId = "kotlin-css-generator"
}
}
*/
}

View File

@@ -2,4 +2,4 @@ kotlin.code.style=official
kotlin.js.compiler=both
nexusUsername=deployment
nexusPassword=3p7pl4aenHNFqUhYBaRIlqH6lk
nexusPassword=

122
readme.md Normal file
View File

@@ -0,0 +1,122 @@
# Css generator like less/sass in kotlin multiplatform
This library is for generating css from a kotlin dsl.
It is meant to be used runtime to dynamically generate css.
Tools like less and sass are often used as a build step and take some time.
This library is meant to be fast enough to generate the css on the fly either from the server or directly in the browser.
Examples:
## Nesting / colors / variables
```kotlin
val color = hsla(0, 50, 50, 1.0)
val backgroundColor = Color.white
val css = style {
select(cls("button")) {
padding(5.px)
select("a") {
color(color)
backgroundColor(backgroundColor)
hover {
color(color.lighten(10))
backgroundColor(backgroundColor.darken(10))
}
}
}
}
```
Result:
```css
.button {
padding: 5px;
}
.button a {
color: hsla(0, 50%, 50%, 1.0);
background-color: white;
}
.button a:hover {
color: hsla(0, 50%, 55%, 1.0);
background-color: rgba(229, 229, 229, 1.0);
}
```
## Mixins
As it's just kotlin code includes, mixins etc. are just functions calls.
```kotlin
fun Style.borderStyles(borderWidth: Measurement = 2.px) {
borderWidth(borderWidth)
borderColor(Color.aquamarine)
borderStyle(BorderStyle.solid)
}
val css = style {
select(txt("a"), cls("button")) {
borderStyles()
color(Color.white)
}
select(cls("btn-primary")) {
borderStyles(3.px)
color(Color.blue)
}
}
```
Result:
```css
a {
border-width: 2px;
border-color: aquamarine;
border-style: solid;
color: white;
}
.button {
border-width: 2px;
border-color: aquamarine;
border-style: solid;
color: white;
}
.btn-primary {
border-width: 3px;
border-color: aquamarine;
border-style: solid;
color: blue;
}
```
# Measurements
Sizes and widths are given in measurements, there are extension variables to help with these:
```kotlin
select("body") {
fontSize(1.2.em)
borderWidth(3.px)
width(75.prc)
}
```
Result:
```css
body {
font-size: 1.2em;
border-width: 3px;
width: 75%;
}
```

View File

@@ -296,7 +296,8 @@ class Color(value: String) : CssProperty(value) {
}
}
if (saturation == 0) return RGBA(lightness, lightness, lightness)
val lightness255 = lightness * 255 / 100
if (saturation == 0) return RGBA(lightness255, lightness255, lightness255)
// scale H, S, V values into 0..1 fractions
val h = (hue % 360.0) / 360.0

View File

@@ -0,0 +1,6 @@
package nl.astraeus.css.style
data class CssBlock(
val selector: String,
val content: String
)

View File

@@ -78,6 +78,7 @@ abstract class CssGenerator {
warnOnRedeclaration: Boolean = true,
allowCommaInSelector: Boolean = false
): String {
val blocks = mutableListOf<CssBlock>()
val builder = StringBuilder()
for (name in definitions.keys) {
@@ -235,6 +236,7 @@ class ValueDescriptionProvider(
}
fun txt(name: String): DescriptionProvider = ValueDescriptionProvider(name)
fun id(name: String): DescriptionProvider = ValueDescriptionProvider("#$name")
fun cls(name: String): DescriptionProvider = ValueDescriptionProvider(".$name")
fun attr(name: String): DescriptionProvider = ValueDescriptionProvider("[$name]")
@@ -380,6 +382,10 @@ open class Style : CssGenerator() {
addStyle(":hover", style)
}
fun pseudo(selector: DescriptionProvider, style: Css) {
addStyle("::${selector.description()}", style)
}
fun visited(style: Css) {
addStyle(":visited", style)
}

View File

@@ -0,0 +1,43 @@
package nl.astraeus.css
import nl.astraeus.css.properties.Color
import nl.astraeus.css.style.DescriptionProvider
import kotlin.test.Test
private val CAPITAL_LETTER by lazy { Regex("[A-Z]") }
fun String.hyphenize(): String =
replace(CAPITAL_LETTER) {
"-${it.value.lowercase()}"
}
open class CssName(name: String? = null) : DescriptionProvider {
val name: String = if (name != null) {
"css-$name"
} else{
"css${this::class.simpleName?.hyphenize() ?: this::class}"
}
override fun description() = name
}
object MainTitle : CssName()
object SectionTitle : CssName("sct-title")
class CssNameExample {
@Test
fun testCssName() {
val css = style {
select(MainTitle) {
color(Color.white)
}
select(SectionTitle) {
color(Color.red)
}
}
println(css.generateCss())
}
}

View File

@@ -0,0 +1,78 @@
package nl.astraeus.css
import nl.astraeus.css.properties.BorderStyle
import nl.astraeus.css.properties.Color
import nl.astraeus.css.properties.Measurement
import nl.astraeus.css.properties.em
import nl.astraeus.css.properties.hsla
import nl.astraeus.css.properties.prc
import nl.astraeus.css.properties.px
import nl.astraeus.css.style.Style
import nl.astraeus.css.style.cls
import nl.astraeus.css.style.txt
import kotlin.test.Test
class Examples {
@Test
fun testColor() {
val color = hsla(0, 50, 50, 1.0)
val backgroundColor = Color.white
val css = style {
select(cls("button")) {
padding(5.px)
select("a") {
color(color)
backgroundColor(backgroundColor)
hover {
color(color.lighten(10))
backgroundColor(backgroundColor.darken(10))
}
}
}
}
println(css.generateCss())
}
@Test
fun testMixins() {
fun Style.borderStyles(borderWidth: Measurement = 2.px) {
borderWidth(borderWidth)
borderColor(Color.aquamarine)
borderStyle(BorderStyle.solid)
}
val css = style {
select(txt("a"), cls("button")) {
borderStyles()
color(Color.white)
}
select(cls("btn-primary")) {
borderStyles(3.px)
color(Color.blue)
}
}
println(css.generateCss())
}
@Test
fun testMeasurementss() {
val css = style {
select("body") {
fontSize(1.2.em)
borderWidth(3.px)
width(75.prc)
}
}
println(css.generateCss())
}
}

View File

@@ -180,27 +180,26 @@ class TestCssBuilder {
println(css.generateCss())
}
@Test
fun testOrWithComma() {
val css = style {
select("h1") {
color(Color.blue)
var excepted = false
try {
val css = style {
select("h1") {
color(Color.blue)
select("table") {
color(Color.red)
select("table") {
color(Color.red)
select("th, td") {
color(Color.green)
select("th, td") {
color(Color.green)
}
}
}
}
}
var excepted = false
try {
println(css.generateCss())
} catch(e: Exception) {
} catch (e: Exception) {
excepted = true
assertTrue {
e is IllegalStateException
@@ -214,9 +213,8 @@ class TestCssBuilder {
}
}
@Test
fun testAlhpaFunctions() {
fun testAlphaFunctions() {
val hsl = hsl(1, 50, 50)
val hsla = hsla(1, 50, 50, 0.5)
val rgb = rgb(101, 111, 121)

View File

@@ -1,30 +0,0 @@
package nl.astraeus.css
/*
fun main() {
val sd = style {
select("#pipo") {
backgroundColor(hex(0xeeeeee))
fontFamily("Arial, Courier")
animationDelay(DelayDuration.initial)
select("div") {
color(hex(0x1b1b1b1))
alignContent(AlignContent.flexStart)
animationName("animname")
animationTimingFunction(
TimingFunction.cubicBezier(0.1, 0.2, 0.3, 0.4),
TimingFunction.easeInOut
)
}
}
val bla = hsla(1, 50,50,0.5)
bla.toRGBA()
}
//println(sd.generateCss())
}
*/