31 Commits

Author SHA1 Message Date
0e1c1cd99f Version 1.1.0, add oklch color option
- Update publish plugin
2025-05-03 10:49:00 +02:00
996a8f385e version 1.0.11-SNAPSHOT 2024-10-23 14:00:59 +02:00
d2349c9308 version 1.0.10 2024-10-23 13:50:36 +02:00
e0a4ff54de v. 1.0.8 update Kotlin to 1.9.22, gradle to 8.5 and test-logger to 4.0.0 2024-01-27 12:04:24 +01:00
3f5f1c6543 Example
Took 15 minutes
2023-07-24 10:34:20 +02:00
ac491761d9 v. 1.0.7, kotlin v. 1.7.20, gradle 7.5.1
Took 24 minutes
2022-10-15 11:11:11 +02:00
0d8157cabf Update to snapshot version 2022-03-24 09:29:47 +01:00
1e37ac07ba v. 1.0.6
- Fix not

Took 9 minutes
2022-03-24 09:24:10 +01:00
780dd0782a Update to snapshot version
Took 6 minutes
2021-11-09 13:45:34 +01:00
70a52a3bb5 v. 1.0.4, add vh,vw measurements
Took 47 seconds
2021-11-09 13:38:36 +01:00
68ce4ffa16 Merge remote-tracking branch 'github/main' into main 2021-10-23 11:56:35 +02:00
9f3be7cadd v. 1.0.3, add inline style, fix TemplateRowColumn value types
Took 27 minutes
2021-10-23 11:56:18 +02:00
9217476ae7 Update readme.md 2021-10-15 15:08:08 +02:00
7e86441d84 v. 1.0.2, fix minified option
Took 8 minutes
2021-10-15 15:04:22 +02:00
6375a0d78d v. 1.0.1, update readme.md
Took 1 hour 56 minutes
2021-10-09 20:13:38 +02:00
b2c112f711 Merge branch 'master' into main 2021-10-03 13:26:11 +02:00
95c190defd Initial commit 2021-10-03 13:19:37 +02:00
4137427989 v. 1.0.0
Took 1 hour 52 minutes
2021-10-03 13:18:00 +02:00
ca68871eca Fixes
Took 14 seconds
2021-08-30 12:38:52 +02:00
d4a8b18ec2 Fixes 2021-08-15 08:36:23 +02:00
1dc6f6cf9f Add UoM 2021-07-09 11:16:29 +02:00
adec3b21b0 Add Color conversion options (add hsla -> hex) 2021-07-08 16:15:42 +02:00
9e43f5b746 Add Color conversion options 2021-07-08 13:17:15 +02:00
57edc59853 Add fr uom 2021-06-15 13:20:30 +02:00
536d095b96 Disallow comma in selector by default 2021-06-11 11:07:46 +02:00
95fb7ec923 Allow multiple selectors for one style (or operator) 2021-06-11 09:45:04 +02:00
c5ba12032d Reformat code 2021-05-11 17:26:08 +02:00
2b725f6af2 Add gradle.properties.example 2021-05-11 09:09:52 +02:00
46d99d4122 Delete gradle.properties 2021-05-11 09:06:27 +02:00
d1094bddef Merge function-builder branch into master 2021-05-11 09:04:49 +02:00
4730e6d3d7 Fix js test 2020-03-01 13:21:00 +01:00
89 changed files with 4004 additions and 2021 deletions

21
LICENSE Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2021 Rien
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -1,36 +1,48 @@
@file:OptIn(ExperimentalWasmDsl::class)
import com.vanniktech.maven.publish.SonatypeHost
import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl
plugins { plugins {
kotlin("multiplatform") version "1.4.32" kotlin("multiplatform") version "2.1.10"
`maven-publish` id("com.vanniktech.maven.publish") version "0.31.0"
signing
id("org.jetbrains.dokka") version "2.0.0"
} }
group = "nl.astraeus" group = "nl.astraeus"
version = "0.4.19" version = "1.1.0"
repositories { repositories {
maven { setUrl("https://dl.bintray.com/kotlin/kotlin-eap") }
mavenLocal()
mavenCentral() mavenCentral()
} }
kotlin { kotlin {
jvm() jvm()
js(BOTH) { js(IR) {
browser { browser {
testTask { /* testTask {
useKarma { // work around, browser test is broken atm
useFirefox() enabled = false
//useChrome() }*/
} }
} }
wasmJs {
//moduleName = project.name
browser()
mavenPublication {
groupId = group as String
pom { name = "${project.name}-wasm-js" }
} }
} }
sourceSets { sourceSets {
val commonMain by getting {} val commonMain by getting
val commonTest by getting { val commonTest by getting {
dependencies { dependencies {
implementation(kotlin("test-common")) implementation(kotlin("test"))
implementation(kotlin("test-annotations-common"))
} }
} }
val jvmTest by getting { val jvmTest by getting {
@@ -38,46 +50,69 @@ kotlin {
implementation(kotlin("test-junit")) implementation(kotlin("test-junit"))
} }
} }
val jsTest by getting { val jsMain by getting
dependencies { val wasmJsMain by getting
implementation(kotlin("test-js"))
}
}
} }
} }
val javadocJar by tasks.registering(Jar::class) {
archiveClassifier.set("javadoc")
}
publishing { publishing {
repositories { repositories {
mavenLocal()
maven { maven {
name = "releases" name = "gitea"
// change to point to your repo, e.g. http://my.org/repo setUrl("https://gitea.astraeus.nl/api/packages/rnentjes/maven")
url = uri("http://nexus.astraeus.nl/nexus/content/repositories/releases")
credentials {
val nexusUsername: String by project
val nexusPassword: String by project
username = nexusUsername credentials() {
password = nexusPassword val giteaUsername: kotlin.String? by project
} val giteaPassword: kotlin.String? by project
}
maven {
name = "snapshots"
// change to point to your repo, e.g. http://my.org/repo
url = uri("http://nexus.astraeus.nl/nexus/content/repositories/snapshots")
credentials {
val nexusUsername: String by project
val nexusPassword: String by project
username = nexusUsername username = giteaUsername
password = nexusPassword password = giteaPassword
} }
} }
} }
/* }
publications {
val kotlinMultiplatform by getting { signing {
artifactId = "kotlin-css-generator" sign(publishing.publications)
} }
}
*/
tasks.withType<AbstractPublishToMaven> {
dependsOn(tasks.withType<Sign>())
}
mavenPublishing {
publishToMavenCentral(SonatypeHost.CENTRAL_PORTAL)
signAllPublications()
coordinates(group.toString(), name, version.toString())
pom {
name = "kotlin-css-generator"
description = "Kotlin css generator"
inceptionYear = "2020"
url = "https://github.com/rnentjes/kotlin-css-generator"
licenses {
license {
name = "MIT"
url = "https://opensource.org/licenses/MIT"
}
}
developers {
developer {
id = "rnentjes"
name = "Rien Nentjes"
email = "info@nentjes.com"
}
}
scm {
url = "https://github.com/rnentjes/kotlin-css-generator"
}
}
} }

View File

@@ -1,5 +0,0 @@
kotlin.code.style=official
kotlin.js.compiler=both
nexusUsername=deployment
nexusPassword=bGtci5GLFbqORmruICmTWFmGLY

11
gradle.properties.example Normal file
View File

@@ -0,0 +1,11 @@
kotlin.code.style=official
kotlin.js.compiler=both
nexusUsername=deployment
nexusPassword=
signingKeyId=
signingPassword=
signingSecretKeyRingFile=
ossrhUsername=
ossrhPassword=

View File

@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.3-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists

98
publish/build.gradle.kts Normal file
View File

@@ -0,0 +1,98 @@
import java.util.*
plugins {
`maven-publish`
signing
}
repositories {
mavenCentral()
}
project.extra.set("PUBLISH_GROUP_ID", "nl.astraeus")
project.extra.set("PUBLISH_VERSION", "1.0.0")
project.extra.set("PUBLISH_ARTIFACT_ID", "kotlin-css-generator")
apply(from = "${rootProject.projectDir}/build.gradle.kts")
// Stub secrets to let the project sync and build without the publication values set up
extra["signing.keyId"] = null
extra["signing.password"] = null
extra["signing.secretKeyRingFile"] = null
extra["ossrhUsername"] = null
extra["ossrhPassword"] = null
// Grabbing secrets from local.properties file or from environment variables, which could be used on CI
val secretPropsFile = project.rootProject.file("local.properties")
if (secretPropsFile.exists()) {
secretPropsFile.reader().use {
Properties().apply {
load(it)
}
}.onEach { (name, value) ->
extra[name.toString()] = value
}
} else {
extra["signing.keyId"] = System.getenv("SIGNING_KEY_ID")
extra["signing.password"] = System.getenv("SIGNING_PASSWORD")
extra["signing.secretKeyRingFile"] = System.getenv("SIGNING_SECRET_KEY_RING_FILE")
extra["ossrhUsername"] = System.getenv("OSSRH_USERNAME")
extra["ossrhPassword"] = System.getenv("OSSRH_PASSWORD")
}
val javadocJar by tasks.registering(Jar::class) {
archiveClassifier.set("javadoc")
}
fun getExtraString(name: String) = extra[name]?.toString()
publishing {
// Configure maven central repository
repositories {
maven {
name = "sonatype"
setUrl("https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/")
credentials {
username = getExtraString("ossrhUsername")
password = getExtraString("ossrhPassword")
}
}
}
// Configure all publications
publications.withType<MavenPublication> {
// Stub javadoc.jar artifact
artifact(javadocJar.get())
// Provide artifacts information requited by Maven Central
pom {
name.set("kotlin-css-generator")
description.set("Kotlin css generator")
url.set("https://github.com/rnentjes/kotlin-css-generator")
licenses {
license {
name.set("MIT")
url.set("https://opensource.org/licenses/MIT")
}
}
developers {
developer {
id.set("rnentjes")
name.set("Rien Nentjes")
email.set("info@nentjes.com")
}
}
scm {
url.set("https://github.com/rnentjes/kotlin-css-generator")
}
}
}
}
// Signing artifacts. Signing.* extra properties values will be used
signing {
sign(publishing.publications)
}

View File

@@ -0,0 +1,121 @@
apply plugin: 'maven-publish'
apply plugin: 'signing'
task publishSourcesJar(type: Jar) {
archiveClassifier.set('sources')
// For pure Kotlin libraries, in case you have them
from sourceSets.main.java.srcDirs
//from sourceSets.main.kotlin.srcDirs
}
task packageJavadoc(type: Jar) {
from javadoc
classifier = 'javadoc'
}
artifacts {
archives publishSourcesJar
}
File secretPropsFile = project.rootProject.file('local.properties')
ext["signing.keyId"] = ''
ext["signing.password"] = ''
ext["signing.secretKeyRingFile"] = ''
ext["ossrhUsername"] = ''
ext["ossrhPassword"] = ''
ext["sonatypeStagingProfileId"] = ''
if (secretPropsFile.exists()) {
Properties p = new Properties()
new FileInputStream(secretPropsFile).withCloseable { is ->
p.load(is)
}
p.each { name, value ->
ext[name] = value
}
}
afterEvaluate {
publishing {
publications {
release(MavenPublication) {
// The coordinates of the library, being set from variables that
// we'll set up later
groupId PUBLISH_GROUP_ID
artifactId PUBLISH_ARTIFACT_ID
version PUBLISH_VERSION
// Two artifacts, the `aar` (or `jar`) and the sources
if (project.plugins.findPlugin("com.android.library")) {
artifact("$buildDir/outputs/aar/${project.getName()}-release.aar")
} else {
artifact("$buildDir/libs/${project.getName()}-${version}.jar")
}
artifact publishSourcesJar
artifact packageJavadoc
// Mostly self-explanatory metadata
pom {
name = PUBLISH_ARTIFACT_ID
description = 'Simple JDBC wrapper for query statistics'
url = 'https://github.com/rnentjes/Simple-jdbc-statistics'
licenses {
license {
name = 'MIT License'
url = 'https://github.com/rnentjes/Simple-jdbc-statistics/blob/master/LICENCE.txt'
}
}
developers {
developer {
id = 'rnentjes'
name = 'Rien Nentjes'
email = 'info@nentjes.com'
}
// Add all other devs here...
}
// Version control info - if you're using GitHub, follow the format as seen here
scm {
connection = 'scm:git:github.com/rnentjes/Simple-jdbc-statistics.git'
developerConnection = 'scm:git:ssh://github.com/rnentjes/Simple-jdbc-statistics.git'
url = 'https://github.com/rnentjes/Simple-jdbc-statistics.git/tree/main'
}
// A slightly hacky fix so that your POM will include any transitive dependencies
// that your library builds upon
/*
witXml {
def dependenciesNode = asNode().appendNode('dependencies')
project.configurations.implementation.allDependencies.each {
def dependencyNode = dependenciesNode.appendNode('dependency')
dependencyNode.appendNode('groupId', it.group)
dependencyNode.appendNode('artifactId', it.name)
dependencyNode.appendNode('version', it.version)
}
}*/
}
}
}
// The repository to publish to, Sonatype/MavenCentral
repositories {
maven {
// This is an arbitrary name, you may also use "mavencentral" or
// any other name that's descriptive for you
name = "sonatype"
url = "https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/"
credentials {
username ossrhUsername
password ossrhPassword
}
}
}
}
}
signing {
sign publishing.publications
}

View File

@@ -0,0 +1,12 @@
pluginManagement {
repositories {
mavenCentral()
maven { setUrl("https://plugins.gradle.org/m2/") }
}
}
rootProject.name = "publish-kotlin-css-generator"
//enableFeaturePreview("GRADLE_METADATA")
//include(":publish")

176
readme.md Normal file
View File

@@ -0,0 +1,176 @@
# Css generator like less/sass in kotlin multiplatform
This library is for generating css from a kotlin dsl.
It can be used as an alternative to less/sass or as a runtime library to generate css on-the-fly.
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.
## Usage
Include in build.gradle.kts:
```kotlin
repositories {
mavenCentral()
}
val commonMain by getting {
dependencies {
api("nl.astraeus:kotlin-css-generator:1.0.9")
}
}
```
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))
}
}
}
}
```
To generate the css call get generateCss function:
```kotlin
val cssString: String = css.generateCss()
```
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);
}
```
There are several options when generating the css, for example minified:
```kotlin
val cssString: String = css.generateCss(minified = true)
```
Result:
```css
.button{padding:5px;}.buttona{color:hsla(0,50%,50%,1.0);background-color:white;}.buttona:hover{color:hsla(0,50%,55%,1.0);background-color:rgba(229,229,229,1.0);}
```
## Mixins
As it's all just kotlin code, includes and 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;
}
```
Giving the option combineEqualBlocks to the generateCss call will combine the a and .button blocks with the following result:
```css
a,
.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

@@ -1,13 +1,20 @@
pluginManagement { pluginManagement {
repositories { repositories {
maven { setUrl("https://dl.bintray.com/kotlin/kotlin-eap") } google()
mavenCentral() mavenCentral()
gradlePluginPortal()
maven { setUrl("https://plugins.gradle.org/m2/") }
} }
} }
rootProject.name = "kotlin-css-generator" dependencyResolutionManagement {
repositories {
google()
mavenCentral()
}
}
enableFeaturePreview("GRADLE_METADATA") plugins {
id("org.gradle.toolchains.foojay-resolver-convention") version "0.8.0"
}
rootProject.name = "kotlin-css-generator"

View File

@@ -8,23 +8,23 @@ import nl.astraeus.css.style.Style
fun css(definition: Css) = definition fun css(definition: Css) = definition
fun style(definition: ConditionalCss): ConditionalStyle { fun style(definition: ConditionalCss): ConditionalStyle {
val css = ConditionalStyle() val css = ConditionalStyle()
definition(css) definition(css)
return css return css
} }
class CssBuilder { class CssBuilder {
var definition: Style = Style() var definition: Style = Style()
fun style(definition: Style.() -> Unit) { fun style(definition: Style.() -> Unit) {
definition(this.definition) definition(this.definition)
} }
fun getCss(minified: Boolean = false): String = definition.generateCss(minified = minified) fun getCss(minified: Boolean = false): String = definition.generateCss(minified = minified)
override fun toString(): String { override fun toString(): String {
return "CssBuilder(${definition.generateCss()})" return "CssBuilder(${definition.generateCss()})"
} }
} }

