Add option to overwrite and redeclaration warning option

This commit is contained in:
2020-09-08 09:39:15 +02:00
parent f23d54d8c8
commit dedbce0fa0
12 changed files with 259 additions and 482 deletions

1
.gitignore vendored
View File

@@ -1,3 +1,4 @@
.gradle
build
.idea
local.properties

View File

@@ -1,66 +1,70 @@
import org.jetbrains.kotlin.fir.declarations.builder.buildResolvedImport
plugins {
kotlin("multiplatform") version "1.4-M1"
kotlin("multiplatform") version "1.4.0-rc"
`maven-publish`
}
group = "nl.astraeus"
version = "0.1.0-SNAPSHOT"
version = "0.3.6-SNAPSHOT"
repositories {
maven { setUrl("https://dl.bintray.com/kotlin/kotlin-eap") }
mavenLocal()
mavenCentral()
}
//apply(plugin = "kotlin-dce-js")
kotlin {
/* Targets configuration omitted.
* To find out how to configure the targets, please follow the link:
* https://kotlinlang.org/docs/reference/building-mpp-with-gradle.html#setting-up-targets */
jvm()
js {
produceExecutable()
browser {
distribution {
directory = File("$projectDir/web/")
}
}
js(BOTH) {
browser()
//produceKotlinLibrary()
}
val hostOs = System.getProperty("os.name")
val isMingwX64 = hostOs.startsWith("Windows")
val nativeTarget = when {
hostOs == "Mac OS X" -> macosX64("native")
hostOs == "Linux" -> linuxX64("native")
isMingwX64 -> mingwX64("native")
else -> throw GradleException("Host OS is not supported in Kotlin/Native.")
}
sourceSets {
val commonMain by getting {
dependencies {
implementation(kotlin("stdlib-common"))
val commonMain by getting {}
}
}
implementation("io.github.microutils:kotlin-logging-common:1.7.8")
}
}
val commonTest by getting {
dependencies {
implementation(kotlin("test-common"))
//implementation(kotlin("test-annotations-common"))
}
}
val jsMain by getting {
dependencies {
implementation(kotlin("stdlib-js"))
publishing {
repositories {
maven {
name = "releases"
// change to point to your repo, e.g. http://my.org/repo
url = uri("http://nexus.astraeus.nl/nexus/content/repositories/releases")
credentials {
val nexusUsername: String by project
val nexusPassword: String by project
implementation("io.github.microutils:kotlin-logging-js:1.7.8")
username = nexusUsername
password = nexusPassword
}
}
val jsTest by getting {
dependencies {
implementation(kotlin("test-js"))
//implementation(kotlin("test-annotations-js"))
}
}
val jvmMain by getting {
dependencies {
implementation(kotlin("stdlib-jdk8"))
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
implementation("org.slf4j:slf4j-api:1.7.29")
implementation("org.slf4j:slf4j-simple:1.7.29")
implementation("io.github.microutils:kotlin-logging:1.7.8")
username = nexusUsername
password = nexusPassword
}
}
}
publications {
val kotlinMultiplatform by getting {
//artifactId = "kotlin-css-generator"
}
}
}

6
gradle.properties Normal file
View File

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

View File

@@ -7,4 +7,7 @@ pluginManagement {
maven { setUrl("https://plugins.gradle.org/m2/") }
}
}
rootProject.name = "kotlin-css-generator"
enableFeaturePreview("GRADLE_METADATA")

View File

@@ -1,8 +1,45 @@
package nl.astraeus.css.properties
class Color(
value: String
value: String,
val readOnly: Boolean = true
) : CssProperty(value) {
/* val hue: Int? = null
val saturation: Int? = null
val lightness: Int? = null
val alpha: Double? = null
init {
}
override fun css(): String {
return super.css()
}
fun adjust(
red: Int? = null,
green: Int? = null,
blue: Int? = null,
hue: Int? = null,
saturation: Int? = null,
lightness: Int? = null,
alpha: Double? = null
): Color {
return this
}
fun darken(): Color {
if (readOnly) {
return this
} else {
return this
}
}
fun lighten(): Color {
return this
}*/
companion object {
val auto = Color("auto")
@@ -25,12 +62,21 @@ class Color(
hue: Int,
saturation: Int,
lightness: Int
) = Color("hsl($hue, $saturation, $lightness)")
) = Color("hsl($hue, $saturation%, $lightness%)")
fun hsla(
hue: Int,
saturation: Int,
lightness: Int,
alpha: Double
) = Color("hsla($hue, $saturation, $lightness, $alpha)")
) = Color("hsla($hue, $saturation%, $lightness%, $alpha)")
private fun fromHex(
red: Int,
green: Int,
blue: Int
) {
}
}
}

