From 2b25176b50e84e654975d3e53dce3e3d14ab212a Mon Sep 17 00:00:00 2001 From: Giorgio Garofalo Date: Sat, 23 Nov 2024 18:30:21 +0100 Subject: [PATCH] Strip headings' rich content from ToC entries --- .../ast/quarkdown/block/toc/TableOfContentsUtils.kt | 8 ++++++-- .../rendering/html/QuarkdownHtmlNodeRenderer.kt | 1 + .../main/kotlin/eu/iamgio/quarkdown/util/NodeUtils.kt | 10 ++++++++++ .../eu/iamgio/quarkdown/test/FullPipelineTest.kt | 6 +++--- 4 files changed, 20 insertions(+), 5 deletions(-) diff --git a/core/src/main/kotlin/eu/iamgio/quarkdown/ast/quarkdown/block/toc/TableOfContentsUtils.kt b/core/src/main/kotlin/eu/iamgio/quarkdown/ast/quarkdown/block/toc/TableOfContentsUtils.kt index 2202d563..25bcbb71 100644 --- a/core/src/main/kotlin/eu/iamgio/quarkdown/ast/quarkdown/block/toc/TableOfContentsUtils.kt +++ b/core/src/main/kotlin/eu/iamgio/quarkdown/ast/quarkdown/block/toc/TableOfContentsUtils.kt @@ -8,13 +8,17 @@ import eu.iamgio.quarkdown.ast.quarkdown.block.list.FocusListItemVariant import eu.iamgio.quarkdown.ast.quarkdown.block.list.LocationTargetListItemVariant import eu.iamgio.quarkdown.context.toc.TableOfContents import eu.iamgio.quarkdown.document.numbering.DocumentNumbering +import eu.iamgio.quarkdown.util.stripRichContent +import eu.iamgio.quarkdown.visitor.node.NodeVisitor /** * Converts a table of contents to a renderable [OrderedList]. + * @param renderer renderer to use to render items * @param items ToC items [this] view should contain * @param linkUrlMapper function that obtains the URL to send to when a ToC item is interacted with */ fun TableOfContentsView.convertToListNode( + renderer: NodeVisitor, items: List, linkUrlMapper: (TableOfContents.Item) -> String, ): OrderedList = @@ -25,7 +29,7 @@ fun TableOfContentsView.convertToListNode( // A link to the target heading. this += Link( - item.text, + item.text.stripRichContent(renderer), // Rich content is ignored. url = linkUrlMapper(item), title = null, ) @@ -33,7 +37,7 @@ fun TableOfContentsView.convertToListNode( // Recursively include sub-items. item.subItems.filter { it.depth <= view.maxDepth } .takeIf { it.isNotEmpty() } - ?.let { this += convertToListNode(it, linkUrlMapper) } + ?.let { this += convertToListNode(renderer, it, linkUrlMapper) } } return OrderedList( diff --git a/core/src/main/kotlin/eu/iamgio/quarkdown/rendering/html/QuarkdownHtmlNodeRenderer.kt b/core/src/main/kotlin/eu/iamgio/quarkdown/rendering/html/QuarkdownHtmlNodeRenderer.kt index 2c3a693f..18c25ca8 100644 --- a/core/src/main/kotlin/eu/iamgio/quarkdown/rendering/html/QuarkdownHtmlNodeRenderer.kt +++ b/core/src/main/kotlin/eu/iamgio/quarkdown/rendering/html/QuarkdownHtmlNodeRenderer.kt @@ -270,6 +270,7 @@ class QuarkdownHtmlNodeRenderer(context: Context) : BaseHtmlNodeRenderer(context // Content +buildTag("nav") { +node.convertToListNode( + this@QuarkdownHtmlNodeRenderer, tableOfContents.items, linkUrlMapper = { item -> "#" + HtmlIdentifierProvider.of(this@QuarkdownHtmlNodeRenderer).getId(item.target) diff --git a/core/src/main/kotlin/eu/iamgio/quarkdown/util/NodeUtils.kt b/core/src/main/kotlin/eu/iamgio/quarkdown/util/NodeUtils.kt index cae58626..27e21fdc 100644 --- a/core/src/main/kotlin/eu/iamgio/quarkdown/util/NodeUtils.kt +++ b/core/src/main/kotlin/eu/iamgio/quarkdown/util/NodeUtils.kt @@ -6,6 +6,7 @@ import eu.iamgio.quarkdown.ast.NestableNode import eu.iamgio.quarkdown.ast.Node import eu.iamgio.quarkdown.ast.base.inline.CriticalContent import eu.iamgio.quarkdown.ast.base.inline.PlainTextNode +import eu.iamgio.quarkdown.ast.dsl.buildInline import eu.iamgio.quarkdown.ast.quarkdown.inline.TextSymbol import eu.iamgio.quarkdown.visitor.node.NodeVisitor @@ -87,3 +88,12 @@ fun InlineContent.toPlainText(renderer: NodeVisitor? = null): Stri return builder.toString() } + +/** + * Strips rich content from [this] inline content and returns a new inline content with only one [eu.iamgio.quarkdown.ast.base.inline.Text] child, + * which contains the plain text representation of [this] inline content. + * @param renderer optional renderer to use to render critical content and text symbols + * @return inline content with only plain text + * @see toPlainText + */ +fun InlineContent.stripRichContent(renderer: NodeVisitor? = null): InlineContent = buildInline { text(toPlainText(renderer)) } diff --git a/test/src/test/kotlin/eu/iamgio/quarkdown/test/FullPipelineTest.kt b/test/src/test/kotlin/eu/iamgio/quarkdown/test/FullPipelineTest.kt index 1306e273..e07677e6 100644 --- a/test/src/test/kotlin/eu/iamgio/quarkdown/test/FullPipelineTest.kt +++ b/test/src/test/kotlin/eu/iamgio/quarkdown/test/FullPipelineTest.kt @@ -1608,7 +1608,7 @@ class FullPipelineTest { "

TOC

" + "