From d4a8b18ec2613643a3650be9cae81e478970daea Mon Sep 17 00:00:00 2001 From: rnentjes Date: Sun, 15 Aug 2021 08:36:23 +0200 Subject: [PATCH] Fixes --- build.gradle.kts | 11 +- gradle.properties.example | 2 +- readme.md | 122 ++++++++++++++++++ .../nl/astraeus/css/properties/Color.kt | 3 +- .../kotlin/nl/astraeus/css/style/CssBlock.kt | 6 + .../kotlin/nl/astraeus/css/style/Style.kt | 6 + .../kotlin/nl/astraeus/css/CssNameExample.kt | 43 ++++++ .../kotlin/nl/astraeus/css/Examples.kt | 78 +++++++++++ .../kotlin/nl/astraeus/css/TestCssBuilder.kt | 26 ++-- src/jsMain/kotlin/nl/astraeus/css/Test.kt | 30 ----- 10 files changed, 272 insertions(+), 55 deletions(-) create mode 100644 readme.md create mode 100644 src/commonMain/kotlin/nl/astraeus/css/style/CssBlock.kt create mode 100644 src/commonTest/kotlin/nl/astraeus/css/CssNameExample.kt create mode 100644 src/commonTest/kotlin/nl/astraeus/css/Examples.kt delete mode 100644 src/jsMain/kotlin/nl/astraeus/css/Test.kt diff --git a/build.gradle.kts b/build.gradle.kts index 34f45a9..3183702 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -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" - } - } -*/ } diff --git a/gradle.properties.example b/gradle.properties.example index ba7ed9f..a6f8b2a 100644 --- a/gradle.properties.example +++ b/gradle.properties.example @@ -2,4 +2,4 @@ kotlin.code.style=official kotlin.js.compiler=both nexusUsername=deployment -nexusPassword=3p7pl4aenHNFqUhYBaRIlqH6lk +nexusPassword= diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..e3cf0f1 --- /dev/null +++ b/readme.md @@ -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%; +} +``` diff --git a/src/commonMain/kotlin/nl/astraeus/css/properties/Color.kt b/src/commonMain/kotlin/nl/astraeus/css/properties/Color.kt index 625a991..adc6bdb 100644 --- a/src/commonMain/kotlin/nl/astraeus/css/properties/Color.kt +++ b/src/commonMain/kotlin/nl/astraeus/css/properties/Color.kt @@ -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 diff --git a/src/commonMain/kotlin/nl/astraeus/css/style/CssBlock.kt b/src/commonMain/kotlin/nl/astraeus/css/style/CssBlock.kt new file mode 100644 index 0000000..dad6cd6 --- /dev/null +++ b/src/commonMain/kotlin/nl/astraeus/css/style/CssBlock.kt @@ -0,0 +1,6 @@ +package nl.astraeus.css.style + +data class CssBlock( + val selector: String, + val content: String +) diff --git a/src/commonMain/kotlin/nl/astraeus/css/style/Style.kt b/src/commonMain/kotlin/nl/astraeus/css/style/Style.kt index e9ff803..60dd4c9 100644 --- a/src/commonMain/kotlin/nl/astraeus/css/style/Style.kt +++ b/src/commonMain/kotlin/nl/astraeus/css/style/Style.kt @@ -78,6 +78,7 @@ abstract class CssGenerator { warnOnRedeclaration: Boolean = true, allowCommaInSelector: Boolean = false ): String { + val blocks = mutableListOf() 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) } diff --git a/src/commonTest/kotlin/nl/astraeus/css/CssNameExample.kt b/src/commonTest/kotlin/nl/astraeus/css/CssNameExample.kt new file mode 100644 index 0000000..e2090f5 --- /dev/null +++ b/src/commonTest/kotlin/nl/astraeus/css/CssNameExample.kt @@ -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()) + } +} diff --git a/src/commonTest/kotlin/nl/astraeus/css/Examples.kt b/src/commonTest/kotlin/nl/astraeus/css/Examples.kt new file mode 100644 index 0000000..b5b7985 --- /dev/null +++ b/src/commonTest/kotlin/nl/astraeus/css/Examples.kt @@ -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()) + } +} diff --git a/src/commonTest/kotlin/nl/astraeus/css/TestCssBuilder.kt b/src/commonTest/kotlin/nl/astraeus/css/TestCssBuilder.kt index 6196caa..c500441 100644 --- a/src/commonTest/kotlin/nl/astraeus/css/TestCssBuilder.kt +++ b/src/commonTest/kotlin/nl/astraeus/css/TestCssBuilder.kt @@ -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) diff --git a/src/jsMain/kotlin/nl/astraeus/css/Test.kt b/src/jsMain/kotlin/nl/astraeus/css/Test.kt deleted file mode 100644 index 3ed46ac..0000000 --- a/src/jsMain/kotlin/nl/astraeus/css/Test.kt +++ /dev/null @@ -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()) -} - -*/ \ No newline at end of file