204 lines
7.6 KiB
Kotlin
204 lines
7.6 KiB
Kotlin
plugins {
|
|
alias(libs.plugins.kotlin.multiplatform)
|
|
id("kobweb-compose")
|
|
id("com.varabyte.kobweb.internal.publish")
|
|
}
|
|
|
|
group = "com.varabyte.kobwebx"
|
|
version = libs.versions.kobweb.get()
|
|
|
|
private val GENERATED_SRC_ROOT = "build/generated/icons/src/jsMain/kotlin"
|
|
|
|
enum class IconCategory {
|
|
SOLID,
|
|
REGULAR,
|
|
BRAND,
|
|
}
|
|
|
|
val generateIconsTask = tasks.register("generateIcons") {
|
|
val srcFile = layout.projectDirectory.file("fa-icon-list.txt")
|
|
val dstFile =
|
|
layout.projectDirectory.file("$GENERATED_SRC_ROOT/com/varabyte/kobweb/silk/components/icons/fa/FaIcons.kt")
|
|
|
|
inputs.files(srcFile)
|
|
outputs.dir(GENERATED_SRC_ROOT)
|
|
|
|
doLast {
|
|
// {SOLID=[ad, address-book, address-card, ...], REGULAR=[address-book, address-card, angry, ...], ... }
|
|
val iconRawNames = srcFile.asFile
|
|
.readLines().asSequence()
|
|
.filter { line -> !line.startsWith("#") }
|
|
.map { line ->
|
|
// Convert icon name to function name, e.g.
|
|
// align-left -> FaAlignLeft
|
|
line.split("=", limit = 2).let { parts ->
|
|
val category = when (parts[0]) {
|
|
"fas" -> IconCategory.SOLID
|
|
"far" -> IconCategory.REGULAR
|
|
"fab" -> IconCategory.BRAND
|
|
else -> throw GradleException("Unexpected category string: ${parts[0]}")
|
|
}
|
|
val names = parts[1]
|
|
|
|
category to names.split(",")
|
|
}
|
|
}
|
|
.toMap()
|
|
|
|
// For each icon name, figure out what categories they are in. This will affect the function signature we generate.
|
|
// {ad=[SOLID], address-book=[SOLID, REGULAR], address-card=[SOLID, REGULAR], ...
|
|
val iconCategories = mutableMapOf<String, MutableSet<IconCategory>>()
|
|
iconRawNames.forEach { entry ->
|
|
val category = entry.key
|
|
entry.value.forEach { rawName ->
|
|
iconCategories.computeIfAbsent(rawName, { mutableSetOf() }).add(category)
|
|
}
|
|
}
|
|
|
|
// Sanity check results
|
|
iconCategories
|
|
.filterNot { entry ->
|
|
val categories = entry.value
|
|
categories.size == 1 ||
|
|
(categories.size == 2 && categories.contains(IconCategory.SOLID) && categories.contains(IconCategory.REGULAR))
|
|
}
|
|
.let { invalidGroupings ->
|
|
if (invalidGroupings.isNotEmpty()) {
|
|
throw GradleException("Found unexpected groupings. An icon should only be in its own category OR it can have solid and regular versions: $invalidGroupings")
|
|
}
|
|
}
|
|
|
|
// Generate four types of functions: solid only, regular only, solid or regular, and brand
|
|
val iconMethodEntries = iconCategories
|
|
.map { entry ->
|
|
val rawName = entry.key
|
|
// Convert e.g. "align-items" to "FaAlignItems"
|
|
@Suppress("DEPRECATION") // capitalize is way more readable than a direct replacement
|
|
val methodName = "Fa${rawName.split("-").joinToString("") { it.capitalize() }}"
|
|
val categories = entry.value
|
|
|
|
when {
|
|
categories.size == 2 -> {
|
|
"@Composable fun $methodName(modifier: Modifier = Modifier, style: IconStyle = IconStyle.OUTLINE, size: IconSize? = null) = FaIcon(\"$rawName\", modifier, style.category, size)"
|
|
}
|
|
|
|
categories.contains(IconCategory.SOLID) -> {
|
|
"@Composable fun $methodName(modifier: Modifier = Modifier, size: IconSize? = null) = FaIcon(\"$rawName\", modifier, IconCategory.SOLID, size)"
|
|
}
|
|
|
|
categories.contains(IconCategory.REGULAR) -> {
|
|
"@Composable fun $methodName(modifier: Modifier = Modifier, size: IconSize? = null) = FaIcon(\"$rawName\", modifier, IconCategory.REGULAR, size)"
|
|
}
|
|
|
|
categories.contains(IconCategory.BRAND) -> {
|
|
"@Composable fun $methodName(modifier: Modifier = Modifier, size: IconSize? = null) = FaIcon(\"$rawName\", modifier, IconCategory.BRAND, size)"
|
|
}
|
|
|
|
else -> GradleException("Unhandled icon entry: $entry")
|
|
}
|
|
}
|
|
|
|
val iconsCode =
|
|
"""
|
|
|//@formatter:off
|
|
|@file:Suppress("unused", "SpellCheckingInspection")
|
|
|
|
|
|// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
|
|// THIS FILE IS AUTOGENERATED.
|
|
|//
|
|
|// Do not edit this file by hand. Instead, update `fa-icon-list.txt` in the module root and run the Gradle
|
|
|// task "generateIcons"
|
|
|// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
|
|
|
|
|package com.varabyte.kobweb.silk.components.icons.fa
|
|
|
|
|
|import androidx.compose.runtime.*
|
|
|import com.varabyte.kobweb.compose.ui.Modifier
|
|
|import com.varabyte.kobweb.compose.ui.toAttrs
|
|
|import org.jetbrains.compose.web.dom.Span
|
|
|
|
|
|enum class IconCategory(internal val className: String) {
|
|
| REGULAR("far"),
|
|
| SOLID("fas"),
|
|
| BRAND("fab");
|
|
|}
|
|
|
|
|
|enum class IconStyle(internal val category: IconCategory) {
|
|
| FILLED(IconCategory.SOLID),
|
|
| OUTLINE(IconCategory.REGULAR);
|
|
|}
|
|
|
|
|
|// See: https://fontawesome.com/docs/web/style/size
|
|
|enum class IconSize(internal val className: String) {
|
|
| // Relative sizes
|
|
| XXS("fa-2xs"),
|
|
| XS("fa-xs"),
|
|
| SM("fa-sm"),
|
|
| LG("fa-lg"),
|
|
| XL("fa-xl"),
|
|
| XXL("fa-2xl"),
|
|
|
|
|
| // Literal sizes
|
|
| X1("fa-1x"),
|
|
| X2("fa-2x"),
|
|
| X3("fa-3x"),
|
|
| X4("fa-4x"),
|
|
| X5("fa-5x"),
|
|
| X6("fa-6x"),
|
|
| X7("fa-7x"),
|
|
| X8("fa-8x"),
|
|
| X9("fa-9x"),
|
|
| X10("fa-10x");
|
|
|}
|
|
|
|
|
|@Composable
|
|
|fun FaIcon(
|
|
| name: String,
|
|
| modifier: Modifier,
|
|
| style: IconCategory = IconCategory.REGULAR,
|
|
| size: IconSize? = null,
|
|
|) {
|
|
| Span(
|
|
| attrs = modifier.toAttrs {
|
|
| classes(style.className, "fa-${'$'}name")
|
|
| if (size != null) {
|
|
| classes(size.className)
|
|
| }
|
|
| }
|
|
| )
|
|
|}
|
|
|
|
|
|${iconMethodEntries.joinToString("\n")}
|
|
""".trimMargin()
|
|
|
|
dstFile.asFile.apply {
|
|
parentFile.mkdirs()
|
|
writeText(iconsCode)
|
|
}
|
|
}
|
|
}
|
|
|
|
kotlin {
|
|
js {
|
|
browser()
|
|
}
|
|
|
|
sourceSets {
|
|
jsMain {
|
|
kotlin.srcDir(generateIconsTask)
|
|
dependencies {
|
|
implementation(libs.compose.runtime)
|
|
implementation(libs.compose.html.core)
|
|
|
|
api(projects.frontend.kobwebCompose)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
kobwebPublication {
|
|
artifactName.set("Kobweb Silk Icons (Font Awesome)")
|
|
artifactId.set("silk-icons-fa")
|
|
description.set("A collection of composables that directly wrap Font Awesome icons.")
|
|
}
|