aboutsummaryrefslogtreecommitdiff
path: root/src/main/kotlin/org/pacien/pandoc/filter/plantuml/Filter.kt
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/kotlin/org/pacien/pandoc/filter/plantuml/Filter.kt')
-rw-r--r--src/main/kotlin/org/pacien/pandoc/filter/plantuml/Filter.kt57
1 files changed, 57 insertions, 0 deletions
diff --git a/src/main/kotlin/org/pacien/pandoc/filter/plantuml/Filter.kt b/src/main/kotlin/org/pacien/pandoc/filter/plantuml/Filter.kt
new file mode 100644
index 0000000..82a78b5
--- /dev/null
+++ b/src/main/kotlin/org/pacien/pandoc/filter/plantuml/Filter.kt
@@ -0,0 +1,57 @@
1package org.pacien.pandoc.filter.plantuml
2
3import com.fasterxml.jackson.databind.JsonNode
4import com.fasterxml.jackson.databind.ObjectMapper
5import com.fasterxml.jackson.databind.node.ArrayNode
6import com.fasterxml.jackson.databind.node.ObjectNode
7import com.fasterxml.jackson.databind.node.TextNode
8import java.io.InputStream
9import java.io.OutputStream
10
11object Filter {
12 private val mapper = ObjectMapper()
13
14 private inline fun <T> T.conditionally(condition: Boolean, block: (T) -> T): T =
15 if (condition) block(this) else this
16
17 private inline fun <T, A> T.withNonNull(value: A?, block: (T, A) -> T): T =
18 if (value != null) block(this, value) else this
19
20 private fun JsonNode.isCodeBlock() = type() == "CodeBlock"
21 private fun JsonNode.isPlantUmlBlock() = isCodeBlock() && "puml" in classNames()
22
23 private fun Latex.resizeBox(attrs: Map<String, String>) =
24 resizeBox(attrs["width"] ?: "!", attrs["height"] ?: "!")
25
26 private fun Latex.setOptions(classes: List<String>, attrs: Map<String, String>) =
27 this
28 .conditionally("width" in attrs || "height" in attrs) { it -> it.resizeBox(attrs) }
29 .conditionally("centered" in classes, Latex::centering)
30 .withNonNull(attrs["caption"], Latex::caption)
31 .withNonNull(attrs["label"], Latex::label)
32 .conditionally("caption" in attrs || "label" in attrs, Latex::figure)
33
34 private fun arrayNodeOf(type: String, content: String): ArrayNode =
35 mapper.createArrayNode()
36 .add(TextNode.valueOf(type))
37 .add(TextNode.valueOf(content))
38
39 private fun renderPlantumlNode(node: ObjectNode) {
40 val puml = node.content()
41 val tikz = PlantUml.renderTikz(puml)
42 val block = tikz.setOptions(node.classNames(), node.attributeMap())
43 node.setBlock("RawBlock", arrayNodeOf("latex", block.raw()))
44 }
45
46 private fun walk(node: JsonNode): Unit = when {
47 node.isPlantUmlBlock() -> renderPlantumlNode(node as ObjectNode)
48 else -> node.forEach(Filter::walk)
49 }
50
51 fun filter(input: InputStream, output: OutputStream) {
52 mapper.readTree(input)?.let { tree ->
53 walk(tree)
54 mapper.writeValue(output, tree)
55 }
56 }
57}