View File

@@ -1,17 +1,17 @@
package nl.astraeus.css.properties package nl.astraeus.css.properties
class AlignContent( class AlignContent(
value: String value: String
) : CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val stretch = AlignContent("stretch") val stretch = AlignContent("stretch")
val center = AlignContent("center") val center = AlignContent("center")
val flexStart = AlignContent("flex-start") val flexStart = AlignContent("flex-start")
val flexEnd = AlignContent("flex-end") val flexEnd = AlignContent("flex-end")
val spaceBetween = AlignContent("space-between") val spaceBetween = AlignContent("space-between")
val spaceAround = AlignContent("space-around") val spaceAround = AlignContent("space-around")
val initial = AlignContent("initial") val initial = AlignContent("initial")
val inherit = AlignContent("inherit") val inherit = AlignContent("inherit")
} }
} }

View File

@@ -1,17 +1,17 @@
package nl.astraeus.css.properties package nl.astraeus.css.properties
class AlignItems( class AlignItems(
value: String value: String
): CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val stretch = AlignItems("stretch") val stretch = AlignItems("stretch")
val center = AlignItems("center") val center = AlignItems("center")
val flexStart = AlignItems("flex-start") val flexStart = AlignItems("flex-start")
val flexEnd = AlignItems("flex-end") val flexEnd = AlignItems("flex-end")
val baseline = AlignItems("baseline") val baseline = AlignItems("baseline")
val initial = AlignItems("initial") val initial = AlignItems("initial")
val inherit = AlignItems("inherit") val inherit = AlignItems("inherit")
} }
} }

View File

@@ -1,18 +1,18 @@
package nl.astraeus.css.properties package nl.astraeus.css.properties
class AlignSelf( class AlignSelf(
value: String value: String
): CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val auto = AlignSelf("auto") val auto = AlignSelf("auto")
val stretch = AlignSelf("stretch") val stretch = AlignSelf("stretch")
val center = AlignSelf("center") val center = AlignSelf("center")
val flexStart = AlignSelf("flex-start") val flexStart = AlignSelf("flex-start")
val flexEnd = AlignSelf("flex-end") val flexEnd = AlignSelf("flex-end")
val baseline = AlignSelf("baseline") val baseline = AlignSelf("baseline")
val initial = AlignSelf("initial") val initial = AlignSelf("initial")
val inherit = AlignSelf("inherit") val inherit = AlignSelf("inherit")
} }
} }

View File

@@ -1,14 +1,14 @@
package nl.astraeus.css.properties package nl.astraeus.css.properties
class All( class All(
value: String value: String
): CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val unset = All("unset") val unset = All("unset")
val revert = All("revert") val revert = All("revert")
val initial = All("initial") val initial = All("initial")
val inherit = All("inherit") val inherit = All("inherit")
} }
} }

View File

@@ -1,55 +1,55 @@
package nl.astraeus.css.properties package nl.astraeus.css.properties
class AnimationDirection( class AnimationDirection(
value: String value: String
) : CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val normal = AnimationDirection("normal") val normal = AnimationDirection("normal")
val reverse = AnimationDirection("reverse") val reverse = AnimationDirection("reverse")
val alternate = AnimationDirection("alternate") val alternate = AnimationDirection("alternate")
val alternateReverse = AnimationDirection("alternate-reverse") val alternateReverse = AnimationDirection("alternate-reverse")
val initial = AnimationDirection("initial") val initial = AnimationDirection("initial")
val inherit = AnimationDirection("inherit") val inherit = AnimationDirection("inherit")
} }
} }
class AnimationFillMode( class AnimationFillMode(
value: String value: String
) : CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val none = AnimationFillMode("none") val none = AnimationFillMode("none")
val forwards = AnimationFillMode("forwards") val forwards = AnimationFillMode("forwards")
val backwards = AnimationFillMode("backwards") val backwards = AnimationFillMode("backwards")
val both = AnimationFillMode("both") val both = AnimationFillMode("both")
val initial = AnimationFillMode("initial") val initial = AnimationFillMode("initial")
val inherit = AnimationFillMode("inherit") val inherit = AnimationFillMode("inherit")
} }
} }
class AnimationFrame( class AnimationFrame(
value: String = "" value: String = ""
): CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
fun name(name: String) = AnimationFrame(name) fun name(name: String) = AnimationFrame(name)
val none: AnimationFrame = AnimationFrame("none") val none: AnimationFrame = AnimationFrame("none")
val initial: AnimationFrame = AnimationFrame("initial") val initial: AnimationFrame = AnimationFrame("initial")
val inherit: AnimationFrame = AnimationFrame("inherit") val inherit: AnimationFrame = AnimationFrame("inherit")
} }
} }
class AnimationPlayState( class AnimationPlayState(
value: String value: String
) : CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
fun name(name: String) = AnimationPlayState(name) fun name(name: String) = AnimationPlayState(name)
val paused = AnimationPlayState("paused") val paused = AnimationPlayState("paused")
val running = AnimationPlayState("running") val running = AnimationPlayState("running")
val initial = AnimationPlayState("initial") val initial = AnimationPlayState("initial")
val inherit = AnimationPlayState("inherit") val inherit = AnimationPlayState("inherit")
} }
} }

View File

@@ -1,13 +1,13 @@
package nl.astraeus.css.properties package nl.astraeus.css.properties
class BackfaceVisibility( class BackfaceVisibility(
value: String value: String
) : CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val visible = BackfaceVisibility("visible") val visible = BackfaceVisibility("visible")
val hidden = BackfaceVisibility("hidden") val hidden = BackfaceVisibility("hidden")
val initial = BackfaceVisibility("initial") val initial = BackfaceVisibility("initial")
val inherit = BackfaceVisibility("inherit") val inherit = BackfaceVisibility("inherit")
} }
} }

View File

@@ -1,79 +1,79 @@
package nl.astraeus.css.properties package nl.astraeus.css.properties
class BackgroundAttachment( class BackgroundAttachment(
value: String value: String
) : CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val scroll = BackgroundAttachment("scroll") val scroll = BackgroundAttachment("scroll")
val fixed = BackgroundAttachment("fixed") val fixed = BackgroundAttachment("fixed")
val local = BackgroundAttachment("local") val local = BackgroundAttachment("local")
val initial = BackgroundAttachment("initial") val initial = BackgroundAttachment("initial")
val inherit = BackgroundAttachment("inherit") val inherit = BackgroundAttachment("inherit")
} }
} }
class BackgroundBlendMode( class BackgroundBlendMode(
value: String value: String
) : CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val normal = BackgroundBlendMode("normal") val normal = BackgroundBlendMode("normal")
val multiply = BackgroundBlendMode("multiply") val multiply = BackgroundBlendMode("multiply")
val screen = BackgroundBlendMode("screen") val screen = BackgroundBlendMode("screen")
val overlay = BackgroundBlendMode("overlay") val overlay = BackgroundBlendMode("overlay")
val darken = BackgroundBlendMode("darken") val darken = BackgroundBlendMode("darken")
val lighten = BackgroundBlendMode("lighten") val lighten = BackgroundBlendMode("lighten")
val colorDodge = BackgroundBlendMode("color-dodge") val colorDodge = BackgroundBlendMode("color-dodge")
val saturation = BackgroundBlendMode("saturation") val saturation = BackgroundBlendMode("saturation")
val color = BackgroundBlendMode("color") val color = BackgroundBlendMode("color")
val luminosity = BackgroundBlendMode("luminosity") val luminosity = BackgroundBlendMode("luminosity")
} }
} }
class BackgroundPosition( class BackgroundPosition(
value: String value: String
) : CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val left = BackgroundPosition("left") val left = BackgroundPosition("left")
val center = BackgroundPosition("center") val center = BackgroundPosition("center")
val right = BackgroundPosition("right") val right = BackgroundPosition("right")
val initial = BackgroundPosition("initial") val initial = BackgroundPosition("initial")
val inherit = BackgroundPosition("inherit") val inherit = BackgroundPosition("inherit")
} }
} }
class BackgroundRepeat( class BackgroundRepeat(
value: String value: String
) : CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val repeat = BackgroundRepeat("repeat") val repeat = BackgroundRepeat("repeat")
val repeatX = BackgroundRepeat("repeat-x") val repeatX = BackgroundRepeat("repeat-x")
val repeatY = BackgroundRepeat("repeat-y") val repeatY = BackgroundRepeat("repeat-y")
val noRepeat = BackgroundRepeat("no-repeat") val noRepeat = BackgroundRepeat("no-repeat")
val space = BackgroundRepeat("space") val space = BackgroundRepeat("space")
val round = BackgroundRepeat("round") val round = BackgroundRepeat("round")
val initial = BackgroundRepeat("initial") val initial = BackgroundRepeat("initial")
val inherit = BackgroundRepeat("inherit") val inherit = BackgroundRepeat("inherit")
val unset = BackgroundRepeat("unset") val unset = BackgroundRepeat("unset")
} }
} }
class BackgroundSize( class BackgroundSize(
value: String value: String
) : CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
fun px(px: Int) = BackgroundSize("${px}px") fun px(px: Int) = BackgroundSize("${px}px")
fun perc(pc: Double) = BackgroundSize("${pc}%") fun perc(pc: Double) = BackgroundSize("${pc}%")
val auto = BackgroundSize("auto") val auto = BackgroundSize("auto")
val cover = BackgroundSize("cover") val cover = BackgroundSize("cover")
val contain = BackgroundSize("contain") val contain = BackgroundSize("contain")
val initial = BackgroundSize("initial") val initial = BackgroundSize("initial")
val inherit = BackgroundSize("inherit") val inherit = BackgroundSize("inherit")
} }
} }

View File

@@ -1,96 +1,78 @@
package nl.astraeus.css.properties package nl.astraeus.css.properties
class BorderRadius(
value: String
): CssProperty(value) {
companion object {
fun px(nr: Int) = BorderRadius("${nr}px")
fun em(nr: Int) = BorderRadius("${nr}em")
fun em(nr: Double) = BorderRadius("${nr}em")
fun perc(nr: Int) = BorderRadius("${nr}%")
fun perc(nr: Double) = BorderRadius("${nr}%")
fun pc(nr: Int) = BorderRadius("${nr}pc")
fun pc(nr: Double) = BorderRadius("${nr}pc")
fun cm(nr: Int) = BorderRadius("${nr}cm")
fun cm(nr: Double) = BorderRadius("${nr}cm")
val initial = BorderRadius("initial")
val inherit = BorderRadius("inherit")
}
}
class BorderStyle( class BorderStyle(
value: String value: String
): CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val none = BorderStyle("none") val none = BorderStyle("none")
val hidden = BorderStyle("hidden") val hidden = BorderStyle("hidden")
val dotted = BorderStyle("dotted") val dotted = BorderStyle("dotted")
val dashed = BorderStyle("dashed") val dashed = BorderStyle("dashed")
val solid = BorderStyle("solid") val solid = BorderStyle("solid")
val double = BorderStyle("double") val double = BorderStyle("double")
val groove = BorderStyle("groove") val groove = BorderStyle("groove")
val ridge = BorderStyle("ridge") val ridge = BorderStyle("ridge")
val inset = BorderStyle("inset") val inset = BorderStyle("inset")
val outset = BorderStyle("outset") val outset = BorderStyle("outset")
val initial = BorderStyle("initial") val initial = BorderStyle("initial")
val inherit = BorderStyle("inherit") val inherit = BorderStyle("inherit")
} }
} }
class BorderWidth( class BorderWidth(
value: String value: String
): CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val thin = BorderWidth("thin") val thin = BorderWidth("thin")
val medium = BorderWidth("medium") val medium = BorderWidth("medium")
val thick = BorderWidth("thick") val thick = BorderWidth("thick")
val initial = BorderWidth("initial") val initial = BorderWidth("initial")
val inherit = BorderWidth("inherit") val inherit = BorderWidth("inherit")
} }
} }
class BorderCollapse( class BorderCollapse(
value: String value: String
): CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val separate = BorderCollapse("separate") val separate = BorderCollapse("separate")
val collapse = BorderCollapse("collapse") val collapse = BorderCollapse("collapse")
} }
} }
class BorderImageWidth ( class BorderImageWidth(
value: String value: String
): CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
fun px(nr: Int) = BorderImageWidth("${nr}px") fun px(nr: Int) = BorderImageWidth("${nr}px")
fun nr(nr: Int) = BorderImageWidth("$nr") fun nr(nr: Int) = BorderImageWidth("$nr")
fun perc(nr: Int) = BorderImageWidth("${nr}%") fun perc(nr: Int) = BorderImageWidth("${nr}%")
fun perc(nr: Double) = BorderImageWidth("${nr}%") fun perc(nr: Double) = BorderImageWidth("${nr}%")
val auto = BorderImageWidth("auto") val auto = BorderImageWidth("auto")
val initial = BorderImageWidth("initial") val initial = BorderImageWidth("initial")
val inherit = BorderImageWidth("inherit") val inherit = BorderImageWidth("inherit")
} }
} }
class BorderSpacing( class BorderSpacing(
value: String value: String
): CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
fun px(nr: Int) = BorderSpacing("${nr}px") fun px(nr: Int) = BorderSpacing("${nr}px")
fun em(nr: Int) = BorderSpacing("${nr}em") fun em(nr: Int) = BorderSpacing("${nr}em")
fun em(nr: Double) = BorderSpacing("${nr}em") fun em(nr: Double) = BorderSpacing("${nr}em")
fun perc(nr: Int) = BorderSpacing("${nr}%") fun perc(nr: Int) = BorderSpacing("${nr}%")
fun perc(nr: Double) = BorderSpacing("${nr}%") fun perc(nr: Double) = BorderSpacing("${nr}%")
fun pc(nr: Int) = BorderSpacing("${nr}pc") fun pc(nr: Int) = BorderSpacing("${nr}pc")
fun pc(nr: Double) = BorderSpacing("${nr}pc") fun pc(nr: Double) = BorderSpacing("${nr}pc")
fun cm(nr: Int) = BorderSpacing("${nr}cm") fun cm(nr: Int) = BorderSpacing("${nr}cm")
fun cm(nr: Double) = BorderSpacing("${nr}cm") fun cm(nr: Double) = BorderSpacing("${nr}cm")
val initial = BorderSpacing("initial") val initial = BorderSpacing("initial")
val inherit = BorderSpacing("inherit") val inherit = BorderSpacing("inherit")
} }
} }

View File

@@ -1,40 +1,40 @@
package nl.astraeus.css.properties package nl.astraeus.css.properties
class BoxDecorationBreak( class BoxDecorationBreak(
value: String value: String
): CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val slice = BoxDecorationBreak("slice") val slice = BoxDecorationBreak("slice")
val clone = BoxDecorationBreak("clone") val clone = BoxDecorationBreak("clone")
val initial = BoxDecorationBreak("initial") val initial = BoxDecorationBreak("initial")
val inherit = BoxDecorationBreak("inherit") val inherit = BoxDecorationBreak("inherit")
val unset = BoxDecorationBreak("unset") val unset = BoxDecorationBreak("unset")
} }
} }
class BoxShadow( class BoxShadow(
value: String value: String
): CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val none = BoxShadow("none") val none = BoxShadow("none")
val inset = BoxShadow("inset") val inset = BoxShadow("inset")
val initial = BoxShadow("initial") val initial = BoxShadow("initial")
val inherit = BoxShadow("inherit") val inherit = BoxShadow("inherit")
fun text(txt: String) = BoxShadow(txt) fun text(txt: String) = BoxShadow(txt)
} }
} }
class BoxSizing( class BoxSizing(
value: String value: String
): CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val contextBox = BoxSizing("content-box") val contextBox = BoxSizing("content-box")
val borderBox = BoxSizing("border-box") val borderBox = BoxSizing("border-box")
val initial = BoxShadow("initial") val initial = BoxShadow("initial")
val inherit = BoxShadow("inherit") val inherit = BoxShadow("inherit")
} }
} }

