Skip to content

Commit

Permalink
Merge pull request #2 from iodigital-com/improvements
Browse files Browse the repository at this point in the history
Improvements
  • Loading branch information
crysxd authored Jun 26, 2024
2 parents eadd588 + abe50e4 commit 16345b5
Show file tree
Hide file tree
Showing 7 changed files with 66 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,14 @@ internal suspend fun loadValues(
it.copyWithModeAliases(config.modeAliases)
}

val modes = values.flatMap { it.byMode.keys }.distinct()

info(tag, "Loading variables and styles:")
info(tag, "Colors: ${values.count { it.type == FigExArgbColor::class }}")
info(tag, "Floats: ${values.count { it.type == Float::class }}")
info(tag, "Strings: ${values.count { it.type == String::class }}")
info(tag, "Text styles: ${values.count { it.type == FigExTextStyle::class }}")
info(tag, " Colors: ${values.count { it.type == FigExArgbColor::class }}")
info(tag, " Floats: ${values.count { it.type == Float::class }}")
info(tag, " Strings: ${values.count { it.type == String::class }}")
info(tag, " Text styles: ${values.count { it.type == FigExTextStyle::class }}")
info(tag, " Available modes: ${modes.joinToString(", ")} (add aliases in config file!)")

values.forEach {
verbose(tag = tag, message = " ${it.name} (${it.type})")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ class FigmaApi(
}.body()

internal suspend fun loadVariable(
references: List<FigmaVariableReference>
references: List<FigmaVariableReference.WithPath>,
): List<FigExValue<*>> = withRateLimit {
loadNodes(
ids = references.map { it.plainId }.toSet()
Expand Down Expand Up @@ -115,12 +115,16 @@ class FigmaApi(
internal suspend fun loadNodes(
ids: Set<String>
) = withRateLimit {
if (ids.isEmpty()) {
return@withRateLimit FigmaNodesList(emptyMap())
}

httpClient.get {
figmaRequest("v1/files/$fileKey/nodes")
parameter("ids", ids.joinToString(","))
}.body<FigmaNodesList>().let { list ->
val withCached = list.copy(nodes = list.nodes)
withCached.resolveNestedReferences(this)
withCached.resolveNestedReferences(this, emptyList())
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import com.iodigital.figex.models.figma.FigmaVariableReference

internal fun FigmaChild.walk() = doWalk(listOf()).distinctBy { it.id }

private fun FigmaChild.doWalk(path: List<String>): List<FigmaVariableReference> {
return boundVariables + children.flatMap { it.doWalk(path + name) }
}
private fun FigmaChild.doWalk(path: List<String>): List<FigmaVariableReference.WithPath> =
boundVariables.atPath(path + name) + children.flatMap { it.doWalk(path + name) }

private fun List<FigmaVariableReference>.atPath(path: List<String>) =
map { it.atPath(path) }
Original file line number Diff line number Diff line change
Expand Up @@ -4,32 +4,33 @@ import com.iodigital.figex.api.FigmaApi
import com.iodigital.figex.models.figma.FigmaNodesList
import com.iodigital.figex.models.figma.FigmaVariableValue

internal suspend fun FigmaNodesList.resolveNestedReferences(api: FigmaApi): FigmaNodesList {
val includedIds = nodes.keys.toList()
val nestedReferences = nodes.flatMap { (_, value) ->
val referenced = value.document.valuesByMode?.mapNotNull { (_, value) ->
if (value is FigmaVariableValue.Reference) value.reference else null
internal suspend fun FigmaNodesList.resolveNestedReferences(
api: FigmaApi,
path: List<String>
): FigmaNodesList {
val nestedReferences = nodes.flatMap { (name, value) ->
val referenced = value.document.valuesByMode?.mapNotNull { (_, it) ->
if (it is FigmaVariableValue.Reference) it.reference.atPath(path + name) else null
} ?: emptyList()
val bound = value.document.boundVariables?.flatMap { (_, value) ->
value.mapNotNull {
if (it is FigmaVariableValue.Reference) it.reference else null
}
val bound = value.document.boundVariables?.flatMap { (_, it) ->
it.mapNotNull { if (it is FigmaVariableValue.Reference) it.reference.atPath(path + name) else null }
} ?: emptyList()

referenced + bound
}

return if (nestedReferences.isEmpty()) {
this
} else {
val resolvedNested = api.loadNodes(nestedReferences.map { it.plainId }.toSet())
val nodes = nodes.mapValues { (_, value) ->
val nodes = nodes.mapValues { (key, value) ->
val mappedValues = value.document.valuesByMode?.mapValues { (mode, value) ->
value.resolveSingle(mode, this + resolvedNested)
value.resolveSingle(mode, this + resolvedNested, path + key)
}

val boundVariablesByMode = value.document.boundVariables?.mapValues { (key, values) ->
require(values.size == 1) { "Expected excactly one value for ${value.document.name} -> boundVariables -> $key but got ${values.size}" }
values.first().resolveMulti(resolvedNested)
values.first().resolveMulti(resolvedNested, path + key)
}

value.copy(
Expand All @@ -44,9 +45,9 @@ internal suspend fun FigmaNodesList.resolveNestedReferences(api: FigmaApi): Figm
}
}

private fun FigmaVariableValue.resolveSingle(mode: String, values: FigmaNodesList) =
private fun FigmaVariableValue.resolveSingle(mode: String, values: FigmaNodesList, path: List<String>) =
if (this is FigmaVariableValue.Reference) {
val id = reference.plainId
val id = reference.atPath(path).plainId
val resolved = requireNotNull(values.nodes[id]) {
"Missing resolved value for $id"
}
Expand All @@ -61,9 +62,9 @@ private fun FigmaVariableValue.resolveSingle(mode: String, values: FigmaNodesLis
this
}

private fun FigmaVariableValue.resolveMulti(values: FigmaNodesList) =
private fun FigmaVariableValue.resolveMulti(values: FigmaNodesList, path: List<String>) =
if (this is FigmaVariableValue.Reference) {
val id = reference.plainId
val id = reference.atPath(path).plainId
val resolved = requireNotNull(values.nodes[id]) {
"Missing resolved value for $id"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ data class FigExConfig(
data class Values(
val templatePath: String,
val destinationPath: String,
val defaultMode: String?,
val defaultMode: String? = null,
val templateVariables: Map<String, String> = emptyMap(),
) : Export()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,27 @@ internal data class FigmaVariableReference(
val type: String,
val id: String,
) {
val plainId get() = id.removePrefix("VariableID:")
fun atPath(path: List<String>) = WithPath(
type = type,
id = id,
path = path
)

data class WithPath(
val type: String,
val id: String,
val path: List<String>,
) {
val plainId
get() = if (id.contains("/")) {
throw UnsupportedOperationException(
"""
References to external libraries are not supported at the moment, see https://github.com/iodigital-com/figex/issues/1
Affected variable: ${(path + id).joinToString(" -> ")}
""".trimIndent()
)
} else {
id.removePrefix("VariableID:")
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import kotlinx.coroutines.Job
import kotlinx.coroutines.cancel
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import java.text.DateFormat
Expand Down Expand Up @@ -78,8 +79,8 @@ internal fun verbose(tag: String, message: String) {
}
}

internal fun critical(tag: String, message: String, throwable: Throwable? = null) {
log(level = "\uFE0F", tag = tag, message = message, throwable = throwable)
internal fun critical(tag: String, message: String, throwable: Throwable? = null) = runBlocking {
log(level = "\uFE0F", tag = tag, message = message, throwable = throwable).join()
}

private fun log(level: String, tag: String, message: String, throwable: Throwable? = null) =
Expand All @@ -99,6 +100,9 @@ private fun log(level: String, tag: String, message: String, throwable: Throwabl
System.out.flush()
print(line.padEnd(status.length + 1, ' ') + "\n$status")
System.out.flush()
throwable?.printStackTrace()
throwable?.let {
print("\r\n\n")
it.printStackTrace()
}
}
}

0 comments on commit 16345b5

Please sign in to comment.