From c9d92d4b950ccb7ebf7500bc39c02dba49138966 Mon Sep 17 00:00:00 2001 From: Giorgio Garofalo Date: Thu, 5 Sep 2024 19:30:46 +0200 Subject: [PATCH] Add `.collapse` --- .../quarkdown/ast/quarkdown/block/Collapse.kt | 19 +++++++++++++++ .../rendering/html/BaseHtmlNodeRenderer.kt | 3 +++ .../html/QuarkdownHtmlNodeRenderer.kt | 11 +++++++++ .../quarkdown/visitor/node/NodeVisitor.kt | 3 +++ .../iamgio/quarkdown/HtmlNodeRendererTest.kt | 24 +++++++++++++++++++ .../rendering/quarkdown/collapse.html | 23 ++++++++++++++++++ .../eu/iamgio/quarkdown/stdlib/Layout.kt | 14 +++++++++++ 7 files changed, 97 insertions(+) create mode 100644 core/src/main/kotlin/eu/iamgio/quarkdown/ast/quarkdown/block/Collapse.kt create mode 100644 core/src/test/resources/rendering/quarkdown/collapse.html diff --git a/core/src/main/kotlin/eu/iamgio/quarkdown/ast/quarkdown/block/Collapse.kt b/core/src/main/kotlin/eu/iamgio/quarkdown/ast/quarkdown/block/Collapse.kt new file mode 100644 index 00000000..d318427e --- /dev/null +++ b/core/src/main/kotlin/eu/iamgio/quarkdown/ast/quarkdown/block/Collapse.kt @@ -0,0 +1,19 @@ +package eu.iamgio.quarkdown.ast.quarkdown.block + +import eu.iamgio.quarkdown.ast.InlineContent +import eu.iamgio.quarkdown.ast.NestableNode +import eu.iamgio.quarkdown.ast.Node +import eu.iamgio.quarkdown.visitor.node.NodeVisitor + +/** + * A collapsible block, whose content can be hidden or shown by interacting with it. + * @param title title of the block + * @param isOpen whether the block is open at the beginning + */ +data class Collapse( + val title: InlineContent, + val isOpen: Boolean, + override val children: List, +) : NestableNode { + override fun accept(visitor: NodeVisitor): T = visitor.visit(this) +} diff --git a/core/src/main/kotlin/eu/iamgio/quarkdown/rendering/html/BaseHtmlNodeRenderer.kt b/core/src/main/kotlin/eu/iamgio/quarkdown/rendering/html/BaseHtmlNodeRenderer.kt index a8aaba28..03c51562 100644 --- a/core/src/main/kotlin/eu/iamgio/quarkdown/rendering/html/BaseHtmlNodeRenderer.kt +++ b/core/src/main/kotlin/eu/iamgio/quarkdown/rendering/html/BaseHtmlNodeRenderer.kt @@ -33,6 +33,7 @@ import eu.iamgio.quarkdown.ast.quarkdown.FunctionCallNode import eu.iamgio.quarkdown.ast.quarkdown.block.Aligned import eu.iamgio.quarkdown.ast.quarkdown.block.Box import eu.iamgio.quarkdown.ast.quarkdown.block.Clipped +import eu.iamgio.quarkdown.ast.quarkdown.block.Collapse import eu.iamgio.quarkdown.ast.quarkdown.block.Math import eu.iamgio.quarkdown.ast.quarkdown.block.PageBreak import eu.iamgio.quarkdown.ast.quarkdown.block.SlidesFragment @@ -255,6 +256,8 @@ open class BaseHtmlNodeRenderer(context: Context) : TagNodeRenderer { fun visit(node: Box): T + fun visit(node: Collapse): T + fun visit(node: Whitespace): T fun visit(node: TableOfContentsView): T diff --git a/core/src/test/kotlin/eu/iamgio/quarkdown/HtmlNodeRendererTest.kt b/core/src/test/kotlin/eu/iamgio/quarkdown/HtmlNodeRendererTest.kt index 966e4316..901c3348 100644 --- a/core/src/test/kotlin/eu/iamgio/quarkdown/HtmlNodeRendererTest.kt +++ b/core/src/test/kotlin/eu/iamgio/quarkdown/HtmlNodeRendererTest.kt @@ -34,6 +34,7 @@ import eu.iamgio.quarkdown.ast.base.inline.Text import eu.iamgio.quarkdown.ast.quarkdown.block.Aligned import eu.iamgio.quarkdown.ast.quarkdown.block.Box import eu.iamgio.quarkdown.ast.quarkdown.block.Clipped +import eu.iamgio.quarkdown.ast.quarkdown.block.Collapse import eu.iamgio.quarkdown.ast.quarkdown.block.Math import eu.iamgio.quarkdown.ast.quarkdown.block.PageBreak import eu.iamgio.quarkdown.ast.quarkdown.inline.MathSpan @@ -729,6 +730,29 @@ class HtmlNodeRendererTest { ) } + @Test + fun collapse() { + val out = readParts("quarkdown/collapse.html") + + assertEquals( + out.next(), + Collapse( + title = listOf(Emphasis(listOf(Text("Hello")))), + isOpen = false, + children = listOf(Strong(listOf(Text("world")))), + ).render(), + ) + + assertEquals( + out.next(), + Collapse( + title = listOf(Text("Hello")), + isOpen = true, + children = listOf(BlockQuote(children = listOf(Paragraph(listOf(Text("world")))))), + ).render(), + ) + } + @Test fun `text transform`() { val out = readParts("quarkdown/texttransform.html") diff --git a/core/src/test/resources/rendering/quarkdown/collapse.html b/core/src/test/resources/rendering/quarkdown/collapse.html new file mode 100644 index 00000000..eb185678 --- /dev/null +++ b/core/src/test/resources/rendering/quarkdown/collapse.html @@ -0,0 +1,23 @@ +
+ + + Hello + + + + world + +
+ +--- + +
+ + Hello + +
+

+ world +

+
+
\ No newline at end of file diff --git a/stdlib/src/main/kotlin/eu/iamgio/quarkdown/stdlib/Layout.kt b/stdlib/src/main/kotlin/eu/iamgio/quarkdown/stdlib/Layout.kt index 20b88b01..22bf0254 100644 --- a/stdlib/src/main/kotlin/eu/iamgio/quarkdown/stdlib/Layout.kt +++ b/stdlib/src/main/kotlin/eu/iamgio/quarkdown/stdlib/Layout.kt @@ -6,6 +6,7 @@ import eu.iamgio.quarkdown.ast.base.block.Table import eu.iamgio.quarkdown.ast.quarkdown.block.Aligned import eu.iamgio.quarkdown.ast.quarkdown.block.Box import eu.iamgio.quarkdown.ast.quarkdown.block.Clipped +import eu.iamgio.quarkdown.ast.quarkdown.block.Collapse import eu.iamgio.quarkdown.ast.quarkdown.block.Stacked import eu.iamgio.quarkdown.ast.quarkdown.inline.Whitespace import eu.iamgio.quarkdown.context.Context @@ -32,6 +33,7 @@ val Layout: Module = ::whitespace, ::clip, ::box, + ::collapse, ::table, ) @@ -164,6 +166,18 @@ fun box( body: MarkdownContent, ) = Box(title?.children, type, padding, backgroundColor, foregroundColor, body.children).wrappedAsValue() +/** + * Inserts content in a collapsible block, whose content can be hidden or shown by interacting with it. + * @param title title of the block + * @param open whether the block is open at the beginning + * @return the new [Collapse] node + */ +fun collapse( + title: InlineMarkdownContent, + open: Boolean = false, + body: MarkdownContent, +) = Collapse(title.children, open, body.children).wrappedAsValue() + /** * Creates a table out of a collection of columns. *