diff options
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.kt | 57 |
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 @@ | |||
1 | package org.pacien.pandoc.filter.plantuml | ||
2 | |||
3 | import com.fasterxml.jackson.databind.JsonNode | ||
4 | import com.fasterxml.jackson.databind.ObjectMapper | ||
5 | import com.fasterxml.jackson.databind.node.ArrayNode | ||
6 | import com.fasterxml.jackson.databind.node.ObjectNode | ||
7 | import com.fasterxml.jackson.databind.node.TextNode | ||
8 | import java.io.InputStream | ||
9 | import java.io.OutputStream | ||
10 | |||
11 | object 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 | } | ||