View File

@@ -2,26 +2,26 @@ package nl.astraeus.css.properties
class Break( class Break(
value: String value: String
): CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val auto = Break("auto") val auto = Break("auto")
val all = Break("all") val all = Break("all")
val always = Break("always") val always = Break("always")
val avoid = Break("avoid") val avoid = Break("avoid")
val avoidColumn = Break("avoid-column") val avoidColumn = Break("avoid-column")
val avoidPage = Break("avoid-page") val avoidPage = Break("avoid-page")
val avoidRegion = Break("avoid-region") val avoidRegion = Break("avoid-region")
val column = Break("column") val column = Break("column")
val left = Break("left") val left = Break("left")
val page = Break("page") val page = Break("page")
val recto = Break("recto") val recto = Break("recto")
val region = Break("region") val region = Break("region")
val right = Break("right") val right = Break("right")
val verso = Break("verso") val verso = Break("verso")
val initial = Break("initial") val initial = Break("initial")
val inherit = Break("inherit") val inherit = Break("inherit")
} }
} }

View File

@@ -0,0 +1,31 @@
package nl.astraeus.css.properties
fun calc(expression: CalcExpression) = Calc(expression)
infix operator fun CalcExpression.plus(other: CalcExpression) = CompoundCalcExpression(
this,
"+",
other
)
infix operator fun CalcExpression.minus(other: CalcExpression) = CompoundCalcExpression(
this,
"-",
other
)
interface CalcExpression
class CompoundCalcExpression(
val left: CalcExpression,
val operator: String,
val right: CalcExpression
): CalcExpression {
override fun toString(): String {
return "$left $operator $right"
}
}
class Calc(
expression: CalcExpression
) : CssProperty(expression.toString())

View File

@@ -1,14 +1,14 @@
package nl.astraeus.css.properties package nl.astraeus.css.properties
class CaptionSide( class CaptionSide(
value: String value: String
): CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val top = CaptionSide("top") val top = CaptionSide("top")
val bottom = CaptionSide("bottom") val bottom = CaptionSide("bottom")
val initial = CaptionSide("initial") val initial = CaptionSide("initial")
val inherit = CaptionSide("inherit") val inherit = CaptionSide("inherit")
} }
} }

View File

@@ -2,16 +2,16 @@ package nl.astraeus.css.properties
class Clear( class Clear(
value: String value: String
): CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val none = Clear("none") val none = Clear("none")
val left = Clear("left") val left = Clear("left")
val right = Clear("right") val right = Clear("right")
val both = Clear("both") val both = Clear("both")
val initial = Clear("initial") val initial = Clear("initial")
val inherit = Clear("inherit") val inherit = Clear("inherit")
} }
} }

View File

@@ -1,57 +1,57 @@
package nl.astraeus.css.properties package nl.astraeus.css.properties
class Clip( class Clip(
value: String value: String
) : CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
fun rect(top: Int, right: Int, bottom: Int, left: Int) = Clip("rect(${top}px,${right}px,${bottom}px,${left}px)") fun rect(top: Int, right: Int, bottom: Int, left: Int) = Clip("rect(${top}px,${right}px,${bottom}px,${left}px)")
val auto = Clip("auto") val auto = Clip("auto")
val initial = Clip("initial") val initial = Clip("initial")
val inherit = Clip("inherit") val inherit = Clip("inherit")
} }
} }
class ClipPath( class ClipPath(
value: String value: String
) : CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val auto = ClipPath("auto") val auto = ClipPath("auto")
fun circle(perc: Double) = ClipPath("circle(${perc}%)") fun circle(perc: Double) = ClipPath("circle(${perc}%)")
fun ellipse(radiusX: Double, radiusY: Double) = ClipPath("ellipse(${radiusX}%,${radiusY}%)") fun ellipse(radiusX: Double, radiusY: Double) = ClipPath("ellipse(${radiusX}%,${radiusY}%)")
fun ellipse( fun ellipse(
radiusX: Double, radiusX: Double,
radiusY: Double, radiusY: Double,
positionX: Double, positionX: Double,
positionY: Double positionY: Double
) = ClipPath("ellipse(${radiusX}%,${radiusY}% at ${positionX}%,${positionY}%)") ) = ClipPath("ellipse(${radiusX}%,${radiusY}% at ${positionX}%,${positionY}%)")
// todo: other options // todo: other options
fun other(text: String) = ClipPath(text) fun other(text: String) = ClipPath(text)
val marginBox = ClipPath("margin-box") val marginBox = ClipPath("margin-box")
val borderBox = ClipPath("border-box") val borderBox = ClipPath("border-box")
val paddingBox = ClipPath("padding-box") val paddingBox = ClipPath("padding-box")
val contentBox = ClipPath("content-box") val contentBox = ClipPath("content-box")
val fillBox = ClipPath("fill-box") val fillBox = ClipPath("fill-box")
val strokeBox = ClipPath("stroke-box") val strokeBox = ClipPath("stroke-box")
val viewBox = ClipPath("view-box") val viewBox = ClipPath("view-box")
val none = ClipPath("none") val none = ClipPath("none")
} }
} }
class ClipOrigin( class ClipOrigin(
value: String value: String
) : CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val borderBox = ClipOrigin("border-box") val borderBox = ClipOrigin("border-box")
val paddingBox = ClipOrigin("padding-box") val paddingBox = ClipOrigin("padding-box")
val contentBox = ClipOrigin("content-box") val contentBox = ClipOrigin("content-box")
val initial = ClipOrigin("initial") val initial = ClipOrigin("initial")
val inherit = ClipOrigin("inherit") val inherit = ClipOrigin("inherit")
} }
} }

View File