View File

@@ -0,0 +1,11 @@
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,7 +1,6 @@
package nl.astraeus.css.style
import nl.astraeus.css.properties.*
import nl.astraeus.logging.log
typealias Css = Style.() -> Unit
@@ -31,53 +30,53 @@ private fun prp(vararg css: String): List<CssProperty> {
}
abstract class CssGenerator {
val definitions: MutableMap<String, Css> = mutableMapOf()
val definitions: MutableMap<String, MutableList<Css>> = mutableMapOf()
val props: MutableMap<String, List<CssProperty>> = mutableMapOf()
abstract fun getValidator(name: String): List<Validator>?
private fun propertyCss(indent: String, name: String, props: List<CssProperty>, minified: Boolean): String {
private fun propertyCss(indent: String, name: String, props: List<CssProperty>): String {
val builder = StringBuilder()
getValidator(name)?.forEach {
if (!it.validate(props)) {
log.warn { "Validate error '$name' - ${it.getMessage(name)}" }
println( "Validate error '$name' - ${it.getMessage(name)}")
}
}
for (prop in props) {
if (builder.isNotEmpty()) {
builder.append(",")
indent(minified, builder, " ")
builder.append(" ")
}
builder.append(prop.css())
}
return if (!minified) {
val paddedName = StringBuilder()
paddedName.append(indent)
paddedName.append(name)
paddedName.append(":")
while (paddedName.length < 32) {
paddedName.append(' ')
}
"$paddedName$builder;\n"
} else {
"$name:$builder;"
val paddedName = StringBuilder()
paddedName.append(indent)
paddedName.append(name)
paddedName.append(":")
while (paddedName.length < 32) {
paddedName.append(' ')
}
return "$paddedName$builder;\n"
}
fun generatePropertyCss(indent: String, minified: Boolean): String {
fun generatePropertyCss(indent: String): String {
val builder = StringBuilder()
for ((name, prop) in props) {
builder.append(propertyCss(indent, name, prop, minified))
builder.append(propertyCss(indent, name, prop))
}
return builder.toString()
}
open fun generateCss(namespace: String = "", indent: String = "", minified: Boolean = false): String {
open fun generateCss(
namespace: String = "",
indent: String = "",
minified: Boolean = false,
warnOnRedeclaration: Boolean = true
): String {
val builder = StringBuilder()
if (this is ConditionalStyle) {
@@ -85,22 +84,20 @@ abstract class CssGenerator {
mq.keys.sorted().forEach { mediaName ->
val css = mq[mediaName]
indent(minified, builder, indent)
builder.append(indent)
builder.append("@media ")
builder.append(mediaName)
builder.append(" {")
indent(minified, builder, "\n")
builder.append(" {\n")
css?.let { css ->
val mediaStyle = ConditionalStyle()
css(mediaStyle)
builder.append(mediaStyle.generateCss("", " $indent", minified))
builder.append(mediaStyle.generateCss("", " $indent"))
}
indent(minified, builder, indent)
builder.append("}")
indent(minified, builder, "\n")
builder.append(indent)
builder.append("}\n")
}
}
@@ -108,102 +105,107 @@ abstract class CssGenerator {
mq.keys.sorted().forEach { mediaName ->
val css = mq[mediaName]
indent(minified, builder, indent)
builder.append(indent)
builder.append("@supports ")
builder.append(mediaName)
builder.append(" {")
indent(minified, builder, "\n")
builder.append(" {\n")
css?.let { css ->
val mediaStyle = ConditionalStyle()
css(mediaStyle)
builder.append(mediaStyle.generateCss(""," $indent", minified))
builder.append(mediaStyle.generateCss(""," $indent"))
}
indent(minified, builder, indent)
builder.append("}")
indent(minified, builder, "\n")
builder.append(indent)
builder.append("}\n")
}
}
}
for ((name, prop) in definitions) {
for (name in definitions.keys.sorted()) {
val props = definitions[name]!!
val css = StringBuilder()
if (warnOnRedeclaration && props.size > 1) {
css.append("/* style '$name' is defined ${props.size} times! */\n")
}
val finalStyle = Style()
prop(finalStyle)
for (prop in props) {
prop(finalStyle)
}
css.append(finalStyle.generatePropertyCss(" $indent", minified))
css.append(finalStyle.generatePropertyCss(" $indent"))
if (css.isNotBlank()) {
builder.append("\n$namespace $name".trim())
indent(minified, builder, " $indent")
builder.append("{")
indent(minified, builder, "\n")
if (name.startsWith(":")) {
builder.append("\n$namespace$name".trim())
} else {
builder.append("\n$namespace $name".trim())
}
builder.append(" $indent")
builder.append("{\n")
finalStyle.fontFace?.let { ff ->
indent(minified, builder, " $indent")
builder.append("@font-face {")
indent(minified, builder, "\n")
builder.append(ff.generatePropertyCss( " $indent", minified))
builder.append(" $indent")
builder.append("}")
indent(minified, builder, "\n")
builder.append("@font-face {\n")
builder.append(ff.generatePropertyCss( " $indent"))
builder.append(" $indent")
builder.append("}\n")
}
finalStyle.keyFrames.let { kf ->
kf.keys.sorted().forEach { frameName ->
val css = kf[frameName]
indent(minified, builder, " $indent")
builder.append(" $indent")
builder.append("@keyframes ")
builder.append(frameName)
builder.append(" {")
indent(minified, builder, "\n")
builder.append(" {\n")
css?.let { css ->
for ((nr, style) in css.frames) {
indent(minified, builder, " $indent")
builder.append(" $indent")
builder.append("${nr}% ")
indent(minified, builder, " $indent")
builder.append("{")
indent(minified, builder, "\n")
builder.append(" $indent")
builder.append("{\n")
val finalStyle = Style()
style(finalStyle)
builder.append(finalStyle.generatePropertyCss(" $indent", minified))
builder.append(finalStyle.generatePropertyCss(" $indent"))
indent(minified, builder, " $indent")
builder.append("}")
indent(minified, builder, "\n")
builder.append(" $indent")
builder.append("}\n")
}
indent(minified, builder, " $indent")
builder.append("}")
indent(minified, builder, "\n")
builder.append(" $indent")
builder.append("}\n")
}
}
}
builder.append(css)
builder.append("}")
indent(minified, builder, "\n\n")
builder.append("}\n\n")
}
builder.append(finalStyle.generateCss( "$namespace $name".trim(), indent, minified))
builder.append(finalStyle.generateCss("$namespace $name".trim(), indent))
}
return builder.toString()
}
private fun indent(minified: Boolean, builder: StringBuilder, indent: String) {
if (!minified) {
builder.append(indent)
return if (minified) {
val stripped = StringBuilder()
val skip = arrayOf(' ', '\t', '\n', '\r')
for (char in builder) {
if (!skip.contains(char)) {
stripped.append(char)
}
}
stripped.toString();
} else {
builder.toString()
}
}
}
@@ -220,6 +222,8 @@ open class Style : CssGenerator() {
MaxCountValidator(4),
InitialInheritSingleValue()
),
"animation-iteration-mode" to listOf(MaxCountValidator(4)),
"animation-timing-function" to listOf(MaxCountValidator(4)),
"border-image-repeat" to listOf(MaxCountValidator(2)),
"border-image-slice" to listOf(MaxCountValidator(4)),
@@ -229,8 +233,49 @@ open class Style : CssGenerator() {
override fun getValidator(name: String) = validators[name]
private fun addStyle(selector: String, style: Css) {
definitions[selector] = definitions[selector] ?: mutableListOf()
definitions[selector]?.add(style)
}
fun select(selector: String, style: Css) {
definitions[selector] = style
addStyle(selector, style)
}
fun descendant(descName: String, style: Css) {
addStyle(descName, style)
}
fun cls(className: String, style: Css) {
addStyle(".$className", style)
}
fun child(childName: String, style: Css) {
addStyle("> $childName", style)
}
fun active(style: Css) {
addStyle(":active", style)
}
fun focus(style: Css) {
addStyle(":focus", style)
}
fun focusWithin(style: Css) {
addStyle(":focus-within", style)
}
fun hover(style: Css) {
addStyle(":hover", style)
}
fun visited(style: Css) {
addStyle(":visited", style)
}
fun plain(name: String, value: String) {
props[name] = prp(value)
}
fun alignContent(value: AlignContent) { props["align-content"] = prp(value) }
@@ -390,7 +435,7 @@ open class Style : CssGenerator() {
fun gridAutoFlow(flow: GridFlow) { props["grid-auto-flow"] = prp(flow) }
fun gridAutoRows(autoRows: GridAuto) { props["grid-auto-rows"] = prp(autoRows) }
fun gridAutoRows(size: Measurement) { props["grid-auto-rows"] = prp(size) }
fun gridColumn(start: GridRowColumn, end: GridRowColumn) { props["grid-column"] = prp(start, end) }
fun gridColumn(start: GridRowColumn, end: GridRowColumn) { props["grid-column"] = prp(CssProperty("${start.css()}/${end.css()}")) }
fun gridColumnEnd(end: GridRowColumn) { props["grid-column-end"] = prp(end) }
fun gridColumnGap(gap: GridRowColumn) { props["grid-column-gap"] = prp(gap) }
fun gridColumnStart(start: GridRowColumn) { props["grid-column-start"] = prp(start) }
@@ -398,13 +443,18 @@ open class Style : CssGenerator() {
rowGap: Measurement = Measurement.px(0),
columnGap: Measurement = Measurement.px(0)
) { props["grid-gap"] = prp(rowGap, columnGap) }
fun gridRow(start: GridRowColumn, end: GridRowColumn) { props["grid-row"] = prp(start, end) }
fun gridRow(start: GridRowColumn, end: GridRowColumn) { props["grid-row"] = prp(CssProperty("${start.css()}/${end.css()}")) }
fun gridRowEnd(end: GridRowColumn) { props["grid-row-end"] = prp(end) }
fun gridRowGap(gap: GridRowColumn) { props["grid-row-end"] = prp(gap) }
fun gridRowStart(start: GridRowColumn) { props["grid-row-start"] = prp(start) }
fun gridTemplate(template: String) { props["grid-template"] = prp(template) }
fun gridTemplateAreas(template: String) { props["grid-template-areas"] = prp(template) }
@Deprecated(
"Fixed type, use gridTemplateColumns instead",
ReplaceWith("gridTemplateColumns(columns)")
)
fun gridTemplateColumn(vararg columns: TemplateRowColumn) { props["grid-template-columns"] = prp(*columns) }
fun gridTemplateColumns(vararg columns: TemplateRowColumn) { props["grid-template-columns"] = prp(*columns) }
fun gridTemplateRows(vararg rows: TemplateRowColumn) { props["grid-template-rows"] = prp(*rows) }
fun hangingPunctuation(punctuation: Isolation) { props["hanging-punctuation"] = prp(punctuation) }
fun height(height: Measurement) { props["height"] = prp(height) }
@@ -462,6 +512,12 @@ open class Style : CssGenerator() {
fun overflowX(overflow: Overflow) { props["overflow-x"] = prp(overflow) }
fun overflowY(overflow: Overflow) { props["overflow-y"] = prp(overflow) }
fun padding(padding: Measurement) { props["padding"] = prp(padding) }
fun padding(topLeft: Measurement, bottomRight: Measurement) {
props["padding"] = prp(topLeft, bottomRight)
}
fun padding(top: Measurement, right: Measurement, bottom: Measurement, left: Measurement) {
props["padding"] = prp(top, right, bottom, left)
}
fun padding(padding: InitialInherit) { props["padding"] = prp(padding) }
fun paddingBottom(padding: Measurement) { props["padding-bottom"] = prp(padding) }
fun paddingBottom(padding: InitialInherit) { props["padding-bottom"] = prp(padding) }

View File

@@ -1,5 +0,0 @@
package nl.astraeus.logging
import mu.KotlinLogging
val log = KotlinLogging.logger {}

View File

@@ -1,17 +1,8 @@
package nl.astraeus.css
import nl.astraeus.css.properties.Color.Companion.hsl
import nl.astraeus.css.properties.Color.Companion.rgba
import nl.astraeus.css.properties.Measurement.Companion.em
import nl.astraeus.css.properties.Measurement.Companion.px
import nl.astraeus.css.properties.em
import nl.astraeus.css.properties.px
//import kotlin.test.Test
object TestCssBuilder {
//@Test
/*
@Test
fun testBuilder() {
val css = CssBuilder()
@@ -21,14 +12,22 @@ object TestCssBuilder {
top(10.px())
left(4.em())
backgroundColor(rgba(255, 255, 255, 0.75))
animationIterationMode(
Count.auto,
Count.auto,
Count.auto,
Count.auto,
Count.auto
)
select("> a") {
//color = hsl(200, 50, 50)
color(hsl(200, 50, 50))
}
}
}
println(css)
}
}*/
}

View File

@@ -1,105 +0,0 @@
package nl.astraeus.css
import nl.astraeus.css.properties.*
import nl.astraeus.css.properties.Color.Companion.hex
import nl.astraeus.css.style.Style
class StyleBase(
val mainColor: Color = Color.hsl(128, 50, 50),
val mainBackgroundColor: Color = Color.hsl(64, 50, 50),
val mainFont: TextProperty = text("Arial")
)
private fun Style.sizePX(
left: Int,
top: Int,
width: Int,
height: Int
) {
this@sizePX.top(top.px())
this@sizePX.left(left.px())
this@sizePX.width(width.px())
this@sizePX.height(height.px())
}
private fun generateCss(
base: StyleBase
): String {
val css = CssBuilder()
css.style {
select("body") {
// fontFamily = base.mainFont
// color = base.mainColor
backgroundColor(base.mainBackgroundColor)
// alignContent = AlignContent.initial()
}
select(".test") {
// top = px(10)
// left = em(5)
backgroundColor(Color.rgba(255, 255, 255, 0.75))
//
// select("> a") {
// color = Color.hsl(200, 50, 50)
// }
}
select("nav") {
select("ul") {
color(Color.hsl(0, 100, 25))
backgroundColor(base.mainBackgroundColor)
}
select("li") {
sizePX(25, 25, 200, 200)
animationPlayState(AnimationPlayState.paused, AnimationPlayState.running)
select("a") {
// width = px(725)
// background = text("")
// backgroundColor = base.mainBackgroundColor
}
}
}
}
return css.getCss()
}
fun main() {
val css1 = generateCss(StyleBase())
val css2 = generateCss(StyleBase(
Color.hsl(32, 40, 50),
Color.hsl(64, 60, 35),
text("Courier")
))
println(css1)
println(css2)
val sd = style {
select("#pipo") {
backgroundColor(hex("ffeedd"))
fontFamily("Arial, Courier")
// backgroundColor = Color.hex("eeeeee")
// fontFamily = text("Arial, Courier")
// animationDelay = listOf(DelayDuration.initial())
select("div") {
tableLayout(TableLayout.auto)
tabSize(14.px())
// color = Color.hex("1b1b1b1")
// alignContent = AlignContent.flexStart()
// animationName = listOf(text("foo"), text("bar"))
// animationIterationCount = listOf(
// Count.count(3), Count.infinite())
// animationTimingFunction = listOf(AnimationTimingFunction.cubicBezier(0.1, 0.2, 0.3, 0.4), AnimationTimingFunction.easeInOut())
}
}
}
println("======")
println(sd.generateCss())
}

View File

@@ -1,10 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>kotlin-css-generator</title>
</head>
<body>
<script type="text/javascript" src="kotlin-css-generator.js"></script>
</body>
</html>

View File

@@ -1,229 +0,0 @@
package nl.astraeus.css
import nl.astraeus.css.properties.*
import nl.astraeus.css.properties.Color.Companion.hex
import nl.astraeus.css.style.Css
import nl.astraeus.css.style.Style
class StyleBase(
val mainColor: Color = Color.hsl(128, 50, 50),
val mainBackgroundColor: Color = Color.hsl(64, 50, 50),
val mainFont: TextProperty = text("Arial")
)
private fun Style.sizePX(
left: Int,
top: Int,
width: Int,
height: Int
) {
// this@sizePX.top = Measurement.px(top)
// this@sizePX.left = Measurement.px(left)
// this@sizePX.width = Measurement.px(width)
// this@sizePX.height = Measurement.px(height)
}
private fun generateCss(
base: StyleBase
): String {
val css = CssBuilder()
css.style {
select("body") {
// fontFamily = base.mainFont
// color = base.mainColor
// backgroundColor = base.mainBackgroundColor
}
select(".test") {
// top = Measurement.px(10)
// left = Measurement.em(5)
// backgroundColor = Color.rgba(255, 255, 255, 0.75)
select("> a") {
// color = Color.hsl(200, 50, 50)
}
}
select("nav") {
select("ul") {
// color = Color.hsl(0, 100, 25)
// backgroundColor = base.mainBackgroundColor
}
select("li") {
sizePX(25, 25, 200, 200)
select("a") {
// width = Measurement.px(725)
// background = text("red initial")
// backgroundColor = base.mainBackgroundColor
// all = All.initial()
}
}
}
}
return css.getCss()
}
fun main() {
val css1 = generateCss(StyleBase())
val css2 = generateCss(StyleBase(
Color.hsl(32, 40, 50),
Color.hsl(64, 60, 35),
text("Courier")
))
println(css1)
println(css2)
val border = css {
// borderRadius = BorderRadius(1, 2, 3, 4)
// borderColor = listOf(Color.hsl(22,66,55))
select("a") {
// width = Measurement.px(10)
}
}
val border2: Css = {
// borderRadius = BorderRadius(1, 2, 3, 4)
// borderColor = listOf(Color.hsl(20,60,50))
}
val font: Css = {
// fontFamily = text("Arial, Courier")
// fontSize = FontSize.larger()
}
val sd = style {
media("screen and (max-width: 600px)") {
fontSize(12.px())
fontWeight(FontWeight.normal)
supports("bla") {
media("bloe") {
fontSize(14.px())
}
}
}
select("#pipo") {
backgroundColor(hex("eeeeee"))
fontFamily("Arial, Courier")
// animationDelay = listOf(DelayDuration.initial())
select("div") {
fontFace {
fontFamily("SanSation")
fontSize(FontSize.larger)
src("font/sansation_bold.woff")
// fontStretch = FontStretch.condensed()
// fontStyle = FontStyle.italic()
// fontWeight = FontWeight._600()
}
fontFamily("SanSation")
// fontFamily = text("SanSation")
// color = Color.hex("1b1b1b1")
// alignContent = flexStart()
// animationName = listOf(
// text("foo"),
// text("bar")
// )
select("span") {
alignItems(AlignItems.baseline)
alignSelf(AlignSelf.flexStart)
// animationIterationCount = listOf(
// Count.count(3),
// Count.infinite()
// )
// animationTimingFunction = listOf(
// AnimationTimingFunction.cubicBezier(0.1, 0.2, 0.3, 0.4),
// AnimationTimingFunction.easeInOut()
// )
}
select("border-0") {
import(border)
// borderRadius = BorderRadius(4, 5, 6, 7)
}
select("border-1") {
import(border2)
// borderRadius = BorderRadius(4, 5, 6, 7)
}
select("border-2") {
// borderRadius = BorderRadius(4, 5, 6, 7)
import(border2)
borderStyle(BorderStyle.dashed, BorderStyle.dotted)
animationPlayState(AnimationPlayState.paused, AnimationPlayState.running)
keyFrames("mymove") {
percentage(0) {
top(0.px())
}
percentage(50) {
top(60.px())
}
percentage(100) {
top(90.px())
}
}
keyFrames("yourmove") {
percentage(0) {
top(10.px())
}
percentage(40) {
top(20.px())
}
percentage(60) {
top(30.px())
}
percentage(80) {
top(50.px())
color(Color.hex("0000ff"))
}
}
objectFit(ObjectFit.initial)
pageBreakAfter(PageBreak.auto)
tableLayout(TableLayout.auto)
tabSize(12.px())
// display = Display.none()
// borderBottomWidth = BorderWidth.perc(13)
}
}
}
}
val borderStyle = style {
select(".border") {
import(border)
import(font)
select("> p") {
// fontSize = FontSize.smaller()
}
}
}
val test = style {
select("nav") {
alignContent(AlignContent.stretch)
margin(0.px(), 2.em(), 0.5.px(), Measurement.auto)
}
}
println("======")
println(sd.generateCss())
println("======")
println(sd.generateCss(minified = true))
println("======")
println(borderStyle.generateCss())
println("======")
println(test.generateCss())
}