diff --git a/CHANGELOG.md b/CHANGELOG.md index af5c66e6..079172fa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ ## [Unreleased] - Decode character references above U+FFFF, such as `😀` or `𝔄`, to the right character instead of a truncated one, and replace `�`, surrogates and out of range numeric references with U+FFFD as required by CommonMark - Parse an ATX heading followed by `---` or `===` as a heading, not as setext content (IJPL-94630) +- Add `lazyContinuation` parameter to GFM flavor ## [0.7.18] diff --git a/src/commonMain/kotlin/org/intellij/markdown/flavours/gfm/GFMFlavourDescriptor.kt b/src/commonMain/kotlin/org/intellij/markdown/flavours/gfm/GFMFlavourDescriptor.kt index 70ff13e3..0f98e6b2 100644 --- a/src/commonMain/kotlin/org/intellij/markdown/flavours/gfm/GFMFlavourDescriptor.kt +++ b/src/commonMain/kotlin/org/intellij/markdown/flavours/gfm/GFMFlavourDescriptor.kt @@ -33,12 +33,15 @@ import org.intellij.markdown.parser.sequentialparsers.impl.* * otherwise. When enabled, the leading `<` of the disallowed raw HTML tags (`title`, `textarea`, `style`, `xmp`, * `iframe`, `noembed`, `noframes`, `script`, `plaintext`) is replaced with `<`. * See [Disallowed Raw HTML (extension)](https://github.github.com/gfm/#disallowed-raw-html-extension-) + * + * @param lazyContinuation `true` if an unmarked line may continue a paragraph inside a block quote. */ open class GFMFlavourDescriptor( useSafeLinks: Boolean = true, absolutizeAnchorLinks: Boolean = false, private val makeHttpsAutoLinks: Boolean = false, - private val useTagFilter: Boolean = false + private val useTagFilter: Boolean = false, + private val lazyContinuation: Boolean = true, ) : CommonMarkFlavourDescriptor(useSafeLinks, absolutizeAnchorLinks) { /** * For ABI compatibility. @@ -49,7 +52,15 @@ open class GFMFlavourDescriptor( makeHttpsAutoLinks: Boolean = false ) : this(useSafeLinks, absolutizeAnchorLinks, makeHttpsAutoLinks, useTagFilter = false) - override val markerProcessorFactory: MarkerProcessorFactory = GFMMarkerProcessor.Factory + constructor( + useSafeLinks: Boolean = true, + absolutizeAnchorLinks: Boolean = false, + makeHttpsAutoLinks: Boolean = false, + useTagFilter: Boolean = false, + ) : this(useSafeLinks, absolutizeAnchorLinks, makeHttpsAutoLinks, useTagFilter, lazyContinuation = true) + + override val markerProcessorFactory: MarkerProcessorFactory = + GFMMarkerProcessor.Factory.withLazyContinuation(lazyContinuation) override fun createInlinesLexer(): MarkdownLexer { return MarkdownLexer(_GFMLexer()) diff --git a/src/commonMain/kotlin/org/intellij/markdown/flavours/gfm/GFMMarkerProcessor.kt b/src/commonMain/kotlin/org/intellij/markdown/flavours/gfm/GFMMarkerProcessor.kt index 731dad35..e214c1b4 100644 --- a/src/commonMain/kotlin/org/intellij/markdown/flavours/gfm/GFMMarkerProcessor.kt +++ b/src/commonMain/kotlin/org/intellij/markdown/flavours/gfm/GFMMarkerProcessor.kt @@ -12,14 +12,24 @@ import org.intellij.markdown.parser.constraints.CommonMarkdownConstraints import org.intellij.markdown.parser.constraints.MarkdownConstraints import org.intellij.markdown.parser.constraints.getCharsEaten import org.intellij.markdown.parser.markerblocks.MarkerBlockProvider +import org.intellij.markdown.parser.markerblocks.providers.BlockQuoteProvider import org.intellij.markdown.parser.sequentialparsers.SequentialParser import kotlin.math.min -class GFMMarkerProcessor(productionHolder: ProductionHolder, constraintsBase: CommonMarkdownConstraints) +class GFMMarkerProcessor( + productionHolder: ProductionHolder, + constraintsBase: CommonMarkdownConstraints, + private val lazyContinuation: Boolean, +) : CommonMarkMarkerProcessor(productionHolder, constraintsBase) { + constructor(productionHolder: ProductionHolder, constraintsBase: CommonMarkdownConstraints) : + this(productionHolder, constraintsBase, lazyContinuation = true) + private val markerBlockProviders = listOf(GitHubAlertMarkerProvider()) - .plus(super.getMarkerBlockProviders()) + .plus(super.getMarkerBlockProviders().map { + if (it is BlockQuoteProvider) BlockQuoteProvider(lazyContinuation) else it + }) .plus(listOf(GitHubTableMarkerProvider())) override fun getMarkerBlockProviders(): List> { @@ -66,5 +76,15 @@ class GFMMarkerProcessor(productionHolder: ProductionHolder, constraintsBase: Co override fun createMarkerProcessor(productionHolder: ProductionHolder): MarkerProcessor<*> { return GFMMarkerProcessor(productionHolder, GFMConstraints.BASE) } + + internal fun withLazyContinuation(lazyContinuation: Boolean): MarkerProcessorFactory { + return if (lazyContinuation) this else ConfiguredFactory(lazyContinuation) + } + } + + private class ConfiguredFactory(private val lazyContinuation: Boolean) : MarkerProcessorFactory { + override fun createMarkerProcessor(productionHolder: ProductionHolder): MarkerProcessor<*> { + return GFMMarkerProcessor(productionHolder, GFMConstraints.BASE, lazyContinuation) + } } -} \ No newline at end of file +} diff --git a/src/commonTest/kotlin/org/intellij/markdown/NonLazyBlockQuoteFlavours.kt b/src/commonTest/kotlin/org/intellij/markdown/NonLazyBlockQuoteFlavours.kt index 15cfd9a3..8c5d7757 100644 --- a/src/commonTest/kotlin/org/intellij/markdown/NonLazyBlockQuoteFlavours.kt +++ b/src/commonTest/kotlin/org/intellij/markdown/NonLazyBlockQuoteFlavours.kt @@ -2,10 +2,7 @@ package org.intellij.markdown import org.intellij.markdown.flavours.commonmark.CommonMarkFlavourDescriptor import org.intellij.markdown.flavours.commonmark.CommonMarkMarkerProcessor -import org.intellij.markdown.flavours.gfm.GFMConstraints import org.intellij.markdown.flavours.gfm.GFMFlavourDescriptor -import org.intellij.markdown.flavours.gfm.alert.GitHubAlertMarkerProvider -import org.intellij.markdown.flavours.gfm.table.GitHubTableMarkerProvider import org.intellij.markdown.parser.MarkerProcessor import org.intellij.markdown.parser.MarkerProcessorFactory import org.intellij.markdown.parser.ProductionHolder @@ -23,15 +20,19 @@ private class NonLazyBlockQuoteMarkerProcessor( first: List> = emptyList(), last: List> = emptyList() ) : CommonMarkMarkerProcessor(productionHolder, constraintsBase) { - private val markerBlockProviders = first + super.getMarkerBlockProviders().map { - if (it is BlockQuoteProvider) BlockQuoteProvider(lazyContinuation = false) else it - } + last + private val markerBlockProviders = buildList { + addAll(first) + super.getMarkerBlockProviders().mapTo(this) { + if (it is BlockQuoteProvider) BlockQuoteProvider(lazyContinuation = false) else it + } + addAll(last) + } override fun getMarkerBlockProviders(): List> = markerBlockProviders } /** - * The CommonMark flavour that ends a block quote at a line without the `>` marker instead of continuing its paragraph. + * The CommonMark flavor that ends a block quote at a line without the `>` marker instead of continuing its paragraph. */ class NonLazyBlockQuoteCommonMarkFlavour : CommonMarkFlavourDescriptor() { override val markerProcessorFactory: MarkerProcessorFactory = object : MarkerProcessorFactory { @@ -41,19 +42,5 @@ class NonLazyBlockQuoteCommonMarkFlavour : CommonMarkFlavourDescriptor() { } } -/** - * The GFM flavour that ends a block quote at a line without the `>` marker instead of continuing its paragraph. - * Its marker processor has the providers of [org.intellij.markdown.flavours.gfm.GFMMarkerProcessor]. - */ -class NonLazyBlockQuoteGfmFlavour : GFMFlavourDescriptor() { - override val markerProcessorFactory: MarkerProcessorFactory = object : MarkerProcessorFactory { - override fun createMarkerProcessor(productionHolder: ProductionHolder): MarkerProcessor<*> { - return NonLazyBlockQuoteMarkerProcessor( - productionHolder, - GFMConstraints.BASE, - first = listOf(GitHubAlertMarkerProvider()), - last = listOf(GitHubTableMarkerProvider()) - ) - } - } -} +/** The GFM flavor that ends a block quote at a line without the `>` marker. */ +class NonLazyBlockQuoteGfmFlavour : GFMFlavourDescriptor(lazyContinuation = false)