@@ -5,6 +5,25 @@ import kotlin.math.abs
import kotlin.math.max import kotlin.math.max
import kotlin.math.roundToInt import kotlin.math.roundToInt
private val hexString = "0123456789abcdef"
private fun Int.toColorHex(minimumDigits: Int = 2): String {
val result = StringBuilder()
var value = this
while(value > 0) {
result.append(hexString[value%16])
value /= 16
}
while(result.length < minimumDigits) {
result.append("0")
}
return result.reverse().toString()
}
/** /**
* See [CSS Color Module Level 3](https://www.w3.org/TR/2018/REC-css-color-3-20180619/) * See [CSS Color Module Level 3](https://www.w3.org/TR/2018/REC-css-color-3-20180619/)
* *
@@ -30,6 +49,345 @@ class Color(value: String) : CssProperty(value) {
this.rgb = rgb this.rgb = rgb
} }
fun hasAlpha(): Boolean = isRgba() || isHexa() || isHsla()
fun getAlpha(): Double = when {
isHexa() || isRgba() -> {
toRGBA().alpha
}
isHsla() -> {
fromHSLANotation().alpha
}
else -> {
1.0
}
}
fun toHex(): String = if (isHsla() || isHsl()) {
fromHSLANotation().asRGBA().asHex()
} else {
toRGBA().asHex()
}
fun isHsla(): Boolean {
val v = rgb ?: value
return v.startsWith("hsla")
}
fun isHsl(): Boolean {
val v = rgb ?: value
return v.startsWith("hsl(")
}
fun isRgba(): Boolean {
val v = rgb ?: value
return v.startsWith("rgba(")
}
fun isRgb(): Boolean {
val v = rgb ?: value
return v.startsWith("rgb(")
}
fun isHex(): Boolean {
val v = rgb ?: value
return v.startsWith("#") && v.length < 8
}
fun isHexa(): Boolean {
val v = rgb ?: value
return v.startsWith("#") && v.length > 7
}
/**
* withAlpha preserves existing alpha value: rgba(0, 0, 0, 0.5).withAlpha(0.1) = rgba(0, 0, 0, 0.05)
*/
fun withAlpha(alpha: Double) =
when {
value.startsWith("hsl", true) -> with(fromHSLANotation()) { hsla(hue, saturation, lightness, normalizeAlpha(alpha) * this.alpha) }
else -> with(toRGBA()) { rgba(red, green, blue, normalizeAlpha(alpha) * this.alpha) }
}
/**
* changeAlpha rewrites existing alpha value: rgba(0, 0, 0, 0.5).withAlpha(0.1) = rgba(0, 0, 0, 0.1)
*/
fun changeAlpha(alpha: Double) =
when {
value.startsWith("hsl", true) -> with(fromHSLANotation()) { hsla(hue, saturation, lightness, normalizeAlpha(alpha)) }
else -> with(toRGBA()) { rgba(red, green, blue, normalizeAlpha(alpha)) }
}
// https://stackoverflow.com/questions/2049230/convert-rgba-color-to-rgb
fun blend(backgroundColor: Color): Color {
val source = this.toRGBA()
val background = backgroundColor.toRGBA()
val targetR = ((1 - source.alpha) * background.red) + (source.alpha * source.red)
val targetG = ((1 - source.alpha) * background.green) + (source.alpha * source.green)
val targetB = ((1 - source.alpha) * background.blue) + (source.alpha * source.blue)
return rgb(targetR.roundToInt(), targetG.roundToInt(), targetB.roundToInt())
}
/**
* Lighten the color by the specified percent (between 0-100), returning a new instance of Color.
*
* @param percent the percent to lighten the Color
* @return a new lightened version of this color
*/
fun lighten(percent: Int): Color {
val isHSLA = value.startsWith("hsl", ignoreCase = true)
val hsla = if (isHSLA) fromHSLANotation() else toRGBA().asHSLA()
val lightness = hsla.lightness + (hsla.lightness * (normalizePercent(percent) / 100.0)).roundToInt()
val newHSLa = hsla.copy(lightness = normalizePercent(lightness))
return if (isHSLA) {
hsla(newHSLa.hue, newHSLa.saturation, newHSLa.lightness, newHSLa.alpha)
} else {
with(newHSLa.asRGBA()) { rgba(red, green, blue, alpha) }
}
}
/**
* Darken the color by the specified percent (between 0-100), returning a new instance of Color.
*
* @param percent the percent to darken the Color
* @return a new darkened version of this color
*/
fun darken(percent: Int): Color {
val isHSLA = value.startsWith("hsl", ignoreCase = true)
val hsla = if (isHSLA) fromHSLANotation() else toRGBA().asHSLA()
val darkness = hsla.lightness - (hsla.lightness * (normalizePercent(percent) / 100.0)).roundToInt()
val newHSLa = hsla.copy(lightness = normalizePercent(darkness))
return if (isHSLA) {
hsla(newHSLa.hue, newHSLa.saturation, newHSLa.lightness, newHSLa.alpha)
} else {
with(newHSLa.asRGBA()) { rgba(red, green, blue, alpha) }
}
}
/**
* Increase contrast, if lightness > 50 then darken else lighten
*
* @param percent the percent to lighten/darken the Color
* @return a new ligtened/darkened version of this color
*/
fun contrast(percent: Int): Color {
val isHSLA = value.startsWith("hsl", ignoreCase = true)
val hsla = if (isHSLA) fromHSLANotation() else toRGBA().asHSLA()
val darkness = if (hsla.lightness > 50) {
hsla.lightness - (hsla.lightness * (normalizePercent(percent) / 100.0)).roundToInt()
} else {
hsla.lightness + (hsla.lightness * (normalizePercent(percent) / 100.0)).roundToInt()
}
val newHSLa = hsla.copy(lightness = normalizePercent(darkness))
return if (isHSLA) {
hsla(newHSLa.hue, newHSLa.saturation, newHSLa.lightness, newHSLa.alpha)
} else {
with(newHSLa.asRGBA()) { rgba(red, green, blue, alpha) }
}
}
/**
* Saturate the color by the specified percent (between 0-100), returning a new instance of Color.
*
* @param percent the percent to saturate the Color
* @return a new saturated version of this color
*/
fun saturate(percent: Int): Color {
val isHSLA = value.startsWith("hsl", ignoreCase = true)
val hsla = if (isHSLA) fromHSLANotation() else toRGBA().asHSLA()
val saturation = hsla.saturation + (hsla.saturation * (normalizePercent(percent) / 100.0)).roundToInt()
val newHSLa = hsla.copy(saturation = normalizePercent(saturation))
return if (isHSLA) {
hsla(newHSLa.hue, newHSLa.saturation, newHSLa.lightness, newHSLa.alpha)
} else {
with(newHSLa.asRGBA()) { rgba(red, green, blue, alpha) }
}
}
/**
* Desaturate the color by the specified percent (between 0-100), returning a new instance of Color.
*
* @param percent the percent to desaturate the Color
* @return a new desaturated version of this color
*/
fun desaturate(percent: Int): Color {
val isHSLA = value.startsWith("hsl", ignoreCase = true)
val hsla = if (isHSLA) fromHSLANotation() else toRGBA().asHSLA()
val desaturation = hsla.saturation - (hsla.saturation * (normalizePercent(percent) / 100.0)).roundToInt()
val newHSLa = hsla.copy(saturation = normalizePercent(desaturation))
return if (isHSLA) {
hsla(newHSLa.hue, newHSLa.saturation, newHSLa.lightness, newHSLa.alpha)
} else {
with(newHSLa.asRGBA()) { rgba(red, green, blue, alpha) }
}
}
internal data class RGBA(
val red: Int,
val green: Int,
val blue: Int,
val alpha: Double = 1.0
) {
// Algorithm adapted from http://www.niwa.nu/2013/05/math-behind-colorspace-conversions-rgb-hsl/
fun asHSLA(): HSLA {
// scale R, G, B values into 0..1 fractions
val r = red / 255.0
val g = green / 255.0
val b = blue / 255.0
val cMax = maxOf(r, g, b)
val cMin = minOf(r, g, b)
val chroma = cMax - cMin
val lg = normalizeFractionalPercent((cMax + cMin) / 2)
val s = if (chroma != 0.0) normalizeFractionalPercent(chroma / (1.0 - abs((2.0 * lg) - 1.0))) else 0.0
val h = when (cMax) {
cMin -> 0.0
r -> 60 * (((g - b) / chroma) % 6.0)
g -> 60 * (((b - r) / chroma) + 2)
b -> 60 * (((r - g) / chroma) + 4)
else -> error("Unexpected value for max") // theoretically unreachable bc maxOf(r, g, b) above
}
return HSLA(normalizeHue(h), (s * 100).roundToInt(), (lg * 100).roundToInt(), alpha)
}
fun asHex(): String {
val result = StringBuilder()
result.append(red.toColorHex(2))
result.append(green.toColorHex(2))
result.append(blue.toColorHex(2))
return result.toString()
}
}
internal data class HSLA(
val hue: Int,
val saturation: Int,
val lightness: Int,
val alpha: Double = 1.0
) {
// Algorithm from W3C link referenced in class comment (section 4.2.4. HSL color values)
fun asRGBA(): RGBA {
fun hueToRGB(m1: Double, m2: Double, h: Double): Double {
val hu = if (h < 0) h + 1 else if (h > 1) h - 1 else h
return when {
(hu < 1.0 / 6) -> m1 + (m2 - m1) * 6 * hu
(hu < 1.0 / 2) -> m2
(hu < 2.0 / 3) -> m1 + ((m2 - m1) * 6 * (2.0 / 3 - hu))
else -> m1
}
}
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
val s = saturation / 100.0
val lg = lightness / 100.0
val m2 = if (lg < 0.5) lg * (1 + s) else (lg + s - lg * s)
val m1 = 2 * lg - m2
val r = normalizeFractionalPercent(hueToRGB(m1, m2, h + (1.0 / 3)))
val g = normalizeFractionalPercent(hueToRGB(m1, m2, h))
val b = normalizeFractionalPercent(hueToRGB(m1, m2, h - (1.0 / 3)))
return RGBA((r * 255).roundToInt(), (g * 255).roundToInt(), (b * 255).roundToInt(), alpha)
}
}
internal fun fromHSLANotation(): HSLA {
val match = HSLA_REGEX.find(value)
fun getHSLParameter(index: Int) =
match?.groups?.get(index)?.value
?: throw IllegalArgumentException("Expected hsl or hsla notation, got $value")
val hueShape = getHSLParameter(1)
val hue = normalizeHue(
when {
hueShape.endsWith("grad", true) -> hueShape.substringBefore("grad").toDouble() * (9.0 / 10)
hueShape.endsWith("rad", true) -> (hueShape.substringBefore("rad").toDouble() * 180) / PI
hueShape.endsWith("turn", true) -> hueShape.substringBefore("turn").toDouble() * 360.0
hueShape.endsWith("deg", true) -> hueShape.substringBefore("deg").toDouble()
else -> hueShape.toDouble()
}
)
val saturation = normalizePercent(getHSLParameter(2).toInt())
val lightness = normalizePercent(getHSLParameter(3).toInt())
val alpha = normalizeAlpha(match?.groups?.get(4)?.value?.toDouble() ?: 1.0)
return HSLA(hue, saturation, lightness, alpha)
}
internal fun fromRGBANotation(): RGBA {
val match = RGBA_REGEX.find(value)
fun getRGBParameter(index: Int): Int {
val group = match?.groups?.get(index)?.value
?: throw IllegalArgumentException("Expected rgb or rgba notation, got $value")
return when {
(group.endsWith('%')) -> (normalizeFractionalPercent(group.substringBefore('%').toDouble() / 100.0) * 255.0).toInt()
else -> normalizeRGB(group.toInt())
}
}
val red = getRGBParameter(1)
val green = getRGBParameter(2)
val blue = getRGBParameter(3)
val alpha = normalizeAlpha(match?.groups?.get(4)?.value?.toDouble() ?: 1.0)
return RGBA(red, green, blue, alpha)
}
internal fun toRGBA(): RGBA {
val v = rgb ?: value
return when {
v.startsWith("rgb") -> fromRGBANotation()
// Matches #rgb
v.startsWith("#") && v.length == 4 -> RGBA(
"${v[1]}${v[1]}".toInt(16),
"${v[2]}${v[2]}".toInt(16),
"${v[3]}${v[3]}".toInt(16)
)
// Matches both #rrggbb
v.startsWith("#") && v.length == 7 -> RGBA(
(v.substring(1..2)).toInt(16),
(v.substring(3..4)).toInt(16),
(v.substring(5..6)).toInt(16)
)
// Matches both #rrggbbaa
v.startsWith("#") && v.length == 9 -> RGBA(
(v.substring(1..2)).toInt(16),
(v.substring(3..4)).toInt(16),
(v.substring(5..6)).toInt(16),
(v.substring(7..8)).toInt(16) / 255.0
)
else -> throw IllegalArgumentException("Only hexadecimal, rgb, and rgba notations are accepted, got $v")
}
}
companion object { companion object {
val initial = Color("initial") val initial = Color("initial")
val inherit = Color("inherit") val inherit = Color("inherit")
@@ -219,270 +577,6 @@ class Color(value: String) : CssProperty(value) {
) )
} }
} }
/**
* withAlpha preserves existing alpha value: rgba(0, 0, 0, 0.5).withAlpha(0.1) = rgba(0, 0, 0, 0.05)
*/
fun withAlpha(alpha: Double) =
when {
value.startsWith("hsl", true) -> with(fromHSLANotation()) { hsla(hue, saturation, lightness, normalizeAlpha(alpha) * this.alpha) }
else -> with(toRGBA()) { rgba(red, green, blue, normalizeAlpha(alpha) * this.alpha) }
}
/**
* changeAlpha rewrites existing alpha value: rgba(0, 0, 0, 0.5).withAlpha(0.1) = rgba(0, 0, 0, 0.1)
*/
fun changeAlpha(alpha: Double) =
when {
value.startsWith("hsl", true) -> with(fromHSLANotation()) { hsla(hue, saturation, lightness, normalizeAlpha(alpha)) }
else -> with(toRGBA()) { rgba(red, green, blue, normalizeAlpha(alpha)) }
}
// https://stackoverflow.com/questions/2049230/convert-rgba-color-to-rgb
fun blend(backgroundColor: Color): Color {
val source = this.toRGBA()
val background = backgroundColor.toRGBA()
val targetR = ((1 - source.alpha) * background.red) + (source.alpha * source.red)
val targetG = ((1 - source.alpha) * background.green) + (source.alpha * source.green)
val targetB = ((1 - source.alpha) * background.blue) + (source.alpha * source.blue)
return rgb(targetR.roundToInt(), targetG.roundToInt(), targetB.roundToInt())
}
/**
* Lighten the color by the specified percent (between 0-100), returning a new instance of Color.
*
* @param percent the percent to lighten the Color
* @return a new lightened version of this color
*/
fun lighten(percent: Int): Color {
val isHSLA = value.startsWith("hsl", ignoreCase = true)
val hsla = if (isHSLA) fromHSLANotation() else toRGBA().asHSLA()
val lightness = hsla.lightness + (hsla.lightness * (normalizePercent(percent) / 100.0)).roundToInt()
val newHSLa = hsla.copy(lightness = normalizePercent(lightness))
return if (isHSLA) {
hsla(newHSLa.hue, newHSLa.saturation, newHSLa.lightness, newHSLa.alpha)
} else {
with(newHSLa.asRGBA()) { rgba(red, green, blue, alpha) }
}
}
/**
* Darken the color by the specified percent (between 0-100), returning a new instance of Color.
*
* @param percent the percent to darken the Color
* @return a new darkened version of this color
*/
fun darken(percent: Int): Color {
val isHSLA = value.startsWith("hsl", ignoreCase = true)
val hsla = if (isHSLA) fromHSLANotation() else toRGBA().asHSLA()
val darkness = hsla.lightness - (hsla.lightness * (normalizePercent(percent) / 100.0)).roundToInt()
val newHSLa = hsla.copy(lightness = normalizePercent(darkness))
return if (isHSLA) {
hsla(newHSLa.hue, newHSLa.saturation, newHSLa.lightness, newHSLa.alpha)
} else {
with(newHSLa.asRGBA()) { rgba(red, green, blue, alpha) }
}
}
/**
* Increase contrast, if lightness > 50 then darken else lighten
*
* @param percent the percent to lighten/darken the Color
* @return a new ligtened/darkened version of this color
*/
fun contrast(percent: Int): Color {
val isHSLA = value.startsWith("hsl", ignoreCase = true)
val hsla = if (isHSLA) fromHSLANotation() else toRGBA().asHSLA()
val darkness = if (hsla.lightness > 50) {
hsla.lightness - (hsla.lightness * (normalizePercent(percent) / 100.0)).roundToInt()
} else {
hsla.lightness + (hsla.lightness * (normalizePercent(percent) / 100.0)).roundToInt()
}
val newHSLa = hsla.copy(lightness = normalizePercent(darkness))
return if (isHSLA) {
hsla(newHSLa.hue, newHSLa.saturation, newHSLa.lightness, newHSLa.alpha)
} else {
with(newHSLa.asRGBA()) { rgba(red, green, blue, alpha) }
}
}
/**
* Saturate the color by the specified percent (between 0-100), returning a new instance of Color.
*
* @param percent the percent to saturate the Color
* @return a new saturated version of this color
*/
fun saturate(percent: Int): Color {
val isHSLA = value.startsWith("hsl", ignoreCase = true)
val hsla = if (isHSLA) fromHSLANotation() else toRGBA().asHSLA()
val saturation = hsla.saturation + (hsla.saturation * (normalizePercent(percent) / 100.0)).roundToInt()
val newHSLa = hsla.copy(saturation = normalizePercent(saturation))
return if (isHSLA) {
hsla(newHSLa.hue, newHSLa.saturation, newHSLa.lightness, newHSLa.alpha)
} else {
with(newHSLa.asRGBA()) { rgba(red, green, blue, alpha) }
}
}
/**
* Desaturate the color by the specified percent (between 0-100), returning a new instance of Color.
*
* @param percent the percent to desaturate the Color
* @return a new desaturated version of this color
*/
fun desaturate(percent: Int): Color {
val isHSLA = value.startsWith("hsl", ignoreCase = true)
val hsla = if (isHSLA) fromHSLANotation() else toRGBA().asHSLA()
val desaturation = hsla.saturation - (hsla.saturation * (normalizePercent(percent) / 100.0)).roundToInt()
val newHSLa = hsla.copy(saturation = normalizePercent(desaturation))
return if (isHSLA) {
hsla(newHSLa.hue, newHSLa.saturation, newHSLa.lightness, newHSLa.alpha)
} else {
with(newHSLa.asRGBA()) { rgba(red, green, blue, alpha) }
}
}
internal data class RGBA(
val red: Int,
val green: Int,
val blue: Int,
val alpha: Double = 1.0
) {
// Algorithm adapted from http://www.niwa.nu/2013/05/math-behind-colorspace-conversions-rgb-hsl/
fun asHSLA(): HSLA {
// scale R, G, B values into 0..1 fractions
val r = red / 255.0
val g = green / 255.0
val b = blue / 255.0
val cMax = maxOf(r, g, b)
val cMin = minOf(r, g, b)
val chroma = cMax - cMin
val lg = normalizeFractionalPercent((cMax + cMin) / 2)
val s = if (chroma != 0.0) normalizeFractionalPercent(chroma / (1.0 - abs((2.0 * lg) - 1.0))) else 0.0
val h = when (cMax) {
cMin -> 0.0
r -> 60 * (((g - b) / chroma) % 6.0)
g -> 60 * (((b - r) / chroma) + 2)
b -> 60 * (((r - g) / chroma) + 4)
else -> error("Unexpected value for max") // theoretically unreachable bc maxOf(r, g, b) above
}
return HSLA(normalizeHue(h), (s * 100).roundToInt(), (lg * 100).roundToInt(), alpha)
}
}
internal data class HSLA(
val hue: Int,
val saturation: Int,
val lightness: Int,
val alpha: Double = 1.0
) {
// Algorithm from W3C link referenced in class comment (section 4.2.4. HSL color values)
fun asRGBA(): RGBA {
fun hueToRGB(m1: Double, m2: Double, h: Double): Double {
val hu = if (h < 0) h + 1 else if (h > 1) h - 1 else h
return when {
(hu < 1.0 / 6) -> m1 + (m2 - m1) * 6 * hu
(hu < 1.0 / 2) -> m2
(hu < 2.0 / 3) -> m1 + ((m2 - m1) * 6 * (2.0 / 3 - hu))
else -> m1
}
}
if (saturation == 0) return RGBA(lightness, lightness, lightness)
// scale H, S, V values into 0..1 fractions
val h = (hue % 360.0) / 360.0
val s = saturation / 100.0
val lg = lightness / 100.0
val m2 = if (lg < 0.5) lg * (1 + s) else (lg + s - lg * s)
val m1 = 2 * lg - m2
val r = normalizeFractionalPercent(hueToRGB(m1, m2, h + (1.0 / 3)))
val g = normalizeFractionalPercent(hueToRGB(m1, m2, h))
val b = normalizeFractionalPercent(hueToRGB(m1, m2, h - (1.0 / 3)))
return RGBA((r * 255).roundToInt(), (g * 255).roundToInt(), (b * 255).roundToInt(), alpha)
}
}
internal fun fromHSLANotation(): HSLA {
val match = HSLA_REGEX.find(value)
fun getHSLParameter(index: Int) =
match?.groups?.get(index)?.value
?: throw IllegalArgumentException("Expected hsl or hsla notation, got $value")
val hueShape = getHSLParameter(1)
val hue = normalizeHue(
when {
hueShape.endsWith("grad", true) -> hueShape.substringBefore("grad").toDouble() * (9.0 / 10)
hueShape.endsWith("rad", true) -> (hueShape.substringBefore("rad").toDouble() * 180) / PI
hueShape.endsWith("turn", true) -> hueShape.substringBefore("turn").toDouble() * 360.0
hueShape.endsWith("deg", true) -> hueShape.substringBefore("deg").toDouble()
else -> hueShape.toDouble()
}
)
val saturation = normalizePercent(getHSLParameter(2).toInt())
val lightness = normalizePercent(getHSLParameter(3).toInt())
val alpha = normalizeAlpha(match?.groups?.get(4)?.value?.toDouble() ?: 1.0)
return HSLA(hue, saturation, lightness, alpha)
}
internal fun fromRGBANotation(): RGBA {
val match = RGBA_REGEX.find(value)
fun getRGBParameter(index: Int): Int {
val group = match?.groups?.get(index)?.value
?: throw IllegalArgumentException("Expected rgb or rgba notation, got $value")
return when {
(group.endsWith('%')) -> (normalizeFractionalPercent(group.substringBefore('%').toDouble() / 100.0) * 255.0).toInt()
else -> normalizeRGB(group.toInt())
}
}
val red = getRGBParameter(1)
val green = getRGBParameter(2)
val blue = getRGBParameter(3)
val alpha = normalizeAlpha(match?.groups?.get(4)?.value?.toDouble() ?: 1.0)
return RGBA(red, green, blue, alpha)
}
internal fun toRGBA(): RGBA {
val v = rgb ?: value
return when {
v.startsWith("rgb") -> fromRGBANotation()
// Matches #rgb
v.startsWith("#") && v.length == 4 -> RGBA(
"${v[1]}${v[1]}".toInt(16),
"${v[2]}${v[2]}".toInt(16),
"${v[3]}${v[3]}".toInt(16)
)
// Matches both #rrggbb and #rrggbbaa
v.startsWith("#") && (v.length == 7 || v.length == 9) -> RGBA(
(v.substring(1..2)).toInt(16),
(v.substring(3..4)).toInt(16),
(v.substring(5..6)).toInt(16)
)
else -> throw IllegalArgumentException("Only hexadecimal, rgb, and rgba notations are accepted, got $v")
}
}
} }
private fun String.withZeros() = this + "0".repeat(max(0, 3 - this.length)) private fun String.withZeros() = this + "0".repeat(max(0, 3 - this.length))
@@ -491,6 +585,8 @@ fun rgb(red: Int, green: Int, blue: Int) = Color("rgb($red, $green, $blue)")
fun rgba(red: Int, green: Int, blue: Int, alpha: Double) = Color("rgba($red, $green, $blue, ${formatAlpha(alpha)})") fun rgba(red: Int, green: Int, blue: Int, alpha: Double) = Color("rgba($red, $green, $blue, ${formatAlpha(alpha)})")
fun hsl(hue: Int, saturation: Int, lightness: Int) = Color("hsl($hue, $saturation%, $lightness%)") fun hsl(hue: Int, saturation: Int, lightness: Int) = Color("hsl($hue, $saturation%, $lightness%)")
fun hsla(hue: Int, saturation: Int, lightness: Int, alpha: Double) = Color("hsla($hue, $saturation%, $lightness%, ${formatAlpha(alpha)})") fun hsla(hue: Int, saturation: Int, lightness: Int, alpha: Double) = Color("hsla($hue, $saturation%, $lightness%, ${formatAlpha(alpha)})")
fun oklch(lightness: Int, chroma: Double, hue: Double) = Color("oklch($lightness% $chroma $hue)")
fun oklch(lightness: Int, chroma: Double, hue: Double, alpha: Double) = Color("oklch($lightness% $chroma $hue / ${formatAlpha(alpha)})")
fun blackAlpha(alpha: Double) = Color.black.withAlpha(alpha) fun blackAlpha(alpha: Double) = Color.black.withAlpha(alpha)
fun whiteAlpha(alpha: Double) = Color.white.withAlpha(alpha) fun whiteAlpha(alpha: Double) = Color.white.withAlpha(alpha)

View File

