Skip to content

Commit 4cc1722

Browse files
committed
Merge remote-tracking branch 'origin/master'
# Conflicts: # converter/src/main/kotlin/de/jensklingenberg/htmltocfw/converter/Main.kt # converter/src/main/kotlin/de/jensklingenberg/htmltocfw/converter/Result.txt # converter/src/main/kotlin/de/jensklingenberg/htmltocfw/converter/html.text # ideaplugin/gradle.properties
2 parents 477e605 + 15ada48 commit 4cc1722

26 files changed

+903
-267
lines changed

Changelog.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
### 1.0.5
2+
3+
<ul>
4+
<li>KeyFrame rules in < style> tag will now be converted to
5+
Compose for Web StyleSheets</li>
6+
<li> font-face rules will be converted to KotlinJS code</li>
7+
</ul>
8+
19
### 1.0.4
210

311
<ul>

README.md

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ Into this:
4141
The <script> tag will be ignored, but inlined Javascript will be set without changes to the corresponding property. See the "button" code example above.
4242

4343

44-
4544
## :arrow_down:&nbsp;How to install?
4645

4746
[JetBrains Marketplace](https://plugins.jetbrains.com/plugin/18261-html-to-compose-web-converter)
@@ -67,14 +66,12 @@ Alternatively you can download the plugin from the release archive https://githu
6766

6867
## :fire:&nbsp;What's new?
6968

70-
### 1.0.4
69+
### 1.0.5
7170

7271
<ul>
73-
<li>CSS style rules and media rules in < style> tag will now be converted to
72+
<li>KeyFrame rules in < style> tag will now be converted to
7473
Compose for Web StyleSheets</li>
75-
<li>All generated Code will be wrapped inside a Composable called GeneratedComposable() </li>
76-
<li> < title> will be converted to KotlinJS document.title=XZY </li>
77-
74+
<li> font-face rules will be converted to KotlinJS code</li>
7875
</ul>
7976

8077
# 🏠 Architecture

converter/src/main/kotlin/de/jensklingenberg/htmltocfw/converter/Attributes.kt

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,17 @@
11
package de.jensklingenberg.htmltocfw.converter
22

3+
import de.jensklingenberg.htmltocfw.converter.node.ComposeAttribute
34
import org.jsoup.nodes.Attribute
45

6+
fun parseAttributes(attributesList: List<Attribute>): String {
7+
return parseAttributes(attributesList.map { ComposeAttribute(it.key,it.value) })
8+
}
9+
510
/**
611
*
712
*/
8-
fun parseAttributes(attributesList: List<Attribute>): String {
13+
@JvmName("parseAttributes1")
14+
fun parseAttributes(attributesList: List<ComposeAttribute>): String {
915

1016
var str = ""
1117
attributesList.forEachIndexed { index, attribute ->
@@ -21,7 +27,7 @@ fun parseAttributes(attributesList: List<Attribute>): String {
2127
"draggable(Draggable.${attribute.value.capitalize()})"
2228
}
2329
"style" -> {
24-
parseStyleText(attribute)
30+
parseStyleText(ComposeAttribute(attribute.key,attribute.value))
2531
}
2632
"required", "hidden", "selected", "disabled" -> {
2733
attribute.key + "()"
@@ -45,6 +51,7 @@ fun parseAttributes(attributesList: List<Attribute>): String {
4551
}
4652
}
4753
str += "\n"
54+
4855
if (index == attributesList.lastIndex) {
4956
str += "}"
5057
}

converter/src/main/kotlin/de/jensklingenberg/htmltocfw/converter/Main.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,14 @@ fun htmlToCompose(html: String): String {
3333
getMyNode(node).toString()
3434
}
3535

36-
val wrappedBody = if (hasStyle) {
36+
val bodyContent = if (hasStyle) {
3737
"Style(appStylesheet())\n$body"
3838
} else {
3939
body
4040
}
4141

4242

43-
return "@Composable\nfun GeneratedComposable(){\n $head \n$wrappedBody}\n"
43+
return "@Composable\nfun GeneratedComposable(){\n $head \n$bodyContent}\n"
4444
}
4545

4646

converter/src/main/kotlin/de/jensklingenberg/htmltocfw/converter/Style.kt

Lines changed: 73 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,77 @@
11
package de.jensklingenberg.htmltocfw.converter
22

3-
import org.jsoup.nodes.Attribute
3+
import de.jensklingenberg.htmltocfw.converter.node.ComposeAttribute
4+
import de.jensklingenberg.htmltocfw.converter.node.withEscapedSymbol
5+
6+
7+
fun parsePropertyValueWithCssUnit(propName: String, propValue: String, composePropName: String): String {
8+
val unitType = unitsMap.entries.find { propValue.endsWith(it.value) }
9+
10+
return if (unitType == null) {
11+
"$composePropName(\"${propValue}\")"
12+
} else {
13+
val newValue = propValue.split(" ").joinToString { it.replace(unitType.value, ".${unitType.key}") }
14+
"$composePropName(${newValue})"
15+
}
16+
17+
}
418

519
/**
620
*
721
*/
822
fun parseStyleProperties(propName: String, propValue: String): String {
923

1024
return when (propName) {
11-
"background-image" -> {
12-
"backgroundImage(${propValue})"
13-
}
14-
"border-radius" -> {
15-
val unitType = unitsMap.entries.find { propValue.endsWith(it.value) }
16-
17-
if (unitType == null) {
18-
"property(\"$propName\",\"${propValue}\")"
19-
} else {
20-
val newValue = propValue.split(" ").joinToString { it.replace(unitType.value, "") + ".${unitType.key}" }
21-
"borderRadius(${newValue})"
25+
"animation" -> {
26+
var str = ""
27+
val animationPropertyList = propValue.split(" ")
28+
val keyFrameName = animationPropertyList.getOrNull(0)
29+
val duration = animationPropertyList.getOrNull(1)
30+
val iterationCount = animationPropertyList.getOrNull(2)
31+
32+
keyFrameName?.let {
33+
str += "animation(${keyFrameName}){\n"
34+
}
35+
duration?.let {
36+
str += parseStyleProperties("duration", duration) + "\n"
37+
}
38+
39+
iterationCount?.let {
40+
str += "iterationCount = listOf(" + if (iterationCount == "infinite") {
41+
"null)"
42+
} else {
43+
"$it)"
44+
}
45+
2246
}
47+
48+
str += "}"
49+
str
2350
}
24-
"box-sizing" -> {
25-
"boxSizing(\"${propValue}\")"
51+
"animation-duration", "animation-delay" -> {
52+
//Ignore
53+
""
2654
}
27-
"cursor" -> {
28-
"cursor(\"${propValue}\")"
55+
"border" -> {
56+
val animationPropertyList = propValue.split(" ")
57+
val widthValue = animationPropertyList.getOrNull(0)
58+
val lineStyle = animationPropertyList.getOrNull(1)
59+
val color = animationPropertyList.getOrNull(2)
60+
var str = "border {\n"
61+
widthValue?.let {
62+
str += parseStyleProperties("width", widthValue) + "\n"
63+
}
64+
color?.let {
65+
str += parseStyleProperties("color", it) + "\n"
66+
}
67+
lineStyle?.let {
68+
str += "style(LineStyle.${it.capitalize()})" + "\n"
69+
}
70+
71+
str += "\n}"
72+
str
2973
}
74+
3075
"display" -> {
3176
"display(DisplayStyle.${propValue.capitalize()})"
3277
}
@@ -36,47 +81,30 @@ fun parseStyleProperties(propName: String, propValue: String): String {
3681
"flex-wrap" -> {
3782
"flexWrap(FlexWrap.${propValue.capitalize()})"
3883
}
39-
"font-family" -> {
40-
"fontFamily(\"${propValue}\")"
41-
}
42-
"font-size" -> {
43-
val unitType = unitsMap.entries.find { propValue.endsWith(it.value) }
44-
45-
if (unitType == null) {
46-
"property(\"$propName\",\"${propValue}\")"
47-
} else {
48-
val newValue = propValue.split(" ").joinToString { it.replace(unitType.value, "") + ".${unitType.key}" }
49-
"fontSize(${newValue})"
50-
}
51-
}
52-
"text-align" -> {
53-
"textAlign(\"${propValue}\")"
84+
"position" -> {
85+
"position(Position.${propValue.capitalize()})"
5486
}
5587

56-
"text-decoration" -> {
57-
"textDecoration(\"${propValue}\")"
88+
"background-image", "border-radius", "box-sizing", "font-size", "letter-spacing", "text-align", "text-decoration" -> {
89+
//font-size --> fontSize
90+
val (first, second) = propName.split("-")
91+
val composePropName = first + second.capitalize()
92+
parsePropertyValueWithCssUnit(propName, propValue.withEscapedSymbol(), composePropName)
5893
}
59-
"height", "width", "font", "margin", "padding" -> {
60-
val unitType = unitsMap.entries.find { propValue.endsWith(it.value) }
6194

62-
if (unitType == null) {
63-
"property(\"$propName\",\"${propValue}\")"
64-
} else {
65-
66-
val newValue =
67-
propValue.split(" ").joinToString { it.replace(unitType.value, "") + ".${unitType.key}" }
68-
"$propName(${newValue})"
69-
}
95+
"cursor", "duration", "font", "height", "width", "margin", "padding", "left", "top", "bottom" -> {
96+
parsePropertyValueWithCssUnit(propName, propValue, propName)
7097
}
7198
else -> {
72-
"property(\"$propName\",\"${propValue}\")"
99+
val fixValue = propValue.replace("\"", "\\\"")
100+
"property(\"$propName\",\"${fixValue}\")"
73101
}
74102
}
75103

76104
}
77105

78106

79-
fun parseStyleText(attribute: Attribute): String {
107+
fun parseStyleText(attribute: ComposeAttribute): String {
80108
var str = "style {\n"
81109

82110
//Find better way to parse style
Lines changed: 35 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,38 @@
11
package de.jensklingenberg.htmltocfw.converter.node
22

33
import de.jensklingenberg.htmltocfw.converter.parseAttributes
4-
import org.jsoup.nodes.Attributes
4+
import de.jensklingenberg.htmltocfw.converter.visitor.Visitor
5+
import org.jsoup.nodes.Element
56
import org.jsoup.nodes.Node
67

78
/**
89
* This class generates the code for
910
* [org.jetbrains.compose.web.dom.A]
1011
*/
11-
class ANode(private val htmlAttributes: Attributes, val childNodes: List<Node>) : MyNode {
12-
private val TAG = "A"
13-
private val ATTR_HREF = "href"
12+
class ANode(
13+
val childNodes: List<Node>,
14+
val href: String = "",
15+
val attrs: List<ComposeAttribute>
16+
) : MyNode {
17+
18+
override fun accept(visitor: Visitor) {
19+
visitor.visitA(this)
20+
}
1421

1522
override fun toString(): String {
1623

17-
var str = "$TAG ("
18-
val hrefValue = htmlAttributes.get(ATTR_HREF)
19-
htmlAttributes.remove(ATTR_HREF)
24+
var str = "A ("
25+
val hrefValue = href
2026

21-
val attrText = parseAttributes(htmlAttributes.asList())
22-
str += attrText
27+
val arguments = mutableListOf<String>()
2328

24-
if (hrefValue.isNotBlank()) {
25-
if (attrText.isNotBlank()) {
26-
str += (", ")
27-
}
29+
if(attrs.isNotEmpty()){
30+
arguments.add(parseAttributes(attrs))
2831
}
29-
str += ("href = \"${hrefValue}\"") + ")"
32+
33+
arguments.add("href = \"${hrefValue}\"")
34+
35+
str += arguments.joinToString { it } + ")"
3036

3137
val childNodesText = childNodes.joinToString(separator = "") {
3238
getMyNode(it).toString()
@@ -42,4 +48,18 @@ class ANode(private val htmlAttributes: Attributes, val childNodes: List<Node>)
4248
return str
4349
}
4450

45-
}
51+
companion object {
52+
53+
fun createANode(node: Element): ANode {
54+
val htmlAttributes = node.attributes()
55+
val hrefValue = htmlAttributes.get("href")
56+
htmlAttributes.remove("href")
57+
58+
val compo = htmlAttributes.asList().map { ComposeAttribute(it.key, it.value) }
59+
return ANode( node.childNodes(), hrefValue, compo)
60+
61+
}
62+
}
63+
64+
}
65+

converter/src/main/kotlin/de/jensklingenberg/htmltocfw/converter/node/CFWComment.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
11
package de.jensklingenberg.htmltocfw.converter.node
22

3+
import de.jensklingenberg.htmltocfw.converter.visitor.Visitor
34
import org.jsoup.nodes.Comment
45

56
class CFWComment(private val comment: Comment) : MyNode {
7+
override fun accept(visitor: Visitor) {
8+
visitor.visitComment(this)
9+
}
10+
611
override fun toString(): String {
712
return ("//" + comment.data + "\n")
813
}

converter/src/main/kotlin/de/jensklingenberg/htmltocfw/converter/node/CFWTextNode.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package de.jensklingenberg.htmltocfw.converter.node
22

3+
import de.jensklingenberg.htmltocfw.converter.visitor.Visitor
34
import org.jsoup.nodes.TextNode
45

56
/**
@@ -16,4 +17,8 @@ class CFWTextNode(private val textNode: TextNode) : MyNode {
1617
}
1718
}
1819

20+
override fun accept(visitor: Visitor) {
21+
visitor.visitText(this)
22+
}
23+
1924
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
package de.jensklingenberg.htmltocfw.converter.node
2+
3+
data class ComposeAttribute(val key: String, val value: String)

converter/src/main/kotlin/de/jensklingenberg/htmltocfw/converter/node/EmptyNode.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
package de.jensklingenberg.htmltocfw.converter.node
22

3+
import de.jensklingenberg.htmltocfw.converter.visitor.Visitor
4+
35
class EmptyNode : MyNode {
6+
override fun accept(visitor: Visitor) {
7+
visitor.visitEmpty(this)
8+
}
9+
410
override fun toString(): String {
511
return ""
612
}

0 commit comments

Comments
 (0)