Skip to content

Commit

Permalink
Fix value + iterable append
Browse files Browse the repository at this point in the history
  • Loading branch information
iamgio committed Jun 24, 2024
1 parent 0746156 commit 0c6ed4a
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import eu.iamgio.quarkdown.function.value.DynamicValue
import eu.iamgio.quarkdown.function.value.EnumValue
import eu.iamgio.quarkdown.function.value.GeneralCollectionValue
import eu.iamgio.quarkdown.function.value.InlineMarkdownContentValue
import eu.iamgio.quarkdown.function.value.InputValue
import eu.iamgio.quarkdown.function.value.IterableValue
import eu.iamgio.quarkdown.function.value.LambdaValue
import eu.iamgio.quarkdown.function.value.MarkdownContentValue
import eu.iamgio.quarkdown.function.value.NumberValue
Expand Down Expand Up @@ -46,22 +48,32 @@ class AppendExpressionVisitor(private val other: Expression) : ExpressionVisitor
/**
* @return string result of the concatenation between [this] and [other]
*/
private fun Value<*>.concatenate(): String {
private fun Value<*>.concatenate(): InputValue<*> {
val otherEval = other.eval() // Evaluate the next expression.

// If the other value is a collection, add the current value to it as the first element.
if (otherEval is IterableValue<*> && this is OutputValue<*>) {
return GeneralCollectionValue(listOf(this, *otherEval.unwrappedValue.toList().toTypedArray()))
}

// Concatenate the string representation of the two values.

fun stringify(value: Value<*>) =
when (value) {
is VoidValue -> ""
else -> value.unwrappedValue.toString()
}
return stringify(this) + stringify(other.eval())

return StringValue(stringify(this) + stringify(otherEval))
}

// "abc" "def" -> "abcdef"
// "abc" .sum {2} {3} -> "abc5"
override fun visit(value: StringValue) = StringValue(value.concatenate())
override fun visit(value: StringValue) = value.concatenate()

// 15 "abc" -> "15abc"
// 15 8 -> "158"
override fun visit(value: NumberValue) = StringValue(value.concatenate())
override fun visit(value: NumberValue) = value.concatenate()

// true false -> false
// false true -> false
Expand All @@ -71,7 +83,7 @@ class AppendExpressionVisitor(private val other: Expression) : ExpressionVisitor
when (other) {
// Logic AND between values.
is BooleanValue -> BooleanValue(value.unwrappedValue && other.unwrappedValue)
else -> StringValue(value.concatenate())
else -> value.concatenate()
}

// [a, b, c] "abc" -> [a, b, c, "abc"]
Expand All @@ -95,10 +107,10 @@ class AppendExpressionVisitor(private val other: Expression) : ExpressionVisitor
// CENTER "abc" -> "CENTERabc"
// CENTER CENTER -> "CENTERCENTER"
// CENTER 15 -> "CENTER15"
override fun visit(value: EnumValue) = StringValue(value.concatenate())
override fun visit(value: EnumValue) = value.concatenate()

// obj "abc" -> "objabc"
override fun visit(value: ObjectValue<*>) = StringValue(value.concatenate())
override fun visit(value: ObjectValue<*>) = value.concatenate()

private fun concatenateAsNodes(root: Node): List<Node> {
val nodes = mutableListOf(root)
Expand Down Expand Up @@ -127,7 +139,7 @@ class AppendExpressionVisitor(private val other: Expression) : ExpressionVisitor
}

// Like visit(StringValue)
override fun visit(value: DynamicValue): Expression = DynamicValue(value.concatenate())
override fun visit(value: DynamicValue): Expression = DynamicValue(value.concatenate().unwrappedValue)

// TODO append lambda
override fun visit(value: LambdaValue): Expression = throw UnsupportedOperationException()
Expand All @@ -136,7 +148,7 @@ class AppendExpressionVisitor(private val other: Expression) : ExpressionVisitor
override fun visit(expression: FunctionCall<*>): Expression =
when (val result = expression.eval()) {
is Expression -> result.append(other)
else -> StringValue(result.concatenate())
else -> result.concatenate()
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import eu.iamgio.quarkdown.function.value.NodeValue
import eu.iamgio.quarkdown.function.value.NumberValue
import eu.iamgio.quarkdown.function.value.ObjectValue
import eu.iamgio.quarkdown.function.value.OrderedCollectionValue
import eu.iamgio.quarkdown.function.value.OutputValue
import eu.iamgio.quarkdown.function.value.StringValue
import eu.iamgio.quarkdown.function.value.UnorderedCollectionValue
import eu.iamgio.quarkdown.function.value.ValueFactory
Expand Down Expand Up @@ -66,10 +67,16 @@ class NodeOutputValueVisitor(private val context: Context) : OutputValueVisitor<

override fun visit(value: VoidValue) = BlockText()

// Dynamic output (e.g. produced by the stdlib function `.function`) is treated as Markdown by default.
override fun visit(value: DynamicValue) =
when (val raw = value.unwrappedValue) {
is Node -> raw
else -> this.visit(ValueFactory.blockMarkdown(raw.toString(), context).asNodeValue())
// Dynamic output (e.g. produced by the stdlib function `.function`) is treated:
// - If it is a suitable output value: its content is visited again with this visitor.
// - If it is a collection: its items are wrapped in a GeneralCollectionValue and visited.
// - Otherwise: its string content is parsed as Markdown.
@Suppress("UNCHECKED_CAST")
override fun visit(value: DynamicValue): Node {
return when (value.unwrappedValue) {
is OutputValue<*> -> value.unwrappedValue.accept(this)
is Iterable<*> -> GeneralCollectionValue(value.unwrappedValue as Iterable<OutputValue<*>>).accept(this)
else -> this.visit(ValueFactory.blockMarkdown(value.unwrappedValue.toString(), context).asNodeValue())
}
}
}
11 changes: 11 additions & 0 deletions test/src/test/kotlin/eu/iamgio/quarkdown/test/FullPipelineTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,17 @@ class FullPipelineTest {
assertEquals("<h1>Title</h1><p>Hi 0</p><p>Hi 1</p>", it)
}

execute(
"""
.foreach {..2}
# Hello
.foreach {..1}
**Hi**!
""".trimIndent(),
) {
assertEquals("<h1>Hello</h1><p><strong>Hi</strong>!</p><h1>Hello</h1><p><strong>Hi</strong>!</p>", it)
}

execute(
"""
.foreach {..2}
Expand Down

0 comments on commit 0c6ed4a

Please sign in to comment.