@@ -1,33 +1,33 @@
package nl.astraeus.css.properties package nl.astraeus.css.properties
class Length( class Length(
value: String value: String
): CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
fun px(nr: Int) = Length("${nr}px") fun px(nr: Int) = Length("${nr}px")
fun em(nr: Int) = Length("${nr}em") fun em(nr: Int) = Length("${nr}em")
fun em(nr: Double) = Length("${nr}em") fun em(nr: Double) = Length("${nr}em")
fun perc(nr: Int) = Length("${nr}%") fun perc(nr: Int) = Length("${nr}%")
fun perc(nr: Double) = Length("${nr}%") fun perc(nr: Double) = Length("${nr}%")
fun pc(nr: Int) = Length("${nr}pc") fun pc(nr: Int) = Length("${nr}pc")
fun pc(nr: Double) = Length("${nr}pc") fun pc(nr: Double) = Length("${nr}pc")
fun cm(nr: Int) = Length("${nr}cm") fun cm(nr: Int) = Length("${nr}cm")
fun cm(nr: Double) = Length("${nr}cm") fun cm(nr: Double) = Length("${nr}cm")
val initial = Length("initial") val initial = Length("initial")
val inherit = Length("inherit") val inherit = Length("inherit")
} }
} }
class Fill( class Fill(
value: String value: String
) : CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val balance = Fill("balance") val balance = Fill("balance")
val auto = Fill("auto") val auto = Fill("auto")
val initial = Fill("initial") val initial = Fill("initial")
val inherit = Fill("inherit") val inherit = Fill("inherit")
} }
} }

View File

@@ -1,23 +1,23 @@
package nl.astraeus.css.properties package nl.astraeus.css.properties
class Content( class Content(
value: String value: String
) : CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val normal = Content("normal") val normal = Content("normal")
val none = Content("none") val none = Content("none")
val counter = Content("counter") val counter = Content("counter")
val openQuote = Content("open-quote") val openQuote = Content("open-quote")
val closeQuote = Content("close-quote") val closeQuote = Content("close-quote")
val noOpenQuote = Content("no-open-quote") val noOpenQuote = Content("no-open-quote")
val noCloseQuote = Content("no-close-quote") val noCloseQuote = Content("no-close-quote")
val initial = Content("initial") val initial = Content("initial")
val inherit = Content("inherit") val inherit = Content("inherit")
fun attr(attribute: String) = Content("attr($attribute)") fun attr(attribute: String) = Content("attr($attribute)")
fun string(txt: String) = Content("\"$txt\"") fun string(txt: String) = Content("\"$txt\"")
fun url(url: String) = Content("url($url)") fun url(url: String) = Content("url($url)")
} }
} }

View File

@@ -1,15 +1,15 @@
package nl.astraeus.css.properties package nl.astraeus.css.properties
class Count( class Count(
value: String value: String
) : CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val auto: Count = Count("auto") val auto: Count = Count("auto")
val infinite: Count = Count("infinite") val infinite: Count = Count("infinite")
val initial: Count = Count("initial") val initial: Count = Count("initial")
val inherit: Count = Count("inherit") val inherit: Count = Count("inherit")
fun count(number: Int): Count = Count("$number") fun count(number: Int): Count = Count("$number")
} }
} }

View File

@@ -1,15 +1,15 @@
package nl.astraeus.css.properties package nl.astraeus.css.properties
class CssFloat( class CssFloat(
value: String value: String
) : CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val none = CssFloat("none") val none = CssFloat("none")
val left = CssFloat("left") val left = CssFloat("left")
val right = CssFloat("right") val right = CssFloat("right")
val initial = CssFloat("initial") val initial = CssFloat("initial")
val inherit = CssFloat("inherit") val inherit = CssFloat("inherit")
} }
} }

View File

@@ -1,19 +1,20 @@
package nl.astraeus.css.properties package nl.astraeus.css.properties
interface CssValue { interface CssValue {
fun css(): String fun css(): String
} }
open class CssProperty( open class CssProperty(
var value: String var value: String
): CssValue { ) : CssValue {
override fun css(): String = value override fun css(): String = value
override fun toString(): String = value
} }
fun text(value: String) = TextProperty(value) fun text(value: String) = TextProperty(value)
class TextProperty( class TextProperty(
value: String value: String
): CssProperty(value) ) : CssProperty(value)

View File

@@ -1,14 +1,14 @@
package nl.astraeus.css.properties package nl.astraeus.css.properties
class DelayDuration( class DelayDuration(
value: String value: String
) : CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val initial = DelayDuration("initial") val initial = DelayDuration("initial")
val inherit = DelayDuration("inherit") val inherit = DelayDuration("inherit")
fun seconds(seconds: Int) = DelayDuration("${seconds}s") fun seconds(seconds: Int) = DelayDuration("${seconds}s")
fun millis(milliSeconds: Int) = DelayDuration("${milliSeconds}ms") fun millis(milliSeconds: Int) = DelayDuration("${milliSeconds}ms")
} }
} }

View File

@@ -1,14 +1,14 @@
package nl.astraeus.css.properties package nl.astraeus.css.properties
class Direction( class Direction(
value: String value: String
) : CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val ltr = Direction("ltr") val ltr = Direction("ltr")
val rtl = Direction("rtl") val rtl = Direction("rtl")
val initial = Direction("initial") val initial = Direction("initial")
val inherit = Direction("inherit") val inherit = Direction("inherit")
} }
} }

View File

@@ -1,33 +1,33 @@
package nl.astraeus.css.properties package nl.astraeus.css.properties
class Display( class Display(
value: String value: String
) : CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val inline = Display("inline") val inline = Display("inline")
val block = Display("block") val block = Display("block")
val contents = Display("contents") val contents = Display("contents")
val flex = Display("flex") val flex = Display("flex")
val grid = Display("grid") val grid = Display("grid")
val inlineBlock = Display("inline-block") val inlineBlock = Display("inline-block")
val inlineFlex = Display("inline-flex") val inlineFlex = Display("inline-flex")
val inlineGrid = Display("inline-grid") val inlineGrid = Display("inline-grid")
val inlineTable = Display("inline-table") val inlineTable = Display("inline-table")
val listItem = Display("list-item") val listItem = Display("list-item")
val runIn = Display("run-in") val runIn = Display("run-in")
val table = Display("table") val table = Display("table")
val tableCaption = Display("table-caption") val tableCaption = Display("table-caption")
val tableColumnGroup = Display("table-column-group") val tableColumnGroup = Display("table-column-group")
val tableHeaderGroup = Display("table-header-group") val tableHeaderGroup = Display("table-header-group")
val tableFooterGroup = Display("table-footer-group") val tableFooterGroup = Display("table-footer-group")
val tableRowGroup = Display("table-row-group") val tableRowGroup = Display("table-row-group")
val tableCell = Display("table-cell") val tableCell = Display("table-cell")
val tableColumn = Display("table-column") val tableColumn = Display("table-column")
val tableRow = Display("table-row") val tableRow = Display("table-row")
val none = Display("none") val none = Display("none")
val initial = Display("initial") val initial = Display("initial")
val inherit = Display("inherit") val inherit = Display("inherit")
} }
} }

View File

@@ -1,14 +1,14 @@
package nl.astraeus.css.properties package nl.astraeus.css.properties
class EmptyCells( class EmptyCells(
value: String value: String
) : CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val show = EmptyCells("show") val show = EmptyCells("show")
val hide = EmptyCells("hide") val hide = EmptyCells("hide")
val initial = EmptyCells("initial") val initial = EmptyCells("initial")
val inherit = EmptyCells("inherit") val inherit = EmptyCells("inherit")
} }
} }

View File

@@ -1,43 +1,43 @@
package nl.astraeus.css.properties package nl.astraeus.css.properties
class FlexDirection( class FlexDirection(
value: String value: String
) : CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val row = FlexDirection("row") val row = FlexDirection("row")
val rowReverse = FlexDirection("row-reverse") val rowReverse = FlexDirection("row-reverse")
val column = FlexDirection("column") val column = FlexDirection("column")
val columnReverse = FlexDirection("column-reverse") val columnReverse = FlexDirection("column-reverse")
val initial = FlexDirection("initial") val initial = FlexDirection("initial")
val inherit = FlexDirection("inherit") val inherit = FlexDirection("inherit")
} }
} }
class FlexGrowShrink( class FlexGrowShrink(
value: String value: String
) : CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val initial = FlexGrowShrink("initial") val initial = FlexGrowShrink("initial")
val inherit = FlexGrowShrink("inherit") val inherit = FlexGrowShrink("inherit")
fun number(number: Int) = FlexGrowShrink("$number") fun number(number: Int) = FlexGrowShrink("$number")
} }
} }
class FlexWrap( class FlexWrap(
value: String value: String
) : CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val nowrap = FlexWrap("nowrap") val nowrap = FlexWrap("nowrap")
val wrap = FlexWrap("wrap") val wrap = FlexWrap("wrap")
val wrapReverse = FlexWrap("wrap-reverse") val wrapReverse = FlexWrap("wrap-reverse")
val initial = FlexWrap("initial") val initial = FlexWrap("initial")
val inherit = FlexWrap("inherit") val inherit = FlexWrap("inherit")
} }
} }

View File

@@ -1,142 +1,142 @@
package nl.astraeus.css.properties package nl.astraeus.css.properties
class FontSize( class FontSize(
value: String value: String
) : CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val xxSmall = FontSize("xx-small") val xxSmall = FontSize("xx-small")
val xSmall = FontSize("x-small") val xSmall = FontSize("x-small")
val small = FontSize("small") val small = FontSize("small")
val medium = FontSize("medium") val medium = FontSize("medium")
val large = FontSize("large") val large = FontSize("large")
val xLarge = FontSize("x-large") val xLarge = FontSize("x-large")
val xxLarge = FontSize("xx-large") val xxLarge = FontSize("xx-large")
val smaller = FontSize("smaller") val smaller = FontSize("smaller")
val larger = FontSize("larger") val larger = FontSize("larger")
val initial = FontSize("initial") val initial = FontSize("initial")
val inherit = FontSize("inherit") val inherit = FontSize("inherit")
fun px(nr: Int) = FontSize("${nr}px") fun px(nr: Int) = FontSize("${nr}px")
fun em(nr: Int) = FontSize("${nr}em") fun em(nr: Int) = FontSize("${nr}em")
fun em(nr: Double) = FontSize("${nr}em") fun em(nr: Double) = FontSize("${nr}em")
fun perc(nr: Int) = FontSize("${nr}%") fun perc(nr: Int) = FontSize("${nr}%")
fun perc(nr: Double) = FontSize("${nr}%") fun perc(nr: Double) = FontSize("${nr}%")
fun pc(nr: Int) = FontSize("${nr}pc") fun pc(nr: Int) = FontSize("${nr}pc")
fun pc(nr: Double) = FontSize("${nr}pc") fun pc(nr: Double) = FontSize("${nr}pc")
fun cm(nr: Int) = FontSize("${nr}cm") fun cm(nr: Int) = FontSize("${nr}cm")
fun cm(nr: Double) = FontSize("${nr}cm") fun cm(nr: Double) = FontSize("${nr}cm")
} }
} }
class FontStretch( class FontStretch(
value: String value: String
) : CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val normal = FontStretch("normal") val normal = FontStretch("normal")
val condensed = FontStretch("condensed") val condensed = FontStretch("condensed")
val ultraCondensed = FontStretch("ultra-condensed") val ultraCondensed = FontStretch("ultra-condensed")
val extraCondensed = FontStretch("extra-condensed") val extraCondensed = FontStretch("extra-condensed")
val semiCondensed = FontStretch("semi-condensed") val semiCondensed = FontStretch("semi-condensed")
val expanded = FontStretch("expanded") val expanded = FontStretch("expanded")
val semiExpanded = FontStretch("semi-expanded") val semiExpanded = FontStretch("semi-expanded")
val extraExpanded = FontStretch("extra-expanded") val extraExpanded = FontStretch("extra-expanded")
val ultraExpanded = FontStretch("ultra-expanded") val ultraExpanded = FontStretch("ultra-expanded")
val initial = FontWeight("initial") val initial = FontWeight("initial")
val inherit = FontWeight("inherit") val inherit = FontWeight("inherit")
} }
} }
class FontStyle( class FontStyle(
value: String value: String
) : CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val normal = FontStyle("normal") val normal = FontStyle("normal")
val italic = FontStyle("italic") val italic = FontStyle("italic")
val oblique = FontStyle("oblique") val oblique = FontStyle("oblique")
val initial = FontStyle("initial") val initial = FontStyle("initial")
val inherit = FontStyle("inherit") val inherit = FontStyle("inherit")
} }
} }
class FontWeight( class FontWeight(
value: String value: String
) : CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val normal = FontWeight("normal") val normal = FontWeight("normal")
val bold = FontWeight("bold") val bold = FontWeight("bold")
val _100 = FontWeight("100") val _100 = FontWeight("100")
val _200 = FontWeight("200") val _200 = FontWeight("200")
val _300 = FontWeight("300") val _300 = FontWeight("300")
val _400 = FontWeight("400") val _400 = FontWeight("400")
val _500 = FontWeight("500") val _500 = FontWeight("500")
val _600 = FontWeight("600") val _600 = FontWeight("600")
val _700 = FontWeight("700") val _700 = FontWeight("700")
val _800 = FontWeight("800") val _800 = FontWeight("800")
val _900 = FontWeight("900") val _900 = FontWeight("900")
val initial = FontWeight("initial") val initial = FontWeight("initial")
val inherit = FontWeight("inherit") val inherit = FontWeight("inherit")
} }
} }
class FontKerning( class FontKerning(
value: String value: String
) : CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val auto = FontKerning("auto") val auto = FontKerning("auto")
val normal = FontKerning("normal") val normal = FontKerning("normal")
val none = FontKerning("none") val none = FontKerning("none")
} }
} }
class FontSizeAdjust( class FontSizeAdjust(
value: String value: String
) : CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val none = FontSizeAdjust("none") val none = FontSizeAdjust("none")
val initial = FontSizeAdjust("initial") val initial = FontSizeAdjust("initial")
val inherit = FontSizeAdjust("inherit") val inherit = FontSizeAdjust("inherit")
} }
} }
class FontVariant( class FontVariant(
value: String value: String
) : CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val normal = FontVariant("normal") val normal = FontVariant("normal")
val smallCaps = FontVariant("small-caps") val smallCaps = FontVariant("small-caps")
val initial = FontVariant("initial") val initial = FontVariant("initial")
val inherit = FontVariant("inherit") val inherit = FontVariant("inherit")
} }
} }
class FontVariantCaps( class FontVariantCaps(
value: String value: String
) : CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val normal = FontVariantCaps("normal") val normal = FontVariantCaps("normal")
val smallCaps = FontVariantCaps("small-caps") val smallCaps = FontVariantCaps("small-caps")
val allSmallCaps = FontVariantCaps("all-small-caps") val allSmallCaps = FontVariantCaps("all-small-caps")
val petiteCaps = FontVariantCaps("petite-caps") val petiteCaps = FontVariantCaps("petite-caps")
val allPetiteCaps = FontVariantCaps("all-petite-caps") val allPetiteCaps = FontVariantCaps("all-petite-caps")
val unicase = FontVariantCaps("unicase") val unicase = FontVariantCaps("unicase")
val initial = FontVariantCaps("initial") val initial = FontVariantCaps("initial")
val inherit = FontVariantCaps("inherit") val inherit = FontVariantCaps("inherit")
val unset = FontVariantCaps("unset") val unset = FontVariantCaps("unset")
} }
} }

View File

@@ -2,71 +2,71 @@ package nl.astraeus.css.properties
class Grid( class Grid(
value: String value: String
) : CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val none = Grid("none") val none = Grid("none")
val initial = Grid("initial") val initial = Grid("initial")
val inherit = Grid("inherit") val inherit = Grid("inherit")
} }
} }
class GridAuto( class GridAuto(
value: String value: String
) : CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val auto = GridAuto("auto") val auto = GridAuto("auto")
val maxContent = GridAuto("max-content") val maxContent = GridAuto("max-content")
val minContent = GridAuto("min-content") val minContent = GridAuto("min-content")
} }
} }
class GridFlow( class GridFlow(
value: String value: String
) : CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val row = GridFlow("row") val row = GridFlow("row")
val column = GridFlow("column") val column = GridFlow("column")
val dense = GridFlow("dense") val dense = GridFlow("dense")
val rowDense = GridFlow("row dense") val rowDense = GridFlow("row dense")
val columnDense = GridFlow("column dense") val columnDense = GridFlow("column dense")
} }
} }
class GridValue( class GridValue(
value: String value: String
) : CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val auto = GridValue("auto") val auto = GridValue("auto")
fun span(column: Int) = GridValue("span $column") fun span(column: Int) = GridValue("span $column")
fun column(line: Int) = GridValue("$line") fun column(line: Int) = GridValue("$line")
fun row(line: Int) = GridValue("$line") fun row(line: Int) = GridValue("$line")
} }
} }
class TemplateRowColumn( class TemplateRowColumn(
value: String value: String
) : CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val none = GridValue("none") val none = TemplateRowColumn("none")
val auto = GridValue("auto") val auto = TemplateRowColumn("auto")
val maxContent = GridValue("max-content") val maxContent = TemplateRowColumn("max-content")
val minContent = GridValue("min-content") val minContent = TemplateRowColumn("min-content")
val initial = GridValue("initial") val initial = TemplateRowColumn("initial")
val inherit = GridValue("inherit") val inherit = TemplateRowColumn("inherit")
fun length(length: Measurement) = GridValue(length.value) fun length(length: Measurement) = TemplateRowColumn(length.value)
} }
} }

