From e0146f4c28663aeef990a2bad25e12d8ae65ac97 Mon Sep 17 00:00:00 2001 From: David Gregorczyk Date: Thu, 30 Mar 2023 13:40:56 +0200 Subject: [PATCH] #87 Fix link rendering bug. --- .../main/kotlin/org/sdpi/AsciidocConverter.kt | 2 +- .../asciidoc/extension/NumberingProcessor.kt | 50 +++++++++++-------- .../ReferenceSanitizerPostprocessor.kt | 43 ++++++++-------- .../ReferenceSanitizerPreprocessor.kt | 41 +++++++++++++-- .../asciidoc/model/StructuralNodeWrapper.kt | 2 + .../src/main/resources/log4j2.properties | 2 +- .../tf2-ch-a-mdpws-discovery-scopes.adoc | 8 +-- 7 files changed, 97 insertions(+), 51 deletions(-) diff --git a/.ci/asciidoc-converter/src/main/kotlin/org/sdpi/AsciidocConverter.kt b/.ci/asciidoc-converter/src/main/kotlin/org/sdpi/AsciidocConverter.kt index 3e7d1b8..9f5a222 100644 --- a/.ci/asciidoc-converter/src/main/kotlin/org/sdpi/AsciidocConverter.kt +++ b/.ci/asciidoc-converter/src/main/kotlin/org/sdpi/AsciidocConverter.kt @@ -25,7 +25,7 @@ class AsciidocConverter( val asciidoctor = Asciidoctor.Factory.create() - val anchorReplacements = mutableMapOf() + val anchorReplacements = AnchorReplacementsMap() val requirementsBlockProcessor = RequirementsBlockProcessor() asciidoctor.javaExtensionRegistry().block(requirementsBlockProcessor) diff --git a/.ci/asciidoc-converter/src/main/kotlin/org/sdpi/asciidoc/extension/NumberingProcessor.kt b/.ci/asciidoc-converter/src/main/kotlin/org/sdpi/asciidoc/extension/NumberingProcessor.kt index dbcede6..8e7cfe7 100644 --- a/.ci/asciidoc-converter/src/main/kotlin/org/sdpi/asciidoc/extension/NumberingProcessor.kt +++ b/.ci/asciidoc-converter/src/main/kotlin/org/sdpi/asciidoc/extension/NumberingProcessor.kt @@ -31,7 +31,7 @@ fun String.replaceHtmlTags() = this.replace("""<.+?>""".toRegex(), "") */ class NumberingProcessor( private val structureDump: OutputStream? = null, - private val anchorReplacements: MutableMap + private val anchorReplacements: AnchorReplacementsMap ) : Treeprocessor() { private var numbering = mutableListOf() private var currentAdditionalLevel = 0 @@ -100,7 +100,8 @@ class NumberingProcessor( if (level == 0 && !node.wrapped.isAppendix()) { - currentVolumeCaption = Attributes.create(node.wrapped.attributes)[BlockAttribute.VOLUME_CAPTION] ?: "" + currentVolumeCaption = + Attributes.create(node.wrapped.attributes)[BlockAttribute.VOLUME_CAPTION] ?: "" } initSectionNumbers(node.wrapped, level) @@ -112,24 +113,26 @@ class NumberingProcessor( createSectionId(numbering, level).let { currentSection = it - anchorReplacements[node.wrapped.id] = if (isInAppendix()) { - if (node.wrapped.isAppendix()) { - LabelInfo( - (currentAppendix - 1).toString(), - LabelSource.APPENDIX, - currentVolumeCaption, - refText - ) + anchorReplacements.put( + node.wrapped.id, if (isInAppendix()) { + if (node.wrapped.isAppendix()) { + LabelInfo( + (currentAppendix - 1).toString(), + LabelSource.APPENDIX, + currentVolumeCaption, + refText + ) + } else { + LabelInfo(it, LabelSource.APPENDIX, currentVolumeCaption, refText) + } } else { - LabelInfo(it, LabelSource.APPENDIX, currentVolumeCaption, refText) + if (level == 0) { + LabelInfo(it, LabelSource.VOLUME, currentVolumeCaption, refText) + } else { + LabelInfo(it, LabelSource.SECTION, currentVolumeCaption, refText) + } } - } else { - if (level == 0) { - LabelInfo(it, LabelSource.VOLUME, currentVolumeCaption, refText) - } else { - LabelInfo(it, LabelSource.SECTION, currentVolumeCaption, refText) - } - } + ) val volPrefix = if (!node.wrapped.isAppendix()) { volumePrefix(level) @@ -159,6 +162,10 @@ class NumberingProcessor( } } + is StructuralNodeWrapper.Listing -> { + replaceCaption(node.wrapped, "Figure") + } + is StructuralNodeWrapper.Image -> replaceCaption(node.wrapped, "Figure") is StructuralNodeWrapper.Table -> replaceCaption(node.wrapped, "Table") @@ -185,11 +192,10 @@ class NumberingProcessor( it + 1 } } - block.caption = "" - block.title = "$sectionNumber-$objectNumber. ${block.title.replaceHtmlTags()}" + val newTitle = "$sectionNumber-$objectNumber. ${block.title.replaceHtmlTags()}" + block.title = newTitle block.id?.let { - anchorReplacements[block.id] = - LabelInfo("$sectionNumber-$objectNumber", LabelSource.TABLE_OR_FIGURE) + anchorReplacements.put(block.id, LabelInfo("$sectionNumber-$objectNumber", LabelSource.TABLE_OR_FIGURE)) } } } diff --git a/.ci/asciidoc-converter/src/main/kotlin/org/sdpi/asciidoc/extension/ReferenceSanitizerPostprocessor.kt b/.ci/asciidoc-converter/src/main/kotlin/org/sdpi/asciidoc/extension/ReferenceSanitizerPostprocessor.kt index 9d860cc..f05f74e 100644 --- a/.ci/asciidoc-converter/src/main/kotlin/org/sdpi/asciidoc/extension/ReferenceSanitizerPostprocessor.kt +++ b/.ci/asciidoc-converter/src/main/kotlin/org/sdpi/asciidoc/extension/ReferenceSanitizerPostprocessor.kt @@ -7,8 +7,6 @@ import org.jsoup.Jsoup import org.jsoup.nodes.Element import java.net.URI import java.net.URLDecoder -import java.nio.charset.Charset -import java.util.* enum class LabelSource { SECTION, @@ -26,7 +24,7 @@ data class LabelInfo( ) class ReferenceSanitizerPostprocessor( - private val anchorLabels: Map + private val anchorLabels: AnchorReplacementsMap ) : Postprocessor() { override fun process(document: Document, output: String): String { // skip numbering if xref style has been changed to reduce likelihood of broken references @@ -61,37 +59,42 @@ class ReferenceSanitizerPostprocessor( continue } - val fragment = URI.create(href).fragment - if (fragment.isNullOrEmpty()) { + + val parsedFragment = URI.create(href).fragment + if (parsedFragment.isNullOrEmpty()) { continue } - val (id, label) = if (fragment.contains(ReferenceSanitizerPreprocessor.refSeparator)) { - val parts = fragment.split(ReferenceSanitizerPreprocessor.refSeparator) - Pair(parts[0], URLDecoder.decode(parts[1], Charsets.UTF_8).trim()).also { (id, label) -> - logger.info { "Found custom reference: $id => $label"} + val rawFragment = href.substring(1) + val (id, encodedLabel) = if (rawFragment.contains(ReferenceSanitizerPreprocessor.refSeparator)) { + val parts = rawFragment.split(ReferenceSanitizerPreprocessor.refSeparator) + Pair(parts[0], parts[1]).also { (id, label) -> + val decoded = decodeLabel(label) + logger.info { "Found custom reference: $id => $label => $decoded" } } } else { - logger.info { "Found regular reference: $fragment"} - Pair(fragment, null) + logger.info { "Found regular reference: $rawFragment" } + Pair(rawFragment, null) } anchor.attr("href", "#$id") - anchorLabels[id]?.also { - val anchorText = it.refText ?: label - when (it.source) { - LabelSource.SECTION -> anchor.text(anchorText ?: "$sectionSig${it.label}") - LabelSource.TABLE_OR_FIGURE -> anchor.text(anchorText ?: it.label) - LabelSource.APPENDIX -> anchor.text(anchorText ?: "$appendixSig${it.prefix}:${it.label}") - LabelSource.VOLUME -> anchor.text(anchorText ?: "$chapterSig${it.prefix}") - LabelSource.UNKNOWN -> anchor.text(anchorText ?: it.label) - } + val item = encodedLabel?.let { anchorLabels.get(id, it) } ?: anchorLabels.get(id) ?: continue + + val anchorText = (encodedLabel?.let { decodeLabel(it) }) ?: item.refText + when (item.source) { + LabelSource.SECTION -> anchor.text(anchorText ?: "$sectionSig${item.label}") + LabelSource.TABLE_OR_FIGURE -> anchor.text(anchorText ?: item.label) + LabelSource.APPENDIX -> anchor.text(anchorText ?: "$appendixSig${item.prefix}:${item.label}") + LabelSource.VOLUME -> anchor.text(anchorText ?: "$chapterSig${item.prefix}") + LabelSource.UNKNOWN -> anchor.text(anchorText ?: item.label) } } return doc.html() } + private fun decodeLabel(encodedLabel: String) = URLDecoder.decode(encodedLabel, Charsets.UTF_8).trim() + private fun sanitizeSig(sig: String) = when (sig.isEmpty()) { true -> "" false -> "$sig " diff --git a/.ci/asciidoc-converter/src/main/kotlin/org/sdpi/asciidoc/extension/ReferenceSanitizerPreprocessor.kt b/.ci/asciidoc-converter/src/main/kotlin/org/sdpi/asciidoc/extension/ReferenceSanitizerPreprocessor.kt index b2dc8cd..7a32972 100644 --- a/.ci/asciidoc-converter/src/main/kotlin/org/sdpi/asciidoc/extension/ReferenceSanitizerPreprocessor.kt +++ b/.ci/asciidoc-converter/src/main/kotlin/org/sdpi/asciidoc/extension/ReferenceSanitizerPreprocessor.kt @@ -6,9 +6,38 @@ import org.asciidoctor.extension.PreprocessorReader import java.net.URLEncoder import java.util.* +class AnchorReplacementsMap { + private val anchorReplacements: MutableMap> = mutableMapOf() + + fun put(firstLevel: String, secondLevel: String, value: LabelInfo) { + val secondLevelMap = anchorReplacements[firstLevel].let { + if (it == null) { + anchorReplacements[firstLevel] = mutableMapOf() + } + anchorReplacements[firstLevel]!! + } + secondLevelMap[secondLevel] = value + } + + fun put(firstLevel: String, value: LabelInfo) { + put(firstLevel, defaultKey, value) + } + + fun get(firstLevel: String): LabelInfo? { + return get(firstLevel, defaultKey) + } + + fun get(firstLevel: String, secondLevel: String): LabelInfo? { + return anchorReplacements[firstLevel]?.let { it[secondLevel] } + } + + private companion object { + val defaultKey = UUID.randomUUID().toString() + } +} class ReferenceSanitizerPreprocessor( - private val anchorReplacements: MutableMap + private val anchorReplacements: AnchorReplacementsMap ) : Preprocessor() { private val variables = mutableMapOf() @@ -24,8 +53,14 @@ class ReferenceSanitizerPreprocessor( } else { val substitutedVariables = substituteVariables(refs[1].trim()) val encodedRefText = URLEncoder.encode(substitutedVariables, Charsets.UTF_8) - val transformed = "<<${refs[0]}$refSeparator$encodedRefText>>" - anchorReplacements[refs[0]] = LabelInfo(substitutedVariables, LabelSource.UNKNOWN) + val key = "${refs[0]}$refSeparator$encodedRefText" + val transformed = "<<$key>>" + + anchorReplacements.put( + refs[0], + encodedRefText, + LabelInfo(substitutedVariables, LabelSource.UNKNOWN) + ) logger.info { "Found reference with custom label: ${it.groupValues.first()} => $transformed" } transformed } diff --git a/.ci/asciidoc-converter/src/main/kotlin/org/sdpi/asciidoc/model/StructuralNodeWrapper.kt b/.ci/asciidoc-converter/src/main/kotlin/org/sdpi/asciidoc/model/StructuralNodeWrapper.kt index 24f5c61..dc5cc52 100644 --- a/.ci/asciidoc-converter/src/main/kotlin/org/sdpi/asciidoc/model/StructuralNodeWrapper.kt +++ b/.ci/asciidoc-converter/src/main/kotlin/org/sdpi/asciidoc/model/StructuralNodeWrapper.kt @@ -14,6 +14,7 @@ fun StructuralNode.toSealed(): StructuralNodeWrapper { "paragraph" -> StructuralNodeWrapper.Paragraph(this as Block) "image" -> StructuralNodeWrapper.Image(this as Block) "table" -> StructuralNodeWrapper.Table(this as Table) + "listing" -> StructuralNodeWrapper.Listing(this as Block) "sidebar" -> this.attributes.entries.find { it.key == "1" && it.value == BLOCK_NAME_SDPI_REQUIREMENT }?.let { @@ -34,6 +35,7 @@ sealed class StructuralNodeWrapper { data class Paragraph(val wrapped: Block): StructuralNodeWrapper() data class Image(val wrapped: Block): StructuralNodeWrapper() data class Table(val wrapped: org.asciidoctor.ast.Table): StructuralNodeWrapper() + data class Listing(val wrapped: Block): StructuralNodeWrapper() object Unknown : StructuralNodeWrapper() } diff --git a/.ci/asciidoc-converter/src/main/resources/log4j2.properties b/.ci/asciidoc-converter/src/main/resources/log4j2.properties index ecc95bd..283d625 100644 --- a/.ci/asciidoc-converter/src/main/resources/log4j2.properties +++ b/.ci/asciidoc-converter/src/main/resources/log4j2.properties @@ -8,6 +8,6 @@ appender.console.name = LogToConsole appender.console.layout.type = PatternLayout appender.console.layout.pattern = %d{yyyy-MM-dd HH:mm:ss} %-5p - %m%n -rootLogger.level = info +rootLogger.level = trace rootLogger.appenderRefs = stdout rootLogger.appenderRef.stdout.ref = LogToConsole \ No newline at end of file diff --git a/asciidoc/volume2/discovery-scopes/tf2-ch-a-mdpws-discovery-scopes.adoc b/asciidoc/volume2/discovery-scopes/tf2-ch-a-mdpws-discovery-scopes.adoc index 4792316..1977c23 100644 --- a/asciidoc/volume2/discovery-scopes/tf2-ch-a-mdpws-discovery-scopes.adoc +++ b/asciidoc/volume2/discovery-scopes/tf2-ch-a-mdpws-discovery-scopes.adoc @@ -30,7 +30,7 @@ URIs of a <> name and serial number: ==== **** -.<> for the encoding of production specifications +.Extended Backus-Naur Form for the encoding of production specifications [source#vol2_listing_encoding_production_specification] ---- Char ::= unreserved | pct-encoded @@ -54,7 +54,7 @@ ProductionSpecification ::= ProductionSpec ':' SpecType [ ':' ComponentId ] - `pct-encoded` is specified in <>, {var_uri_percent_encoding}[2.1. Percent-Encoding] ==== -.<> for the encoding of MDS production specifications +.Extended Backus-Naur Form for the encoding of MDS production specifications [source#vol2_listing_encoding_production_specification_mds] ---- Scheme ::= 'sdc.mds.prodspec' @@ -83,7 +83,7 @@ URI of a Soft ID named _PatMon 03_: `sdc.mds.attr:PatMon%2003:67886` ==== **** -.<> for the encoding of attributes +.Extended Backus-Naur Form for the encoding of attributes [source#vol2_listing_encoding_attribute] ---- Char ::= unreserved | pct-encoded @@ -103,7 +103,7 @@ Attribute ::= AttributeValue ':' AttributeCode - `pct-encoded` is specified in <>, {var_uri_percent_encoding}[2.1. Percent-Encoding] ==== -.<> for the encoding of MDS attribute specifications +.Extended Backus-Naur Form for the encoding of MDS attribute specifications [source#vol2_listing_encoding_attribute_mds] ---- Scheme ::= 'sdc.mds.attr'