diff options
Diffstat (limited to 'src/main/kotlin/moe/nea/blog/gen/HtmlGenerator.kt')
-rw-r--r-- | src/main/kotlin/moe/nea/blog/gen/HtmlGenerator.kt | 149 |
1 files changed, 0 insertions, 149 deletions
diff --git a/src/main/kotlin/moe/nea/blog/gen/HtmlGenerator.kt b/src/main/kotlin/moe/nea/blog/gen/HtmlGenerator.kt deleted file mode 100644 index ef0858a..0000000 --- a/src/main/kotlin/moe/nea/blog/gen/HtmlGenerator.kt +++ /dev/null @@ -1,149 +0,0 @@ -package moe.nea.blog.gen - -import moe.nea.blog.md.* -import kotlin.reflect.KClass - -fun interface HtmlFragmentGenerator<T : MarkdownElement> { - fun generateHtml(htmlGenerator: HtmlGenerator, node: T): HtmlFragment -} - - -class HtmlFragment private constructor(val text: String) { - companion object { - fun ofUnescaped(text: String) = HtmlFragment( - text.replace("&", "&") - .replace("<", "<") - .replace(">", ">") - .replace("\"", """) - .replace("'", "'") - ) - - fun ofPreEscaped(text: String) = HtmlFragment(text) - fun empty(): HtmlFragment { - return HtmlFragment("") - } - } -} - -annotation class HtmlDslMarker - -@HtmlDslMarker -class HtmlDsl { - val parts = mutableListOf<HtmlFragment>() - - fun append(string: String) { - parts.add(HtmlFragment.ofUnescaped(string)) - } - - fun append(fragment: HtmlFragment) { - parts.add(fragment) - } - - fun appendPreEscaped(markup: String) { - append(HtmlFragment.ofPreEscaped(markup)) - } - - operator fun String.unaryPlus() = append(this) - operator fun HtmlFragment.unaryPlus() = append(this) - - fun element(name: String, attributes: Map<String, String>, block: HtmlDsl.() -> Unit) { - element(name, attributes, HtmlDsl().also(block).intoFragment()) - } - - fun element(name: String, attributes: Map<String, String>, fragment: HtmlFragment) { - appendPreEscaped(("<")) - append(name) - - for ((key, value) in attributes) { - appendPreEscaped((" ")) - append(key) - appendPreEscaped(("=\"")) - append(value) - appendPreEscaped(("\"")) - } - - appendPreEscaped((">")) - - append(fragment) - - appendPreEscaped(("</")) - append(name) - appendPreEscaped((">")) - } - - fun intoFragment(): HtmlFragment { - return HtmlFragment.ofPreEscaped(parts.joinToString("") { it.text }) - } -} - - -class HtmlGenerator { - private val generators = mutableMapOf<KClass<out MarkdownElement>, HtmlFragmentGenerator<MarkdownElement>>() - - fun <T : MarkdownElement> getGeneratorFor(kClass: KClass<out T>) = generators[kClass] as HtmlFragmentGenerator<T>? - - inline fun <reified T : MarkdownElement> registerFragmentGenerator(noinline outputter: HtmlDsl.(generator: HtmlGenerator, node: T) -> Unit) { - registerGeneratorFor(T::class) { gen, node -> - HtmlDsl() - .apply { outputter.invoke(this, gen, node) } - .intoFragment() - } - } - - inline fun <reified T : MarkdownElement> registerGeneratorFor(outputter: HtmlFragmentGenerator<T>) { - registerGeneratorFor(T::class, outputter) - } - - fun <T : MarkdownElement> registerGeneratorFor(kClass: KClass<T>, outputter: HtmlFragmentGenerator<T>) { - generators[kClass] = outputter as HtmlFragmentGenerator<MarkdownElement> - } - - fun registerDefaultGenerators() { - registerGeneratorFor<Begin> { _, _ -> HtmlFragment.empty() } - registerFragmentGenerator<Header> { gen, header -> - element("h${header.level}", mapOf()) { - +header.text - } - } - registerFragmentGenerator<Bold> { gen, node -> - element("b", mapOf(), gen.generateHtml(node.inner)) - } - registerFragmentGenerator<Italics> { generator, node -> - element("em", mapOf(), generator.generateHtml(node.inner)) - } - registerFragmentGenerator<Link> { generator, node -> - element("a", mapOf("href" to node.target), generator.generateHtml(node.label ?: Begin())) - } - registerFragmentGenerator<Paragraph> { generator, node -> - element("p", mapOf(), generator.generateHtml(node.format)) - } - registerFragmentGenerator<CodeBlock> { generator, node -> - element("pre", mapOf()) { - element("code", mapOf("class" to "language-${node.language}")) { - append(node.lines.joinToString("\n")) - } - } - } - registerFragmentGenerator<FormatSequence> { generator, node -> - for (markdownFormat in node.list) { - append(generator.generateHtml(markdownFormat)) - } - } - registerFragmentGenerator<Word> { generator, node -> - append(node.text) - } - registerFragmentGenerator<Whitespace> { generator, node -> - append(" ") - } - registerFragmentGenerator<Document> { generator, node -> - for (markdownBlock in node.list) { - append(generator.generateHtml(markdownBlock)) - } - } - } - - fun <T : MarkdownElement> generateHtml(node: T): HtmlFragment { - val gen = getGeneratorFor(node::class) ?: error("Missing html generator for $node") - return gen.generateHtml(this, node) - } -}
\ No newline at end of file |