View File

@@ -1,15 +1,15 @@
package nl.astraeus.css.properties package nl.astraeus.css.properties
class Hyphens( class Hyphens(
value: String value: String
) : CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val none = Hyphens("none") val none = Hyphens("none")
val manual = Hyphens("manual") val manual = Hyphens("manual")
val auto = Hyphens("auto") val auto = Hyphens("auto")
val initial = Hyphens("initial") val initial = Hyphens("initial")
val inherit = Hyphens("inherit") val inherit = Hyphens("inherit")
} }
} }

View File

@@ -1,62 +1,62 @@
package nl.astraeus.css.properties package nl.astraeus.css.properties
class Image( class Image(
value: String value: String
) : CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val none = Image("none") val none = Image("none")
val initial = Image("initial") val initial = Image("initial")
val inherit = Image("inherit") val inherit = Image("inherit")
fun url(url: String) = Image("url($url)") fun url(url: String) = Image("url($url)")
} }
} }
class ImageRepeat( class ImageRepeat(
value: String value: String
) : CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val repeat = ImageRepeat("repeat") val repeat = ImageRepeat("repeat")
val round = ImageRepeat("round") val round = ImageRepeat("round")
val initial = ImageRepeat("initial") val initial = ImageRepeat("initial")
val inherit = ImageRepeat("inherit") val inherit = ImageRepeat("inherit")
fun stretch(url: String) = ImageRepeat("stretch") fun stretch(url: String) = ImageRepeat("stretch")
} }
} }
class ImageSlice( class ImageSlice(
value: String value: String
) : CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val repeat = ImageSlice("repeat") val repeat = ImageSlice("repeat")
val fill = ImageSlice("fill") val fill = ImageSlice("fill")
val initial = ImageSlice("initial") val initial = ImageSlice("initial")
val inherit = ImageSlice("inherit") val inherit = ImageSlice("inherit")
fun nr(nr: Int) = ImageSlice("$nr") fun nr(nr: Int) = ImageSlice("$nr")
fun perc(perc: Int) = ImageSlice("$perc%") fun perc(perc: Int) = ImageSlice("$perc%")
fun perc(perc: Double) = ImageSlice("$perc%") fun perc(perc: Double) = ImageSlice("$perc%")
fun stretch(url: String) = ImageSlice("stretch") fun stretch(url: String) = ImageSlice("stretch")
} }
} }
class ImageSource( class ImageSource(
value: String value: String
) : CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val none = ImageSource("none") val none = ImageSource("none")
val initial = ImageSource("initial") val initial = ImageSource("initial")
val inherit = ImageSource("inherit") val inherit = ImageSource("inherit")
fun text(txt: String) = ImageSource(txt) fun text(txt: String) = ImageSource(txt)
fun image(url: String) = ImageSource("'$url'") fun image(url: String) = ImageSource("'$url'")
} }
} }

View File

@@ -1,12 +1,12 @@
package nl.astraeus.css.properties package nl.astraeus.css.properties
class InitialInherit( class InitialInherit(
value: String value: String
) : CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val initial = InitialInherit("initial") val initial = InitialInherit("initial")
val inherit = InitialInherit("inherit") val inherit = InitialInherit("inherit")
} }
} }

View File

@@ -1,14 +1,14 @@
package nl.astraeus.css.properties package nl.astraeus.css.properties
class Isolation( class Isolation(
value: String value: String
) : CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val auto = Isolation("auto") val auto = Isolation("auto")
val isolate = Isolation("isolate") val isolate = Isolation("isolate")
val initial = Isolation("initial") val initial = Isolation("initial")
val inherit = Isolation("inherit") val inherit = Isolation("inherit")
} }
} }

View File

@@ -1,17 +1,17 @@
package nl.astraeus.css.properties package nl.astraeus.css.properties
class JustifyContent( class JustifyContent(
value: String value: String
) : CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val flexStart = JustifyContent("flex-start") val flexStart = JustifyContent("flex-start")
val flexEnd = JustifyContent("flex-end") val flexEnd = JustifyContent("flex-end")
val center = JustifyContent("center") val center = JustifyContent("center")
val spaceBetween = JustifyContent("space-between") val spaceBetween = JustifyContent("space-between")
val spaceAround = JustifyContent("space-around") val spaceAround = JustifyContent("space-around")
val initial = JustifyContent("initial") val initial = JustifyContent("initial")
val inherit = JustifyContent("inherit") val inherit = JustifyContent("inherit")
} }
} }

View File

@@ -1,13 +1,13 @@
package nl.astraeus.css.properties package nl.astraeus.css.properties
class LetterSpacing( class LetterSpacing(
value: String value: String
) : CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val normal = LetterSpacing("normal") val normal = LetterSpacing("normal")
val initial = LetterSpacing("initial") val initial = LetterSpacing("initial")
val inherit = LetterSpacing("inherit") val inherit = LetterSpacing("inherit")
} }
} }

View File

@@ -2,47 +2,47 @@ package nl.astraeus.css.properties
class ListStylePosition( class ListStylePosition(
value: String value: String
) : CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val inside = ListStylePosition("inside") val inside = ListStylePosition("inside")
val outside = ListStylePosition("outside") val outside = ListStylePosition("outside")
val initial = ListStylePosition("initial") val initial = ListStylePosition("initial")
val inherit = ListStylePosition("inherit") val inherit = ListStylePosition("inherit")
} }
} }
class ListStyleType( class ListStyleType(
value: String value: String
) : CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val disc = ListStyleType("disc") val disc = ListStyleType("disc")
val armenian = ListStyleType("armenian") val armenian = ListStyleType("armenian")
val circle = ListStyleType("circle") val circle = ListStyleType("circle")
val cjkIdeographic = ListStyleType("cjk-ideographic") val cjkIdeographic = ListStyleType("cjk-ideographic")
val decimal = ListStyleType("decimal") val decimal = ListStyleType("decimal")
val decimalLeadingZero = ListStyleType("decimal-leading-zero") val decimalLeadingZero = ListStyleType("decimal-leading-zero")
val georgian = ListStyleType("georgian") val georgian = ListStyleType("georgian")
val hebrew = ListStyleType("hebrew") val hebrew = ListStyleType("hebrew")
val hiragana = ListStyleType("hiragana") val hiragana = ListStyleType("hiragana")
val hiraganaIroha = ListStyleType("hiragana-iroha") val hiraganaIroha = ListStyleType("hiragana-iroha")
val katakana = ListStyleType("katakana") val katakana = ListStyleType("katakana")
val katakanaIroha = ListStyleType("katakana-iroha") val katakanaIroha = ListStyleType("katakana-iroha")
val lowerAlpha = ListStyleType("lower-alpha") val lowerAlpha = ListStyleType("lower-alpha")
val lowerGreek = ListStyleType("lower-greek") val lowerGreek = ListStyleType("lower-greek")
val lowerLatin = ListStyleType("lower-latin") val lowerLatin = ListStyleType("lower-latin")
val lowerRoman = ListStyleType("lower-roman") val lowerRoman = ListStyleType("lower-roman")
val none = ListStyleType("none") val none = ListStyleType("none")
val square = ListStyleType("square") val square = ListStyleType("square")
val upperAlpha = ListStyleType("upper-alpha") val upperAlpha = ListStyleType("upper-alpha")
val upperGreek = ListStyleType("upper-greek") val upperGreek = ListStyleType("upper-greek")
val upperLatin = ListStyleType("upper-latin") val upperLatin = ListStyleType("upper-latin")
val upperRoman = ListStyleType("upper-roman") val upperRoman = ListStyleType("upper-roman")
val initial = ListStyleType("initial") val initial = ListStyleType("initial")
val inherit = ListStyleType("inherit") val inherit = ListStyleType("inherit")
} }
} }

View File

@@ -1,60 +1,112 @@
package nl.astraeus.css.properties package nl.astraeus.css.properties
enum class MeasurementUoM {
NONE,
PX,
EM,
REL,
REM,
PC,
PRC,
CM,
FR,
VH,
VW
}
open class Measurement( open class Measurement(
value: String value: String,
) : CssProperty(value) { val uom: MeasurementUoM = MeasurementUoM.NONE
) : CssProperty(value), CalcExpression {
companion object { override fun toString(): String = super.value
val auto = Measurement("auto")
val initial = Measurement("initial")
val inherit = Measurement("inherit")
val normal = Measurement("normal")
fun px(nr: Int) = if (nr == 0) { Measurement("0") } else { Measurement("${nr}px") } companion object {
fun px(nr: Double) = nr.px val auto = Measurement("auto")
fun em(nr: Int) = nr.em val initial = Measurement("initial")
fun em(nr: Double) = nr.em val inherit = Measurement("inherit")
fun prc(nr: Int) = nr.prc val normal = Measurement("normal")
fun prc(nr: Double) = nr.prc
fun pc(nr: Int) = nr.pc fun fromString(value: String): Measurement = when {
fun pc(nr: Double) = nr.pc value == "0" -> Measurement("0", MeasurementUoM.PX)
fun cm(nr: Int) = nr.cm value.endsWith("px") -> Measurement(value.slice(0..(value.length - 2)), MeasurementUoM.PX)
fun cm(nr: Double) = nr.cm value.endsWith("rel") -> Measurement(value.slice(0..(value.length - 3)), MeasurementUoM.REL)
else -> {
TODO("Unable to parse $value")
}
} }
}
} }
val Int.px: Measurement val Int.px: Measurement
get() = Measurement("${this}${if (this == 0) { "" } else { "px"}}") get() = Measurement(
"${this}${
if (this == 0) {
""
} else {
"px"
}
}",
MeasurementUoM.PX
)
val Int.em: Measurement val Int.em: Measurement
get() = Measurement("${this}${if (this == 0) { "" } else { "em"}}") get() = Measurement(
"${this}${
if (this == 0) {
""
} else {
"em"
}
}",
MeasurementUoM.EM
)
val Int.rem: Measurement val Int.rem: Measurement
get() = Measurement("${this}${if (this == 0) { "" } else { "rem"}}") get() = Measurement(
"${this}${
if (this == 0) {
""
} else {
"rem"
}
}",
MeasurementUoM.REM
)
val Int.prc: Measurement val Int.prc: Measurement
get() = Measurement("${this}%") get() = Measurement("${this}%", MeasurementUoM.PRC)
val Int.pc: Measurement val Int.pc: Measurement
get() = Measurement("${this}pc") get() = Measurement("${this}pc", MeasurementUoM.PC)
val Int.cm: Measurement val Int.cm: Measurement
get() = Measurement("${this}cm") get() = Measurement("${this}cm", MeasurementUoM.CM)
fun Int.px(): Measurement = Measurement.px(this) val Int.fr: Measurement
get() = Measurement("${this}fr", MeasurementUoM.FR)
val Int.vw: Measurement
get() = Measurement("${this}vw", MeasurementUoM.VW)
val Int.vh: Measurement
get() = Measurement("${this}vh", MeasurementUoM.VH)
val Double.px: Measurement val Double.px: Measurement
get() = Measurement("${this}px") get() = Measurement("${this}px", MeasurementUoM.PX)
val Double.em: Measurement val Double.em: Measurement
get() = Measurement("${this}em") get() = Measurement("${this}em", MeasurementUoM.EM)
val Double.rem: Measurement val Double.rem: Measurement
get() = Measurement("${this}rem") get() = Measurement("${this}rem", MeasurementUoM.REM)
val Double.prc: Measurement val Double.prc: Measurement
get() = Measurement("${this}%") get() = Measurement("${this}%", MeasurementUoM.PRC)
val Double.pc: Measurement val Double.pc: Measurement
get() = Measurement("${this}pc") get() = Measurement("${this}pc", MeasurementUoM.PC)
val Double.cm: Measurement val Double.cm: Measurement
get() = Measurement("${this}cm") get() = Measurement("${this}cm", MeasurementUoM.CM)
fun Double.px(): Measurement = Measurement.px(this) val Double.fr: Measurement
get() = Measurement("${this}fr", MeasurementUoM.FR)
val Double.vw: Measurement
get() = Measurement("${this}vw", MeasurementUoM.VW)
val Double.vh: Measurement
get() = Measurement("${this}vh", MeasurementUoM.VH)
open class LineHeight(value: String) : CssProperty(value) { open class LineHeight(value: String) : CssProperty(value) {
companion object { companion object {
val normal = LineHeight("normal") val normal = LineHeight("normal")
val initial = LineHeight("initial") val initial = LineHeight("initial")
val inherit = LineHeight("inherit") val inherit = LineHeight("inherit")
} }
} }

View File

@@ -2,24 +2,24 @@ package nl.astraeus.css.properties
class MixBlendMode( class MixBlendMode(
value: String value: String
) : CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val normal = MixBlendMode("normal") val normal = MixBlendMode("normal")
val multiply = MixBlendMode("multiply") val multiply = MixBlendMode("multiply")
val screen = MixBlendMode("screen") val screen = MixBlendMode("screen")
val overlay = MixBlendMode("overlay") val overlay = MixBlendMode("overlay")
val darken = MixBlendMode("darken") val darken = MixBlendMode("darken")
val lighten = MixBlendMode("lighten") val lighten = MixBlendMode("lighten")
val colorDodge = MixBlendMode("color-dodge") val colorDodge = MixBlendMode("color-dodge")
val colorBurn = MixBlendMode("color-burn") val colorBurn = MixBlendMode("color-burn")
val difference = MixBlendMode("difference") val difference = MixBlendMode("difference")
val exclusion = MixBlendMode("exclusion") val exclusion = MixBlendMode("exclusion")
val hue = MixBlendMode("hue") val hue = MixBlendMode("hue")
val saturation = MixBlendMode("saturation") val saturation = MixBlendMode("saturation")
val color = MixBlendMode("color") val color = MixBlendMode("color")
val luminosity = MixBlendMode("luminosity") val luminosity = MixBlendMode("luminosity")
} }
} }

View File

@@ -1,17 +1,17 @@
package nl.astraeus.css.properties package nl.astraeus.css.properties
class ObjectFit( class ObjectFit(
value: String value: String
) : CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val fill = ObjectFit("fill") val fill = ObjectFit("fill")
val contain = ObjectFit("contain") val contain = ObjectFit("contain")
val cover = ObjectFit("cover") val cover = ObjectFit("cover")
val scaleDown = ObjectFit("scale-down") val scaleDown = ObjectFit("scale-down")
val none = ObjectFit("none") val none = ObjectFit("none")
val initial = ObjectFit("initial") val initial = ObjectFit("initial")
val inherit = ObjectFit("inherit") val inherit = ObjectFit("inherit")
} }
} }

View File

@@ -1,14 +1,14 @@
package nl.astraeus.css.properties package nl.astraeus.css.properties
class OutlineWidth( class OutlineWidth(
value: String value: String
) : CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val thin = OutlineWidth("thin") val thin = OutlineWidth("thin")
val medium = OutlineWidth("medium") val medium = OutlineWidth("medium")
val thick = OutlineWidth("thick") val thick = OutlineWidth("thick")
val initial = BorderWidth("initial") val initial = BorderWidth("initial")
val inherit = BorderWidth("inherit") val inherit = BorderWidth("inherit")
} }
} }

View File

@@ -1,15 +1,15 @@
package nl.astraeus.css.properties package nl.astraeus.css.properties
class Overflow( class Overflow(
value: String value: String
) : CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val visible = Overflow("visible") val visible = Overflow("visible")
val hidden = Overflow("hidden") val hidden = Overflow("hidden")
val scroll = Overflow("scroll") val scroll = Overflow("scroll")
val auto = Overflow("auto") val auto = Overflow("auto")
val initial = BorderWidth("initial") val initial = BorderWidth("initial")
val inherit = BorderWidth("inherit") val inherit = BorderWidth("inherit")
} }
} }

View File

@@ -1,17 +1,17 @@
package nl.astraeus.css.properties package nl.astraeus.css.properties
class PageBreak( class PageBreak(
value: String value: String
) : CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val auto = PageBreak("auto") val auto = PageBreak("auto")
val always = PageBreak("always") val always = PageBreak("always")
val avoid = PageBreak("avoid") val avoid = PageBreak("avoid")
val left = PageBreak("left") val left = PageBreak("left")
val right = PageBreak("right") val right = PageBreak("right")
val initial = PageBreak("initial") val initial = PageBreak("initial")
val inherit = PageBreak("inherit") val inherit = PageBreak("inherit")
} }
} }

View File

@@ -1,13 +1,13 @@
package nl.astraeus.css.properties package nl.astraeus.css.properties
class Perspective( class Perspective(
value: String value: String
) : CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val none = Perspective("none") val none = Perspective("none")
val initial = Perspective("initial") val initial = Perspective("initial")
val inherit = Perspective("inherit") val inherit = Perspective("inherit")
} }
} }

View File

@@ -1,14 +1,14 @@
package nl.astraeus.css.properties package nl.astraeus.css.properties
class PointerEvents( class PointerEvents(
value: String value: String
) : CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val auto = PointerEvents("auto") val auto = PointerEvents("auto")
val none = PointerEvents("none") val none = PointerEvents("none")
val initial = PointerEvents("initial") val initial = PointerEvents("initial")
val inherit = PointerEvents("inherit") val inherit = PointerEvents("inherit")
} }
} }

View File

@@ -1,17 +1,17 @@
package nl.astraeus.css.properties package nl.astraeus.css.properties
class Position( class Position(
value: String value: String
) : CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val static = Position("static") val static = Position("static")
val absolute = Position("absolute") val absolute = Position("absolute")
val fixed = Position("fixed") val fixed = Position("fixed")
val relative = Position("relative") val relative = Position("relative")
val sticky = Position("sticky") val sticky = Position("sticky")
val initial = Position("initial") val initial = Position("initial")
val inherit = Position("inherit") val inherit = Position("inherit")
} }
} }

View File

@@ -1,17 +1,17 @@
package nl.astraeus.css.properties package nl.astraeus.css.properties
class HangingPunctuation( class HangingPunctuation(
value: String value: String
) : CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val none = HangingPunctuation("none") val none = HangingPunctuation("none")
val first = HangingPunctuation("first") val first = HangingPunctuation("first")
val last = HangingPunctuation("last") val last = HangingPunctuation("last")
val allowEnd = HangingPunctuation("allow-end") val allowEnd = HangingPunctuation("allow-end")
val forceEnd = HangingPunctuation("force-end") val forceEnd = HangingPunctuation("force-end")
val initial = HangingPunctuation("initial") val initial = HangingPunctuation("initial")
val inherit = HangingPunctuation("inherit") val inherit = HangingPunctuation("inherit")
} }
} }

View File

@@ -1,16 +1,16 @@
package nl.astraeus.css.properties package nl.astraeus.css.properties
class Resize( class Resize(
value: String value: String
) : CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val none = Resize("none") val none = Resize("none")
val both = Resize("both") val both = Resize("both")
val horizontal = Resize("horizontal") val horizontal = Resize("horizontal")
val vertical = Resize("vertical") val vertical = Resize("vertical")
val initial = Resize("initial") val initial = Resize("initial")
val inherit = Resize("inherit") val inherit = Resize("inherit")
} }
} }

View File

@@ -1,14 +1,14 @@
package nl.astraeus.css.properties package nl.astraeus.css.properties
class ScrollBehavior( class ScrollBehavior(
value: String value: String
) : CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val auto = ScrollBehavior("auto") val auto = ScrollBehavior("auto")
val smooth = ScrollBehavior("smooth") val smooth = ScrollBehavior("smooth")
val initial = ScrollBehavior("initial") val initial = ScrollBehavior("initial")
val inherit = ScrollBehavior("inherit") val inherit = ScrollBehavior("inherit")
} }
} }

View File

@@ -1,14 +1,14 @@
package nl.astraeus.css.properties package nl.astraeus.css.properties
class Span( class Span(
value: String value: String
) : CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val none = Clip("none") val none = Clip("none")
val all = Clip("all") val all = Clip("all")
val initial = Clip("initial") val initial = Clip("initial")
val inherit = Clip("inherit") val inherit = Clip("inherit")
} }
} }

View File

@@ -1,14 +1,14 @@
package nl.astraeus.css.properties package nl.astraeus.css.properties
class TableLayout( class TableLayout(
value: String value: String
) : CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val auto = TableLayout("auto") val auto = TableLayout("auto")
val fixed = TableLayout("fixed") val fixed = TableLayout("fixed")
val initial = TableLayout("initial") val initial = TableLayout("initial")
val inherit = TableLayout("auto") val inherit = TableLayout("auto")
} }
} }

View File

@@ -1,16 +1,16 @@
package nl.astraeus.css.properties package nl.astraeus.css.properties
class TextAlign( class TextAlign(
value: String value: String
) : CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val left = TextAlign("left") val left = TextAlign("left")
val right = TextAlign("right") val right = TextAlign("right")
val center = TextAlign("center") val center = TextAlign("center")
val justify = TextAlign("justify") val justify = TextAlign("justify")
val initial = TextAlign("initial") val initial = TextAlign("initial")
val inherit = TextAlign("inherit") val inherit = TextAlign("inherit")
} }
} }

View File

@@ -1,19 +1,19 @@
package nl.astraeus.css.properties package nl.astraeus.css.properties
class TextAlignLast( class TextAlignLast(
value: String value: String
) : CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val auto = TextAlignLast("auto") val auto = TextAlignLast("auto")
val left = TextAlignLast("left") val left = TextAlignLast("left")
val right = TextAlignLast("right") val right = TextAlignLast("right")
val center = TextAlignLast("center") val center = TextAlignLast("center")
val justify = TextAlignLast("justify") val justify = TextAlignLast("justify")
val start = TextAlignLast("start") val start = TextAlignLast("start")
val end = TextAlignLast("end") val end = TextAlignLast("end")
val initial = TextAlignLast("initial") val initial = TextAlignLast("initial")
val inherit = TextAlignLast("inherit") val inherit = TextAlignLast("inherit")
} }
} }

View File

@@ -1,16 +1,16 @@
package nl.astraeus.css.properties package nl.astraeus.css.properties
class TextDecorationLine( class TextDecorationLine(
value: String value: String
) : CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val none = TextDecorationLine("none") val none = TextDecorationLine("none")
val underline = TextDecorationLine("underline") val underline = TextDecorationLine("underline")
val overline = TextDecorationLine("overline") val overline = TextDecorationLine("overline")
val lineThrough = TextDecorationLine("line-through") val lineThrough = TextDecorationLine("line-through")
val initial = TextDecorationLine("initial") val initial = TextDecorationLine("initial")
val inherit = TextDecorationLine("inherit") val inherit = TextDecorationLine("inherit")
} }
} }

View File

@@ -1,17 +1,17 @@
package nl.astraeus.css.properties package nl.astraeus.css.properties
class TextDecorationStyle( class TextDecorationStyle(
value: String value: String
) : CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val solid = TextDecorationStyle("solid") val solid = TextDecorationStyle("solid")
val double = TextDecorationStyle("double") val double = TextDecorationStyle("double")
val dotted = TextDecorationStyle("dotted") val dotted = TextDecorationStyle("dotted")
val dashed = TextDecorationStyle("dashed") val dashed = TextDecorationStyle("dashed")
val wavy = TextDecorationStyle("wavy") val wavy = TextDecorationStyle("wavy")
val initial = TextDecorationStyle("initial") val initial = TextDecorationStyle("initial")
val inherit = TextDecorationStyle("inherit") val inherit = TextDecorationStyle("inherit")
} }
} }

View File

@@ -1,16 +1,16 @@
package nl.astraeus.css.properties package nl.astraeus.css.properties
class TextJustify( class TextJustify(
value: String value: String
) : CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val auto = TextJustify("auto") val auto = TextJustify("auto")
val interWord = TextJustify("inter-word") val interWord = TextJustify("inter-word")
val interCharacter = TextJustify("inter-character") val interCharacter = TextJustify("inter-character")
val none = TextJustify("none") val none = TextJustify("none")
val initial = TextJustify("initial") val initial = TextJustify("initial")
val inherit = TextJustify("inherit") val inherit = TextJustify("inherit")
} }
} }

View File

@@ -1,16 +1,16 @@
package nl.astraeus.css.properties package nl.astraeus.css.properties
class TextTransform( class TextTransform(
value: String value: String
) : CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val none = TextTransform("none") val none = TextTransform("none")
val capitalize = TextTransform("capitalize") val capitalize = TextTransform("capitalize")
val uppercase = TextTransform("uppercase") val uppercase = TextTransform("uppercase")
val lowercase = TextTransform("lowercase") val lowercase = TextTransform("lowercase")
val initial = TextTransform("initial") val initial = TextTransform("initial")
val inherit = TextTransform("inherit") val inherit = TextTransform("inherit")
} }
} }

View File

@@ -1,22 +1,31 @@
package nl.astraeus.css.properties package nl.astraeus.css.properties
class TimingFunction( class TimingFunction(
value: String value: String
) : CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val linear = TimingFunction("linear") val linear = TimingFunction("linear")
val ease = TimingFunction("ease") val ease = TimingFunction("ease")
val easeIn = TimingFunction("ease-in") val easeIn = TimingFunction("ease-in")
val easeOut = TimingFunction("ease-out") val easeOut = TimingFunction("ease-out")
val easeInOut = TimingFunction("ease-in-out") val easeInOut = TimingFunction("ease-in-out")
val stepStart = TimingFunction("step-start") val stepStart = TimingFunction("step-start")
val stepEnd = TimingFunction("step-end") val stepEnd = TimingFunction("step-end")
val initial = TimingFunction("initial") val initial = TimingFunction("initial")
val inherit = TimingFunction("inherit") val inherit = TimingFunction("inherit")
fun steps(steps: Int, start: Boolean) = TimingFunction("steps($steps, ${if (start) { "start" } else { "end" }}") fun steps(steps: Int, start: Boolean) = TimingFunction(
fun cubicBezier(n1: Double, n2: Double, n3: Double, n4: Double) = TimingFunction("cubic-bezier($n1, $n2, $n3, $n4)") "steps($steps, ${
} if (start) {
"start"
} else {
"end"
}
}"
)
fun cubicBezier(n1: Double, n2: Double, n3: Double, n4: Double) = TimingFunction("cubic-bezier($n1, $n2, $n3, $n4)")
}
} }

View File

@@ -1,49 +1,51 @@
package nl.astraeus.css.properties package nl.astraeus.css.properties
class Transform( class Transform(
value: String value: String
) : CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val none = Transform("none") val none = Transform("none")
val initial = Transform("initial") val initial = Transform("initial")
val inherit = Transform("inherit") val inherit = Transform("inherit")
fun matrix( fun matrix(
n1: Double, n1: Double,
n2: Double, n2: Double,
n3: Double, n3: Double,
n4: Double, n4: Double,
n5: Double, n5: Double,
n6: Double n6: Double
) = Transform("matrix($n1, $n2, $n3, $n4, $n5, $n6)") ) = Transform("matrix($n1, $n2, $n3, $n4, $n5, $n6)")
fun matrix3d(
n01: Double, n02: Double, n03: Double, n04: Double, fun matrix3d(
n05: Double, n06: Double, n07: Double, n08: Double, n01: Double, n02: Double, n03: Double, n04: Double,
n09: Double, n10: Double, n11: Double, n12: Double, n05: Double, n06: Double, n07: Double, n08: Double,
n13: Double, n14: Double, n15: Double, n16: Double n09: Double, n10: Double, n11: Double, n12: Double,
) = Transform( n13: Double, n14: Double, n15: Double, n16: Double
"matrix3d($n01, $n02, $n03, $n04, $n05, $n06, $n07, $n08, $n09, $n10, $n11, $n12, $n13, $n14, $n15, $n16)" ) = Transform(
) "matrix3d($n01, $n02, $n03, $n04, $n05, $n06, $n07, $n08, $n09, $n10, $n11, $n12, $n13, $n14, $n15, $n16)"
fun translate(x: Double, y: Double) = Transform("translate($x, $y)") )
fun translate3d(x: Double, y: Double, z: Double) = Transform("translate3d($x, $y, $z)")
fun translateX(x: Double) = Transform("translateX($x)") fun translate(x: Double, y: Double) = Transform("translate($x, $y)")
fun translateY(y: Double) = Transform("translateY($y)") fun translate3d(x: Double, y: Double, z: Double) = Transform("translate3d($x, $y, $z)")
fun translateZ(z: Double) = Transform("translateZ($z)") fun translateX(x: Double) = Transform("translateX($x)")
fun scale(x: Double, y: Double) = Transform("scale($x, $y)") fun translateY(y: Double) = Transform("translateY($y)")
fun scale3d(x: Double, y: Double, z: Double) = Transform("scale3d($x, $y, $z)") fun translateZ(z: Double) = Transform("translateZ($z)")
fun scaleX(x: Double) = Transform("scaleX($x)") fun scale(x: Double, y: Double) = Transform("scale($x, $y)")
fun scaleY(y: Double) = Transform("scaleY($y)") fun scale3d(x: Double, y: Double, z: Double) = Transform("scale3d($x, $y, $z)")
fun scaleZ(z: Double) = Transform("scaleZ($z)") fun scaleX(x: Double) = Transform("scaleX($x)")
fun rotate(angle: Double) = Transform("rotate($angle)") fun scaleY(y: Double) = Transform("scaleY($y)")
fun rotate3d(x: Double, y: Double, z: Double, angle: Double) = Transform("scale3d($x, $y, $z, $angle") fun scaleZ(z: Double) = Transform("scaleZ($z)")
fun rotateX(x: Double) = Transform("rotateX($x)") fun rotate(angle: Double) = Transform("rotate($angle)")
fun rotateY(y: Double) = Transform("rotateY($y)") fun rotate3d(x: Double, y: Double, z: Double, angle: Double) = Transform("scale3d($x, $y, $z, $angle")
fun rotateZ(z: Double) = Transform("rotateZ($z)") fun rotateX(x: Double) = Transform("rotateX($x)")
fun skew(x: Double, y: Double) = Transform("skew($x, $y)") fun rotateY(y: Double) = Transform("rotateY($y)")
fun skewX(x: Double) = Transform("skew($x)") fun rotateZ(z: Double) = Transform("rotateZ($z)")
fun skewY(y: Double) = Transform("skew($y)") fun skew(x: Double, y: Double) = Transform("skew($x, $y)")
fun perspective(length: Measurement) = Transform("perspective(${length.css()})") fun skewX(x: Double) = Transform("skew($x)")
} fun skewY(y: Double) = Transform("skew($y)")
fun perspective(length: Measurement) = Transform("perspective(${length.css()})")
}
} }

View File

@@ -1,14 +1,14 @@
package nl.astraeus.css.properties package nl.astraeus.css.properties
class TransformStyle( class TransformStyle(
value: String value: String
) : CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val flat = TransformStyle("flat") val flat = TransformStyle("flat")
val preserve3d = TransformStyle("preserve-3d") val preserve3d = TransformStyle("preserve-3d")
val initial = TransformStyle("initial") val initial = TransformStyle("initial")
val inherit = TransformStyle("inherit") val inherit = TransformStyle("inherit")
} }
} }

View File

@@ -1,15 +1,15 @@
package nl.astraeus.css.properties package nl.astraeus.css.properties
class UnicodeBidi( class UnicodeBidi(
value: String value: String
) : CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val normal = UnicodeBidi("normal") val normal = UnicodeBidi("normal")
val embed = UnicodeBidi("embed") val embed = UnicodeBidi("embed")
val bidiOverride = UnicodeBidi("bidi-override") val bidiOverride = UnicodeBidi("bidi-override")
val initial = UnicodeBidi("initial") val initial = UnicodeBidi("initial")
val inherit = UnicodeBidi("inherit") val inherit = UnicodeBidi("inherit")
} }
} }

View File

@@ -1,14 +1,14 @@
package nl.astraeus.css.properties package nl.astraeus.css.properties
class UserSelect( class UserSelect(
value: String value: String
) : CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val auto = UserSelect("auto") val auto = UserSelect("auto")
val none = UserSelect("none") val none = UserSelect("none")
val text = UserSelect("text") val text = UserSelect("text")
val all = UserSelect("all") val all = UserSelect("all")
} }
} }

View File

@@ -1,20 +1,20 @@
package nl.astraeus.css.properties package nl.astraeus.css.properties
class VerticalAlign( class VerticalAlign(
value: String value: String
) : CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val baseline = VerticalAlign("baseline") val baseline = VerticalAlign("baseline")
val sub = VerticalAlign("sub") val sub = VerticalAlign("sub")
val _super = VerticalAlign("super") val _super = VerticalAlign("super")
val top = VerticalAlign("top") val top = VerticalAlign("top")
val textTop = VerticalAlign("text-top") val textTop = VerticalAlign("text-top")
val middle = VerticalAlign("middle") val middle = VerticalAlign("middle")
val bottom = VerticalAlign("bottom") val bottom = VerticalAlign("bottom")
val textBottom = VerticalAlign("text-bottom") val textBottom = VerticalAlign("text-bottom")
val initial = VerticalAlign("initial") val initial = VerticalAlign("initial")
val inherit = VerticalAlign("inherit") val inherit = VerticalAlign("inherit")
} }
} }

View File

@@ -1,15 +1,15 @@
package nl.astraeus.css.properties package nl.astraeus.css.properties
class Visibility( class Visibility(
value: String value: String
) : CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val visible = Visibility("visible") val visible = Visibility("visible")
val hidden = Visibility("hidden") val hidden = Visibility("hidden")
val collapse = Visibility("collapse") val collapse = Visibility("collapse")
val initial = Visibility("initial") val initial = Visibility("initial")
val inherit = Visibility("inherit") val inherit = Visibility("inherit")
} }
} }

View File

@@ -1,17 +1,17 @@
package nl.astraeus.css.properties package nl.astraeus.css.properties
class WhiteSpace( class WhiteSpace(
value: String value: String
) : CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val normal = WhiteSpace("normal") val normal = WhiteSpace("normal")
val nowrap = WhiteSpace("nowrap") val nowrap = WhiteSpace("nowrap")
val pre = WhiteSpace("pre") val pre = WhiteSpace("pre")
val preLine = WhiteSpace("pre-line") val preLine = WhiteSpace("pre-line")
val preWrap = WhiteSpace("pre-wrap") val preWrap = WhiteSpace("pre-wrap")
val initial = WhiteSpace("initial") val initial = WhiteSpace("initial")
val inherit = WhiteSpace("inherit") val inherit = WhiteSpace("inherit")
} }
} }

View File

@@ -1,16 +1,16 @@
package nl.astraeus.css.properties package nl.astraeus.css.properties
class WordBreak( class WordBreak(
value: String value: String
) : CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val normal = WordBreak("normal") val normal = WordBreak("normal")
val breakAll = WordBreak("break-all") val breakAll = WordBreak("break-all")
val keepAll = WordBreak("keep-all") val keepAll = WordBreak("keep-all")
val breakWord = WordBreak("break-word") val breakWord = WordBreak("break-word")
val initial = WordBreak("initial") val initial = WordBreak("initial")
val inherit = WordBreak("inherit") val inherit = WordBreak("inherit")
} }
} }

View File

@@ -1,13 +1,13 @@
package nl.astraeus.css.properties package nl.astraeus.css.properties
class WordSpacing( class WordSpacing(
value: String value: String
) : CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val normal = WordSpacing("normal") val normal = WordSpacing("normal")
val initial = WordSpacing("initial") val initial = WordSpacing("initial")
val inherit = WordSpacing("inherit") val inherit = WordSpacing("inherit")
} }
} }

View File

@@ -1,14 +1,14 @@
package nl.astraeus.css.properties package nl.astraeus.css.properties
class WordWrap( class WordWrap(
value: String value: String
) : CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val normal = WordWrap("normal") val normal = WordWrap("normal")
val breakWord = WordWrap("break-word") val breakWord = WordWrap("break-word")
val initial = WordWrap("initial") val initial = WordWrap("initial")
val inherit = WordWrap("inherit") val inherit = WordWrap("inherit")
} }
} }

View File

@@ -1,13 +1,13 @@
package nl.astraeus.css.properties package nl.astraeus.css.properties
class WritingMode( class WritingMode(
value: String value: String
) : CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val horizontalTb = WritingMode("horizontal-tb") val horizontalTb = WritingMode("horizontal-tb")
val verticalRl = WritingMode("vertical-rl") val verticalRl = WritingMode("vertical-rl")
val verticalLr = WritingMode("vertical-lr") val verticalLr = WritingMode("vertical-lr")
} }
} }

View File

@@ -1,13 +1,13 @@
package nl.astraeus.css.properties package nl.astraeus.css.properties
class ZIndex( class ZIndex(
value: String value: String
) : CssProperty(value) { ) : CssProperty(value) {
companion object { companion object {
val auto = ZIndex("auto") val auto = ZIndex("auto")
val initial = ZIndex("initial") val initial = ZIndex("initial")
val inherit = ZIndex("inherit") val inherit = ZIndex("inherit")
} }
} }

View File

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

View File

@@ -1,11 +0,0 @@
package nl.astraeus.css.style
import nl.astraeus.css.properties.Color
object CssFunctions {
fun darken(color: Color, percentage: Int): Color {
return color
}
}

View File

@@ -1,38 +1,42 @@
package nl.astraeus.css.style package nl.astraeus.css.style
import nl.astraeus.css.properties.* import nl.astraeus.css.properties.CssProperty
import nl.astraeus.css.properties.FontSize
import nl.astraeus.css.properties.FontStretch
import nl.astraeus.css.properties.FontStyle
import nl.astraeus.css.properties.FontWeight
@CssTagMarker @CssTagMarker
open class FontFace : CssGenerator() { open class FontFace : CssGenerator() {
override fun getValidator(name: String) = null override fun getValidator(name: String) = null
fun fontFamily(font: String) { fun fontFamily(font: String) {
props["font-family"] = listOf(CssProperty(font)) props["font-family"] = listOf(CssProperty(font))
} }
fun fontSize(size: FontSize) { fun fontSize(size: FontSize) {
props["font-size"] = listOf(size) props["font-size"] = listOf(size)
} }
fun src(src: String) { fun src(src: String) {
props["src"] = listOf(CssProperty(src)) props["src"] = listOf(CssProperty(src))
} }
fun fontStretch(stretch: FontStretch) { fun fontStretch(stretch: FontStretch) {
props["font-stretch"] = listOf(stretch) props["font-stretch"] = listOf(stretch)
} }
fun fontStyle(style: FontStyle) { fun fontStyle(style: FontStyle) {
props["font-style"] = listOf(style) props["font-style"] = listOf(style)
} }
fun fontWeight(weight: FontWeight) { fun fontWeight(weight: FontWeight) {
props["font-weight"] = listOf(weight) props["font-weight"] = listOf(weight)
} }
fun unicodeRange(unicodeRange: String) { fun unicodeRange(unicodeRange: String) {
props["unicode-range"] = listOf(CssProperty(unicodeRange)) props["unicode-range"] = listOf(CssProperty(unicodeRange))
} }
} }

View File

@@ -2,15 +2,15 @@ package nl.astraeus.css.style
@CssTagMarker @CssTagMarker
open class KeyFrames : CssGenerator() { open class KeyFrames : CssGenerator() {
val frames: MutableMap<Int, Css> = mutableMapOf() val frames: MutableMap<Int, Css> = mutableMapOf()
override fun getValidator(name: String): List<Validator>? = listOf() override fun getValidator(name: String): List<Validator>? = listOf()
fun percentage(percentage: Int, style: Css) { fun percentage(percentage: Int, style: Css) {
val css = Style() val css = Style()
style(css) style(css)
frames[percentage] = style frames[percentage] = style
} }
} }

File diff suppressed because it is too large Load Diff

View File

@@ -4,34 +4,34 @@ import nl.astraeus.css.properties.CssProperty
abstract class Validator { abstract class Validator {
open fun validate(properties: List<CssProperty>): Boolean = true open fun validate(properties: List<CssProperty>): Boolean = true
open fun getMessage(name: String): String = "'$name' validation message not defined for $this" open fun getMessage(name: String): String = "'$name' validation message not defined for $this"
} }
class MaxCountValidator( class MaxCountValidator(
val number: Int val number: Int
): Validator() { ) : Validator() {
override fun validate(property: List<CssProperty>): Boolean = property.size <= number override fun validate(property: List<CssProperty>): Boolean = property.size <= number
override fun getMessage(name: String): String = "'$name' should not have more than 4 entries" override fun getMessage(name: String): String = "'$name' should not have more than 4 entries"
} }
class InitialInheritSingleValue: Validator() { class InitialInheritSingleValue : Validator() {
override fun validate(properties: List<CssProperty>): Boolean { override fun validate(properties: List<CssProperty>): Boolean {
for (prop in properties) { for (prop in properties) {
if (prop.css() == "initial" || prop.css() == "inherit") { if (prop.css() == "initial" || prop.css() == "inherit") {
return properties.size == 1 return properties.size == 1
} }
}
return true
} }
override fun getMessage(name: String): String = "'$name' can only have single value when 'initial' or 'inherit'" return true
}
override fun getMessage(name: String): String = "'$name' can only have single value when 'initial' or 'inherit'"
} }

View File

@@ -0,0 +1,20 @@
package nl.astraeus.css
import nl.astraeus.css.properties.oklch
import kotlin.test.Test
class ColorTest {
@Test
fun testColor() {
val css = style {
select("body") {
color(oklch(100, 0.5, 0.5))
backgroundColor(oklch(100, 0.5, 0.5, 0.25))
}
}
println(css.generateCss())
}
}

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,157 @@
package nl.astraeus.css
import nl.astraeus.css.properties.BorderStyle
import nl.astraeus.css.properties.Color
import nl.astraeus.css.properties.FontStyle
import nl.astraeus.css.properties.FontWeight
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(minified = true))
}
@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 testMeasurements() {
val css = style {
select("body") {
fontSize(1.2.em)
borderWidth(3.px)
width(75.prc)
}
}
println(css.generateCss())
}
@Test
fun testGeneration() {
val color = hsla(0, 50, 50, 1.0)
val backgroundColor = Color.white
val css = style {
select(cls("button")) {
padding(5.px)
select("a", "span") {
color(color)
backgroundColor(backgroundColor)
hover {
color(color.lighten(10))
backgroundColor(backgroundColor.darken(10))
}
}
}
}
println(css.generateCss(
minified = false,
sortProperties = true,
combineEqualBlocks = false
))
}
@Test
fun testMediaQueries() {
val css = style {
media("screen and (min-width: 30em)") {
select("html", "body") {
backgroundColor(Color.purple)
color(Color.blue)
}
}
media("print") {
select("html", "body") {
backgroundColor(Color.white)
color(Color.darkGrey)
}
}
}
println(css.generateCss(
minified = false,
sortProperties = true,
combineEqualBlocks = true
))
}
@Test
fun testFontFace() {
val css = style {
select("*") {
fontFace {
fontFamily("UbuntuCondensed")
fontStyle(FontStyle.normal)
fontWeight(FontWeight.normal)
//fontDisplay("auto")
src("fonts/ubuntu.condensed.ttf")
}
}
}
val cssTxt = css.generateCss(
minified = false,
sortProperties = true,
combineEqualBlocks = true
)
println(cssTxt)
}
}

View File

@@ -0,0 +1,18 @@
package nl.astraeus.css
import nl.astraeus.css.properties.calc
import nl.astraeus.css.properties.em
import nl.astraeus.css.properties.minus
import nl.astraeus.css.properties.plus
import nl.astraeus.css.properties.px
import kotlin.test.Test
class TestCalcExpression {
@Test
fun testCalcExpression() {
val a = calc(10.px + 20.px - 5.em)
println(a)
}
}

View File

@@ -1,11 +1,23 @@
package nl.astraeus.css package nl.astraeus.css
import nl.astraeus.css.properties.* import nl.astraeus.css.properties.BoxSizing
import nl.astraeus.css.properties.Color
import nl.astraeus.css.properties.Count
import nl.astraeus.css.properties.Display
import nl.astraeus.css.properties.em
import nl.astraeus.css.properties.hsl
import nl.astraeus.css.properties.hsla
import nl.astraeus.css.properties.px
import nl.astraeus.css.properties.rgb
import nl.astraeus.css.properties.rgba
import nl.astraeus.css.style.attr import nl.astraeus.css.style.attr
import nl.astraeus.css.style.attrEquals import nl.astraeus.css.style.attrEquals
import nl.astraeus.css.style.cls import nl.astraeus.css.style.cls
import nl.astraeus.css.style.id import nl.astraeus.css.style.id
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertFalse
import kotlin.test.assertTrue
class TestCssBuilder { class TestCssBuilder {
@@ -13,6 +25,32 @@ class TestCssBuilder {
fun testBuilder() { fun testBuilder() {
val css = style { val css = style {
select("*", "*::before", "*::after") {
boxSizing(BoxSizing.borderBox)
}
select("html") {
transition("background-color 1s ease")
margin(0.px)
padding(0.px)
focus {
backgroundColor(Color.blue)
}
}
select("body") {
margin(0.px)
padding(0.px)
focus {
backgroundColor(Color.blue)
}
transition("background-color 1s ease")
}
select(".test") { select(".test") {
top(10.px) top(10.px)
left(4.em) left(4.em)
@@ -66,7 +104,7 @@ class TestCssBuilder {
} }
} }
println(css.generateCss()) println(css.generateCss(combineEqualBlocks = true, sortProperties = true))
} }
@Test @Test
@@ -148,4 +186,82 @@ class TestCssBuilder {
println(css2.generateCss()) println(css2.generateCss())
} }
@Test
fun testOr() {
val css = style {
select("h1") {
color(Color.blue)
select("table") {
color(Color.red)
select("th", "td") {
color(Color.green)
}
}
}
}
println(css.generateCss())
}
@Test
fun testOrWithComma() {
var excepted = false
try {
val css = style {
select("h1") {
color(Color.blue)
select("table") {
color(Color.red)
select("th, td") {
color(Color.green)
}
}
}
}
println(css.generateCss())
} catch (e: Exception) {
excepted = true
assertTrue {
e is IllegalStateException
}
assertTrue {
e.message?.contains("Comma is not allowed in selector") ?: false
}
}
assertTrue {
excepted
}
}
@Test
fun testAlphaFunctions() {
val hsl = hsl(1, 50, 50)
val hsla = hsla(1, 50, 50, 0.5)
val rgb = rgb(101, 111, 121)
val rgba = rgba(100, 110, 120, 0.4)
val hex = Color("#88ff44")
val hexa = Color("#88ff4466")
assertFalse { hsl.hasAlpha() }
assertFalse { rgb.hasAlpha() }
assertFalse { hex.hasAlpha() }
assertTrue { hsla.hasAlpha() }
assertTrue { rgba.hasAlpha() }
assertTrue { hexa.hasAlpha() }
assertEquals(0.5, hsla.getAlpha())
assertEquals(0.4, rgba.getAlpha())
assertEquals(0.5, hsla.getAlpha())
assertEquals(0.4, hexa.getAlpha())
assertEquals("646e78", rgba.toHex())
assertEquals("bf4240", hsla.toHex())
}
} }