diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 5d1e8aa30..5b013282b 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -3,7 +3,7 @@ commonmark = "0.22.0" composeDesktop = "1.6.10-dev1549" detekt = "1.23.4" dokka = "1.8.20" -idea = "241.14494.17-EAP-SNAPSHOT" +idea = "241.14494.158-EAP-SNAPSHOT" ideaGradlePlugin = "1.17.1" jna = "5.14.0" kotlin = "1.8.21" diff --git a/markdown/core/api/core.api b/markdown/core/api/core.api index 14248ba4f..8d8deded7 100644 --- a/markdown/core/api/core.api +++ b/markdown/core/api/core.api @@ -1,166 +1,277 @@ public abstract interface class org/jetbrains/jewel/markdown/BlockWithInlineMarkdown { - public abstract fun getInlineContent-Ns87O_s ()Ljava/lang/String; + public abstract fun getInlineContent ()Ljava/util/List; } -public final class org/jetbrains/jewel/markdown/InlineMarkdown { - public static final synthetic fun box-impl (Ljava/lang/String;)Lorg/jetbrains/jewel/markdown/InlineMarkdown; - public static fun constructor-impl (Ljava/lang/String;)Ljava/lang/String; +public abstract interface class org/jetbrains/jewel/markdown/InlineMarkdown { + public abstract fun getChildren ()Ljava/util/Iterator; + public abstract fun getValue ()Lorg/commonmark/node/Node; +} + +public final class org/jetbrains/jewel/markdown/InlineMarkdown$Code : org/jetbrains/jewel/markdown/InlineMarkdown { + public static final synthetic fun box-impl (Lorg/commonmark/node/Code;)Lorg/jetbrains/jewel/markdown/InlineMarkdown$Code; + public static fun constructor-impl (Lorg/commonmark/node/Code;)Lorg/commonmark/node/Code; public fun equals (Ljava/lang/Object;)Z - public static fun equals-impl (Ljava/lang/String;Ljava/lang/Object;)Z - public static final fun equals-impl0 (Ljava/lang/String;Ljava/lang/String;)Z - public final fun getContent ()Ljava/lang/String; + public static fun equals-impl (Lorg/commonmark/node/Code;Ljava/lang/Object;)Z + public static final fun equals-impl0 (Lorg/commonmark/node/Code;Lorg/commonmark/node/Code;)Z + public fun getChildren ()Ljava/util/Iterator; + public static fun getChildren-impl (Lorg/commonmark/node/Code;)Ljava/util/Iterator; + public fun getValue ()Lorg/commonmark/node/Code; + public synthetic fun getValue ()Lorg/commonmark/node/Node; public fun hashCode ()I - public static fun hashCode-impl (Ljava/lang/String;)I + public static fun hashCode-impl (Lorg/commonmark/node/Code;)I public fun toString ()Ljava/lang/String; - public static fun toString-impl (Ljava/lang/String;)Ljava/lang/String; - public final synthetic fun unbox-impl ()Ljava/lang/String; + public static fun toString-impl (Lorg/commonmark/node/Code;)Ljava/lang/String; + public final synthetic fun unbox-impl ()Lorg/commonmark/node/Code; } -public abstract interface class org/jetbrains/jewel/markdown/MarkdownBlock { +public final class org/jetbrains/jewel/markdown/InlineMarkdown$CustomNode : org/jetbrains/jewel/markdown/InlineMarkdown { + public static final synthetic fun box-impl (Lorg/commonmark/node/CustomNode;)Lorg/jetbrains/jewel/markdown/InlineMarkdown$CustomNode; + public static fun constructor-impl (Lorg/commonmark/node/CustomNode;)Lorg/commonmark/node/CustomNode; + public fun equals (Ljava/lang/Object;)Z + public static fun equals-impl (Lorg/commonmark/node/CustomNode;Ljava/lang/Object;)Z + public static final fun equals-impl0 (Lorg/commonmark/node/CustomNode;Lorg/commonmark/node/CustomNode;)Z + public fun getChildren ()Ljava/util/Iterator; + public static fun getChildren-impl (Lorg/commonmark/node/CustomNode;)Ljava/util/Iterator; + public fun getValue ()Lorg/commonmark/node/CustomNode; + public synthetic fun getValue ()Lorg/commonmark/node/Node; + public fun hashCode ()I + public static fun hashCode-impl (Lorg/commonmark/node/CustomNode;)I + public fun toString ()Ljava/lang/String; + public static fun toString-impl (Lorg/commonmark/node/CustomNode;)Ljava/lang/String; + public final synthetic fun unbox-impl ()Lorg/commonmark/node/CustomNode; } -public final class org/jetbrains/jewel/markdown/MarkdownBlock$BlockQuote : org/jetbrains/jewel/markdown/MarkdownBlock { - public static final field $stable I - public fun (Ljava/util/List;)V - public final fun component1 ()Ljava/util/List; - public final fun copy (Ljava/util/List;)Lorg/jetbrains/jewel/markdown/MarkdownBlock$BlockQuote; - public static synthetic fun copy$default (Lorg/jetbrains/jewel/markdown/MarkdownBlock$BlockQuote;Ljava/util/List;ILjava/lang/Object;)Lorg/jetbrains/jewel/markdown/MarkdownBlock$BlockQuote; +public final class org/jetbrains/jewel/markdown/InlineMarkdown$DefaultImpls { + public static fun getChildren (Lorg/jetbrains/jewel/markdown/InlineMarkdown;)Ljava/util/Iterator; +} + +public final class org/jetbrains/jewel/markdown/InlineMarkdown$Emphasis : org/jetbrains/jewel/markdown/InlineMarkdown { + public static final synthetic fun box-impl (Lorg/commonmark/node/Emphasis;)Lorg/jetbrains/jewel/markdown/InlineMarkdown$Emphasis; + public static fun constructor-impl (Lorg/commonmark/node/Emphasis;)Lorg/commonmark/node/Emphasis; public fun equals (Ljava/lang/Object;)Z - public final fun getContent ()Ljava/util/List; + public static fun equals-impl (Lorg/commonmark/node/Emphasis;Ljava/lang/Object;)Z + public static final fun equals-impl0 (Lorg/commonmark/node/Emphasis;Lorg/commonmark/node/Emphasis;)Z + public fun getChildren ()Ljava/util/Iterator; + public static fun getChildren-impl (Lorg/commonmark/node/Emphasis;)Ljava/util/Iterator; + public fun getValue ()Lorg/commonmark/node/Emphasis; + public synthetic fun getValue ()Lorg/commonmark/node/Node; public fun hashCode ()I + public static fun hashCode-impl (Lorg/commonmark/node/Emphasis;)I public fun toString ()Ljava/lang/String; + public static fun toString-impl (Lorg/commonmark/node/Emphasis;)Ljava/lang/String; + public final synthetic fun unbox-impl ()Lorg/commonmark/node/Emphasis; } -public abstract interface class org/jetbrains/jewel/markdown/MarkdownBlock$CodeBlock : org/jetbrains/jewel/markdown/MarkdownBlock { - public abstract fun getContent ()Ljava/lang/String; +public final class org/jetbrains/jewel/markdown/InlineMarkdown$HardLineBreak : org/jetbrains/jewel/markdown/InlineMarkdown { + public static final synthetic fun box-impl (Lorg/commonmark/node/HardLineBreak;)Lorg/jetbrains/jewel/markdown/InlineMarkdown$HardLineBreak; + public static fun constructor-impl (Lorg/commonmark/node/HardLineBreak;)Lorg/commonmark/node/HardLineBreak; + public fun equals (Ljava/lang/Object;)Z + public static fun equals-impl (Lorg/commonmark/node/HardLineBreak;Ljava/lang/Object;)Z + public static final fun equals-impl0 (Lorg/commonmark/node/HardLineBreak;Lorg/commonmark/node/HardLineBreak;)Z + public fun getChildren ()Ljava/util/Iterator; + public static fun getChildren-impl (Lorg/commonmark/node/HardLineBreak;)Ljava/util/Iterator; + public fun getValue ()Lorg/commonmark/node/HardLineBreak; + public synthetic fun getValue ()Lorg/commonmark/node/Node; + public fun hashCode ()I + public static fun hashCode-impl (Lorg/commonmark/node/HardLineBreak;)I + public fun toString ()Ljava/lang/String; + public static fun toString-impl (Lorg/commonmark/node/HardLineBreak;)Ljava/lang/String; + public final synthetic fun unbox-impl ()Lorg/commonmark/node/HardLineBreak; } -public final class org/jetbrains/jewel/markdown/MarkdownBlock$CodeBlock$FencedCodeBlock : org/jetbrains/jewel/markdown/MarkdownBlock$CodeBlock { - public static final field $stable I - public synthetic fun (Ljava/lang/String;Ljava/lang/String;Lkotlin/jvm/internal/DefaultConstructorMarker;)V - public final fun component1 ()Ljava/lang/String; - public final fun component2-EIRQHX8 ()Ljava/lang/String; - public final fun copy-k5OzbWQ (Ljava/lang/String;Ljava/lang/String;)Lorg/jetbrains/jewel/markdown/MarkdownBlock$CodeBlock$FencedCodeBlock; - public static synthetic fun copy-k5OzbWQ$default (Lorg/jetbrains/jewel/markdown/MarkdownBlock$CodeBlock$FencedCodeBlock;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Lorg/jetbrains/jewel/markdown/MarkdownBlock$CodeBlock$FencedCodeBlock; +public final class org/jetbrains/jewel/markdown/InlineMarkdown$HtmlInline : org/jetbrains/jewel/markdown/InlineMarkdown { + public static final synthetic fun box-impl (Lorg/commonmark/node/HtmlInline;)Lorg/jetbrains/jewel/markdown/InlineMarkdown$HtmlInline; + public static fun constructor-impl (Lorg/commonmark/node/HtmlInline;)Lorg/commonmark/node/HtmlInline; public fun equals (Ljava/lang/Object;)Z - public fun getContent ()Ljava/lang/String; - public final fun getMimeType-EIRQHX8 ()Ljava/lang/String; + public static fun equals-impl (Lorg/commonmark/node/HtmlInline;Ljava/lang/Object;)Z + public static final fun equals-impl0 (Lorg/commonmark/node/HtmlInline;Lorg/commonmark/node/HtmlInline;)Z + public fun getChildren ()Ljava/util/Iterator; + public static fun getChildren-impl (Lorg/commonmark/node/HtmlInline;)Ljava/util/Iterator; + public fun getValue ()Lorg/commonmark/node/HtmlInline; + public synthetic fun getValue ()Lorg/commonmark/node/Node; public fun hashCode ()I + public static fun hashCode-impl (Lorg/commonmark/node/HtmlInline;)I public fun toString ()Ljava/lang/String; + public static fun toString-impl (Lorg/commonmark/node/HtmlInline;)Ljava/lang/String; + public final synthetic fun unbox-impl ()Lorg/commonmark/node/HtmlInline; } -public final class org/jetbrains/jewel/markdown/MarkdownBlock$CodeBlock$IndentedCodeBlock : org/jetbrains/jewel/markdown/MarkdownBlock$CodeBlock { - public static final field $stable I - public fun (Ljava/lang/String;)V - public final fun component1 ()Ljava/lang/String; - public final fun copy (Ljava/lang/String;)Lorg/jetbrains/jewel/markdown/MarkdownBlock$CodeBlock$IndentedCodeBlock; - public static synthetic fun copy$default (Lorg/jetbrains/jewel/markdown/MarkdownBlock$CodeBlock$IndentedCodeBlock;Ljava/lang/String;ILjava/lang/Object;)Lorg/jetbrains/jewel/markdown/MarkdownBlock$CodeBlock$IndentedCodeBlock; +public final class org/jetbrains/jewel/markdown/InlineMarkdown$Image : org/jetbrains/jewel/markdown/InlineMarkdown { + public static final synthetic fun box-impl (Lorg/commonmark/node/Image;)Lorg/jetbrains/jewel/markdown/InlineMarkdown$Image; + public static fun constructor-impl (Lorg/commonmark/node/Image;)Lorg/commonmark/node/Image; public fun equals (Ljava/lang/Object;)Z - public fun getContent ()Ljava/lang/String; + public static fun equals-impl (Lorg/commonmark/node/Image;Ljava/lang/Object;)Z + public static final fun equals-impl0 (Lorg/commonmark/node/Image;Lorg/commonmark/node/Image;)Z + public fun getChildren ()Ljava/util/Iterator; + public static fun getChildren-impl (Lorg/commonmark/node/Image;)Ljava/util/Iterator; + public fun getValue ()Lorg/commonmark/node/Image; + public synthetic fun getValue ()Lorg/commonmark/node/Node; public fun hashCode ()I + public static fun hashCode-impl (Lorg/commonmark/node/Image;)I public fun toString ()Ljava/lang/String; + public static fun toString-impl (Lorg/commonmark/node/Image;)Ljava/lang/String; + public final synthetic fun unbox-impl ()Lorg/commonmark/node/Image; } -public abstract interface class org/jetbrains/jewel/markdown/MarkdownBlock$Extension : org/jetbrains/jewel/markdown/MarkdownBlock { +public final class org/jetbrains/jewel/markdown/InlineMarkdown$Link : org/jetbrains/jewel/markdown/InlineMarkdown { + public static final synthetic fun box-impl (Lorg/commonmark/node/Link;)Lorg/jetbrains/jewel/markdown/InlineMarkdown$Link; + public static fun constructor-impl (Lorg/commonmark/node/Link;)Lorg/commonmark/node/Link; + public fun equals (Ljava/lang/Object;)Z + public static fun equals-impl (Lorg/commonmark/node/Link;Ljava/lang/Object;)Z + public static final fun equals-impl0 (Lorg/commonmark/node/Link;Lorg/commonmark/node/Link;)Z + public fun getChildren ()Ljava/util/Iterator; + public static fun getChildren-impl (Lorg/commonmark/node/Link;)Ljava/util/Iterator; + public fun getValue ()Lorg/commonmark/node/Link; + public synthetic fun getValue ()Lorg/commonmark/node/Node; + public fun hashCode ()I + public static fun hashCode-impl (Lorg/commonmark/node/Link;)I + public fun toString ()Ljava/lang/String; + public static fun toString-impl (Lorg/commonmark/node/Link;)Ljava/lang/String; + public final synthetic fun unbox-impl ()Lorg/commonmark/node/Link; } -public abstract interface class org/jetbrains/jewel/markdown/MarkdownBlock$Heading : org/jetbrains/jewel/markdown/BlockWithInlineMarkdown, org/jetbrains/jewel/markdown/MarkdownBlock { +public final class org/jetbrains/jewel/markdown/InlineMarkdown$Paragraph : org/jetbrains/jewel/markdown/InlineMarkdown { + public static final synthetic fun box-impl (Lorg/commonmark/node/Paragraph;)Lorg/jetbrains/jewel/markdown/InlineMarkdown$Paragraph; + public static fun constructor-impl (Lorg/commonmark/node/Paragraph;)Lorg/commonmark/node/Paragraph; + public fun equals (Ljava/lang/Object;)Z + public static fun equals-impl (Lorg/commonmark/node/Paragraph;Ljava/lang/Object;)Z + public static final fun equals-impl0 (Lorg/commonmark/node/Paragraph;Lorg/commonmark/node/Paragraph;)Z + public fun getChildren ()Ljava/util/Iterator; + public static fun getChildren-impl (Lorg/commonmark/node/Paragraph;)Ljava/util/Iterator; + public synthetic fun getValue ()Lorg/commonmark/node/Node; + public fun getValue ()Lorg/commonmark/node/Paragraph; + public fun hashCode ()I + public static fun hashCode-impl (Lorg/commonmark/node/Paragraph;)I + public fun toString ()Ljava/lang/String; + public static fun toString-impl (Lorg/commonmark/node/Paragraph;)Ljava/lang/String; + public final synthetic fun unbox-impl ()Lorg/commonmark/node/Paragraph; } -public final class org/jetbrains/jewel/markdown/MarkdownBlock$Heading$H1 : org/jetbrains/jewel/markdown/MarkdownBlock$Heading { - public static final field $stable I - public synthetic fun (Ljava/lang/String;Lkotlin/jvm/internal/DefaultConstructorMarker;)V - public final fun component1-Ns87O_s ()Ljava/lang/String; - public final fun copy-0TBB8uk (Ljava/lang/String;)Lorg/jetbrains/jewel/markdown/MarkdownBlock$Heading$H1; - public static synthetic fun copy-0TBB8uk$default (Lorg/jetbrains/jewel/markdown/MarkdownBlock$Heading$H1;Ljava/lang/String;ILjava/lang/Object;)Lorg/jetbrains/jewel/markdown/MarkdownBlock$Heading$H1; +public final class org/jetbrains/jewel/markdown/InlineMarkdown$SoftLineBreak : org/jetbrains/jewel/markdown/InlineMarkdown { + public static final synthetic fun box-impl (Lorg/commonmark/node/SoftLineBreak;)Lorg/jetbrains/jewel/markdown/InlineMarkdown$SoftLineBreak; + public static fun constructor-impl (Lorg/commonmark/node/SoftLineBreak;)Lorg/commonmark/node/SoftLineBreak; public fun equals (Ljava/lang/Object;)Z - public fun getInlineContent-Ns87O_s ()Ljava/lang/String; + public static fun equals-impl (Lorg/commonmark/node/SoftLineBreak;Ljava/lang/Object;)Z + public static final fun equals-impl0 (Lorg/commonmark/node/SoftLineBreak;Lorg/commonmark/node/SoftLineBreak;)Z + public fun getChildren ()Ljava/util/Iterator; + public static fun getChildren-impl (Lorg/commonmark/node/SoftLineBreak;)Ljava/util/Iterator; + public synthetic fun getValue ()Lorg/commonmark/node/Node; + public fun getValue ()Lorg/commonmark/node/SoftLineBreak; public fun hashCode ()I + public static fun hashCode-impl (Lorg/commonmark/node/SoftLineBreak;)I public fun toString ()Ljava/lang/String; + public static fun toString-impl (Lorg/commonmark/node/SoftLineBreak;)Ljava/lang/String; + public final synthetic fun unbox-impl ()Lorg/commonmark/node/SoftLineBreak; } -public final class org/jetbrains/jewel/markdown/MarkdownBlock$Heading$H2 : org/jetbrains/jewel/markdown/MarkdownBlock$Heading { - public static final field $stable I - public synthetic fun (Ljava/lang/String;Lkotlin/jvm/internal/DefaultConstructorMarker;)V - public final fun component1-Ns87O_s ()Ljava/lang/String; - public final fun copy-0TBB8uk (Ljava/lang/String;)Lorg/jetbrains/jewel/markdown/MarkdownBlock$Heading$H2; - public static synthetic fun copy-0TBB8uk$default (Lorg/jetbrains/jewel/markdown/MarkdownBlock$Heading$H2;Ljava/lang/String;ILjava/lang/Object;)Lorg/jetbrains/jewel/markdown/MarkdownBlock$Heading$H2; +public final class org/jetbrains/jewel/markdown/InlineMarkdown$StrongEmphasis : org/jetbrains/jewel/markdown/InlineMarkdown { + public static final synthetic fun box-impl (Lorg/commonmark/node/StrongEmphasis;)Lorg/jetbrains/jewel/markdown/InlineMarkdown$StrongEmphasis; + public static fun constructor-impl (Lorg/commonmark/node/StrongEmphasis;)Lorg/commonmark/node/StrongEmphasis; public fun equals (Ljava/lang/Object;)Z - public fun getInlineContent-Ns87O_s ()Ljava/lang/String; + public static fun equals-impl (Lorg/commonmark/node/StrongEmphasis;Ljava/lang/Object;)Z + public static final fun equals-impl0 (Lorg/commonmark/node/StrongEmphasis;Lorg/commonmark/node/StrongEmphasis;)Z + public fun getChildren ()Ljava/util/Iterator; + public static fun getChildren-impl (Lorg/commonmark/node/StrongEmphasis;)Ljava/util/Iterator; + public synthetic fun getValue ()Lorg/commonmark/node/Node; + public fun getValue ()Lorg/commonmark/node/StrongEmphasis; public fun hashCode ()I + public static fun hashCode-impl (Lorg/commonmark/node/StrongEmphasis;)I public fun toString ()Ljava/lang/String; + public static fun toString-impl (Lorg/commonmark/node/StrongEmphasis;)Ljava/lang/String; + public final synthetic fun unbox-impl ()Lorg/commonmark/node/StrongEmphasis; } -public final class org/jetbrains/jewel/markdown/MarkdownBlock$Heading$H3 : org/jetbrains/jewel/markdown/MarkdownBlock$Heading { - public static final field $stable I - public synthetic fun (Ljava/lang/String;Lkotlin/jvm/internal/DefaultConstructorMarker;)V - public final fun component1-Ns87O_s ()Ljava/lang/String; - public final fun copy-0TBB8uk (Ljava/lang/String;)Lorg/jetbrains/jewel/markdown/MarkdownBlock$Heading$H3; - public static synthetic fun copy-0TBB8uk$default (Lorg/jetbrains/jewel/markdown/MarkdownBlock$Heading$H3;Ljava/lang/String;ILjava/lang/Object;)Lorg/jetbrains/jewel/markdown/MarkdownBlock$Heading$H3; +public final class org/jetbrains/jewel/markdown/InlineMarkdown$Text : org/jetbrains/jewel/markdown/InlineMarkdown { + public static final synthetic fun box-impl (Lorg/commonmark/node/Text;)Lorg/jetbrains/jewel/markdown/InlineMarkdown$Text; + public static fun constructor-impl (Lorg/commonmark/node/Text;)Lorg/commonmark/node/Text; public fun equals (Ljava/lang/Object;)Z - public fun getInlineContent-Ns87O_s ()Ljava/lang/String; + public static fun equals-impl (Lorg/commonmark/node/Text;Ljava/lang/Object;)Z + public static final fun equals-impl0 (Lorg/commonmark/node/Text;Lorg/commonmark/node/Text;)Z + public fun getChildren ()Ljava/util/Iterator; + public static fun getChildren-impl (Lorg/commonmark/node/Text;)Ljava/util/Iterator; + public synthetic fun getValue ()Lorg/commonmark/node/Node; + public fun getValue ()Lorg/commonmark/node/Text; public fun hashCode ()I + public static fun hashCode-impl (Lorg/commonmark/node/Text;)I public fun toString ()Ljava/lang/String; + public static fun toString-impl (Lorg/commonmark/node/Text;)Ljava/lang/String; + public final synthetic fun unbox-impl ()Lorg/commonmark/node/Text; +} + +public final class org/jetbrains/jewel/markdown/InlineMarkdownKt { + public static final fun toInlineNode (Lorg/commonmark/node/Node;)Lorg/jetbrains/jewel/markdown/InlineMarkdown; +} + +public abstract interface class org/jetbrains/jewel/markdown/MarkdownBlock { } -public final class org/jetbrains/jewel/markdown/MarkdownBlock$Heading$H4 : org/jetbrains/jewel/markdown/MarkdownBlock$Heading { +public final class org/jetbrains/jewel/markdown/MarkdownBlock$BlockQuote : org/jetbrains/jewel/markdown/MarkdownBlock { public static final field $stable I - public synthetic fun (Ljava/lang/String;Lkotlin/jvm/internal/DefaultConstructorMarker;)V - public final fun component1-Ns87O_s ()Ljava/lang/String; - public final fun copy-0TBB8uk (Ljava/lang/String;)Lorg/jetbrains/jewel/markdown/MarkdownBlock$Heading$H4; - public static synthetic fun copy-0TBB8uk$default (Lorg/jetbrains/jewel/markdown/MarkdownBlock$Heading$H4;Ljava/lang/String;ILjava/lang/Object;)Lorg/jetbrains/jewel/markdown/MarkdownBlock$Heading$H4; + public fun (Ljava/util/List;)V + public final fun component1 ()Ljava/util/List; + public final fun copy (Ljava/util/List;)Lorg/jetbrains/jewel/markdown/MarkdownBlock$BlockQuote; + public static synthetic fun copy$default (Lorg/jetbrains/jewel/markdown/MarkdownBlock$BlockQuote;Ljava/util/List;ILjava/lang/Object;)Lorg/jetbrains/jewel/markdown/MarkdownBlock$BlockQuote; public fun equals (Ljava/lang/Object;)Z - public fun getInlineContent-Ns87O_s ()Ljava/lang/String; + public final fun getContent ()Ljava/util/List; public fun hashCode ()I public fun toString ()Ljava/lang/String; } -public final class org/jetbrains/jewel/markdown/MarkdownBlock$Heading$H5 : org/jetbrains/jewel/markdown/MarkdownBlock$Heading { +public abstract interface class org/jetbrains/jewel/markdown/MarkdownBlock$CodeBlock : org/jetbrains/jewel/markdown/MarkdownBlock { + public abstract fun getContent ()Ljava/lang/String; +} + +public final class org/jetbrains/jewel/markdown/MarkdownBlock$CodeBlock$FencedCodeBlock : org/jetbrains/jewel/markdown/MarkdownBlock$CodeBlock { public static final field $stable I - public synthetic fun (Ljava/lang/String;Lkotlin/jvm/internal/DefaultConstructorMarker;)V - public final fun component1-Ns87O_s ()Ljava/lang/String; - public final fun copy-0TBB8uk (Ljava/lang/String;)Lorg/jetbrains/jewel/markdown/MarkdownBlock$Heading$H5; - public static synthetic fun copy-0TBB8uk$default (Lorg/jetbrains/jewel/markdown/MarkdownBlock$Heading$H5;Ljava/lang/String;ILjava/lang/Object;)Lorg/jetbrains/jewel/markdown/MarkdownBlock$Heading$H5; + public synthetic fun (Ljava/lang/String;Ljava/lang/String;Lkotlin/jvm/internal/DefaultConstructorMarker;)V + public final fun component1 ()Ljava/lang/String; + public final fun component2-EIRQHX8 ()Ljava/lang/String; + public final fun copy-k5OzbWQ (Ljava/lang/String;Ljava/lang/String;)Lorg/jetbrains/jewel/markdown/MarkdownBlock$CodeBlock$FencedCodeBlock; + public static synthetic fun copy-k5OzbWQ$default (Lorg/jetbrains/jewel/markdown/MarkdownBlock$CodeBlock$FencedCodeBlock;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Lorg/jetbrains/jewel/markdown/MarkdownBlock$CodeBlock$FencedCodeBlock; public fun equals (Ljava/lang/Object;)Z - public fun getInlineContent-Ns87O_s ()Ljava/lang/String; + public fun getContent ()Ljava/lang/String; + public final fun getMimeType-EIRQHX8 ()Ljava/lang/String; public fun hashCode ()I public fun toString ()Ljava/lang/String; } -public final class org/jetbrains/jewel/markdown/MarkdownBlock$Heading$H6 : org/jetbrains/jewel/markdown/MarkdownBlock$Heading { +public final class org/jetbrains/jewel/markdown/MarkdownBlock$CodeBlock$IndentedCodeBlock : org/jetbrains/jewel/markdown/MarkdownBlock$CodeBlock { public static final field $stable I - public synthetic fun (Ljava/lang/String;Lkotlin/jvm/internal/DefaultConstructorMarker;)V - public final fun component1-Ns87O_s ()Ljava/lang/String; - public final fun copy-0TBB8uk (Ljava/lang/String;)Lorg/jetbrains/jewel/markdown/MarkdownBlock$Heading$H6; - public static synthetic fun copy-0TBB8uk$default (Lorg/jetbrains/jewel/markdown/MarkdownBlock$Heading$H6;Ljava/lang/String;ILjava/lang/Object;)Lorg/jetbrains/jewel/markdown/MarkdownBlock$Heading$H6; + public fun (Ljava/lang/String;)V + public final fun component1 ()Ljava/lang/String; + public final fun copy (Ljava/lang/String;)Lorg/jetbrains/jewel/markdown/MarkdownBlock$CodeBlock$IndentedCodeBlock; + public static synthetic fun copy$default (Lorg/jetbrains/jewel/markdown/MarkdownBlock$CodeBlock$IndentedCodeBlock;Ljava/lang/String;ILjava/lang/Object;)Lorg/jetbrains/jewel/markdown/MarkdownBlock$CodeBlock$IndentedCodeBlock; public fun equals (Ljava/lang/Object;)Z - public fun getInlineContent-Ns87O_s ()Ljava/lang/String; + public fun getContent ()Ljava/lang/String; public fun hashCode ()I public fun toString ()Ljava/lang/String; } -public final class org/jetbrains/jewel/markdown/MarkdownBlock$HtmlBlock : org/jetbrains/jewel/markdown/MarkdownBlock { +public abstract interface class org/jetbrains/jewel/markdown/MarkdownBlock$CustomBlock : org/jetbrains/jewel/markdown/MarkdownBlock { +} + +public final class org/jetbrains/jewel/markdown/MarkdownBlock$Heading : org/jetbrains/jewel/markdown/BlockWithInlineMarkdown, org/jetbrains/jewel/markdown/MarkdownBlock { public static final field $stable I - public fun (Ljava/lang/String;)V - public final fun component1 ()Ljava/lang/String; - public final fun copy (Ljava/lang/String;)Lorg/jetbrains/jewel/markdown/MarkdownBlock$HtmlBlock; - public static synthetic fun copy$default (Lorg/jetbrains/jewel/markdown/MarkdownBlock$HtmlBlock;Ljava/lang/String;ILjava/lang/Object;)Lorg/jetbrains/jewel/markdown/MarkdownBlock$HtmlBlock; + public fun (Ljava/util/List;I)V + public final fun component1 ()Ljava/util/List; + public final fun component2 ()I + public final fun copy (Ljava/util/List;I)Lorg/jetbrains/jewel/markdown/MarkdownBlock$Heading; + public static synthetic fun copy$default (Lorg/jetbrains/jewel/markdown/MarkdownBlock$Heading;Ljava/util/List;IILjava/lang/Object;)Lorg/jetbrains/jewel/markdown/MarkdownBlock$Heading; public fun equals (Ljava/lang/Object;)Z - public final fun getContent ()Ljava/lang/String; + public fun getInlineContent ()Ljava/util/List; + public final fun getLevel ()I public fun hashCode ()I public fun toString ()Ljava/lang/String; } -public final class org/jetbrains/jewel/markdown/MarkdownBlock$Image : org/jetbrains/jewel/markdown/MarkdownBlock { +public final class org/jetbrains/jewel/markdown/MarkdownBlock$HtmlBlock : org/jetbrains/jewel/markdown/MarkdownBlock { public static final field $stable I - public fun (Ljava/lang/String;Ljava/lang/String;)V + public fun (Ljava/lang/String;)V public final fun component1 ()Ljava/lang/String; - public final fun component2 ()Ljava/lang/String; - public final fun copy (Ljava/lang/String;Ljava/lang/String;)Lorg/jetbrains/jewel/markdown/MarkdownBlock$Image; - public static synthetic fun copy$default (Lorg/jetbrains/jewel/markdown/MarkdownBlock$Image;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Lorg/jetbrains/jewel/markdown/MarkdownBlock$Image; + public final fun copy (Ljava/lang/String;)Lorg/jetbrains/jewel/markdown/MarkdownBlock$HtmlBlock; + public static synthetic fun copy$default (Lorg/jetbrains/jewel/markdown/MarkdownBlock$HtmlBlock;Ljava/lang/String;ILjava/lang/Object;)Lorg/jetbrains/jewel/markdown/MarkdownBlock$HtmlBlock; public fun equals (Ljava/lang/Object;)Z - public final fun getAltString ()Ljava/lang/String; - public final fun getUrl ()Ljava/lang/String; + public final fun getContent ()Ljava/lang/String; public fun hashCode ()I public fun toString ()Ljava/lang/String; } @@ -170,35 +281,35 @@ public abstract interface class org/jetbrains/jewel/markdown/MarkdownBlock$ListB public abstract fun isTight ()Z } -public final class org/jetbrains/jewel/markdown/MarkdownBlock$ListBlock$OrderedList : org/jetbrains/jewel/markdown/MarkdownBlock$ListBlock { +public final class org/jetbrains/jewel/markdown/MarkdownBlock$ListBlock$BulletList : org/jetbrains/jewel/markdown/MarkdownBlock$ListBlock { public static final field $stable I - public fun (Ljava/util/List;ZIC)V + public fun (Ljava/util/List;ZLjava/lang/String;)V public final fun component1 ()Ljava/util/List; public final fun component2 ()Z - public final fun component3 ()I - public final fun component4 ()C - public final fun copy (Ljava/util/List;ZIC)Lorg/jetbrains/jewel/markdown/MarkdownBlock$ListBlock$OrderedList; - public static synthetic fun copy$default (Lorg/jetbrains/jewel/markdown/MarkdownBlock$ListBlock$OrderedList;Ljava/util/List;ZICILjava/lang/Object;)Lorg/jetbrains/jewel/markdown/MarkdownBlock$ListBlock$OrderedList; + public final fun component3 ()Ljava/lang/String; + public final fun copy (Ljava/util/List;ZLjava/lang/String;)Lorg/jetbrains/jewel/markdown/MarkdownBlock$ListBlock$BulletList; + public static synthetic fun copy$default (Lorg/jetbrains/jewel/markdown/MarkdownBlock$ListBlock$BulletList;Ljava/util/List;ZLjava/lang/String;ILjava/lang/Object;)Lorg/jetbrains/jewel/markdown/MarkdownBlock$ListBlock$BulletList; public fun equals (Ljava/lang/Object;)Z - public final fun getDelimiter ()C + public final fun getBulletMarker ()Ljava/lang/String; public fun getItems ()Ljava/util/List; - public final fun getStartFrom ()I public fun hashCode ()I public fun isTight ()Z public fun toString ()Ljava/lang/String; } -public final class org/jetbrains/jewel/markdown/MarkdownBlock$ListBlock$UnorderedList : org/jetbrains/jewel/markdown/MarkdownBlock$ListBlock { +public final class org/jetbrains/jewel/markdown/MarkdownBlock$ListBlock$OrderedList : org/jetbrains/jewel/markdown/MarkdownBlock$ListBlock { public static final field $stable I - public fun (Ljava/util/List;ZC)V + public fun (Ljava/util/List;ZILjava/lang/String;)V public final fun component1 ()Ljava/util/List; public final fun component2 ()Z - public final fun component3 ()C - public final fun copy (Ljava/util/List;ZC)Lorg/jetbrains/jewel/markdown/MarkdownBlock$ListBlock$UnorderedList; - public static synthetic fun copy$default (Lorg/jetbrains/jewel/markdown/MarkdownBlock$ListBlock$UnorderedList;Ljava/util/List;ZCILjava/lang/Object;)Lorg/jetbrains/jewel/markdown/MarkdownBlock$ListBlock$UnorderedList; + public final fun component3 ()I + public final fun component4 ()Ljava/lang/String; + public final fun copy (Ljava/util/List;ZILjava/lang/String;)Lorg/jetbrains/jewel/markdown/MarkdownBlock$ListBlock$OrderedList; + public static synthetic fun copy$default (Lorg/jetbrains/jewel/markdown/MarkdownBlock$ListBlock$OrderedList;Ljava/util/List;ZILjava/lang/String;ILjava/lang/Object;)Lorg/jetbrains/jewel/markdown/MarkdownBlock$ListBlock$OrderedList; public fun equals (Ljava/lang/Object;)Z - public final fun getBulletMarker ()C + public final fun getDelimiter ()Ljava/lang/String; public fun getItems ()Ljava/util/List; + public final fun getStartFrom ()I public fun hashCode ()I public fun isTight ()Z public fun toString ()Ljava/lang/String; @@ -218,12 +329,12 @@ public final class org/jetbrains/jewel/markdown/MarkdownBlock$ListItem : org/jet public final class org/jetbrains/jewel/markdown/MarkdownBlock$Paragraph : org/jetbrains/jewel/markdown/BlockWithInlineMarkdown, org/jetbrains/jewel/markdown/MarkdownBlock { public static final field $stable I - public synthetic fun (Ljava/lang/String;Lkotlin/jvm/internal/DefaultConstructorMarker;)V - public final fun component1-Ns87O_s ()Ljava/lang/String; - public final fun copy-0TBB8uk (Ljava/lang/String;)Lorg/jetbrains/jewel/markdown/MarkdownBlock$Paragraph; - public static synthetic fun copy-0TBB8uk$default (Lorg/jetbrains/jewel/markdown/MarkdownBlock$Paragraph;Ljava/lang/String;ILjava/lang/Object;)Lorg/jetbrains/jewel/markdown/MarkdownBlock$Paragraph; + public fun (Ljava/util/List;)V + public final fun component1 ()Ljava/util/List; + public final fun copy (Ljava/util/List;)Lorg/jetbrains/jewel/markdown/MarkdownBlock$Paragraph; + public static synthetic fun copy$default (Lorg/jetbrains/jewel/markdown/MarkdownBlock$Paragraph;Ljava/util/List;ILjava/lang/Object;)Lorg/jetbrains/jewel/markdown/MarkdownBlock$Paragraph; public fun equals (Ljava/lang/Object;)Z - public fun getInlineContent-Ns87O_s ()Ljava/lang/String; + public fun getInlineContent ()Ljava/util/List; public fun hashCode ()I public fun toString ()Ljava/lang/String; } @@ -304,12 +415,12 @@ public final class org/jetbrains/jewel/markdown/MimeTypeKt { public abstract interface class org/jetbrains/jewel/markdown/extensions/MarkdownBlockProcessorExtension { public abstract fun canProcess (Lorg/commonmark/node/CustomBlock;)Z - public abstract fun processMarkdownBlock (Lorg/commonmark/node/CustomBlock;Lorg/jetbrains/jewel/markdown/processing/MarkdownProcessor;)Lorg/jetbrains/jewel/markdown/MarkdownBlock$Extension; + public abstract fun processMarkdownBlock (Lorg/commonmark/node/CustomBlock;Lorg/jetbrains/jewel/markdown/processing/MarkdownProcessor;)Lorg/jetbrains/jewel/markdown/MarkdownBlock$CustomBlock; } public abstract interface class org/jetbrains/jewel/markdown/extensions/MarkdownBlockRendererExtension { - public abstract fun canRender (Lorg/jetbrains/jewel/markdown/MarkdownBlock$Extension;)Z - public abstract fun render (Lorg/jetbrains/jewel/markdown/MarkdownBlock$Extension;Lorg/jetbrains/jewel/markdown/rendering/MarkdownBlockRenderer;Lorg/jetbrains/jewel/markdown/rendering/InlineMarkdownRenderer;Landroidx/compose/runtime/Composer;I)V + public abstract fun canRender (Lorg/jetbrains/jewel/markdown/MarkdownBlock$CustomBlock;)Z + public abstract fun render (Lorg/jetbrains/jewel/markdown/MarkdownBlock$CustomBlock;Lorg/jetbrains/jewel/markdown/rendering/MarkdownBlockRenderer;Lorg/jetbrains/jewel/markdown/rendering/InlineMarkdownRenderer;Landroidx/compose/runtime/Composer;I)V } public abstract interface class org/jetbrains/jewel/markdown/extensions/MarkdownProcessorExtension { @@ -325,8 +436,8 @@ public abstract interface class org/jetbrains/jewel/markdown/extensions/Markdown public final class org/jetbrains/jewel/markdown/processing/MarkdownProcessor { public static final field $stable I public fun ()V - public fun (Ljava/util/List;)V - public synthetic fun (Ljava/util/List;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public fun (Ljava/util/List;Z)V + public synthetic fun (Ljava/util/List;ZILkotlin/jvm/internal/DefaultConstructorMarker;)V public fun ([Lorg/jetbrains/jewel/markdown/extensions/MarkdownProcessorExtension;)V public final fun processChildren (Lorg/commonmark/node/Node;)Ljava/util/List; public final fun processMarkdownDocument (Ljava/lang/String;)Ljava/util/List; @@ -337,7 +448,7 @@ public class org/jetbrains/jewel/markdown/rendering/DefaultInlineMarkdownRendere public static final field Companion Lorg/jetbrains/jewel/markdown/rendering/DefaultInlineMarkdownRenderer$Companion; public fun (Ljava/util/List;)V public fun ([Lorg/jetbrains/jewel/markdown/extensions/MarkdownProcessorExtension;)V - public fun renderAsAnnotatedString-44Ri3s0 (Ljava/lang/String;Lorg/jetbrains/jewel/markdown/rendering/InlinesStyling;)Landroidx/compose/ui/text/AnnotatedString; + public fun renderAsAnnotatedString (Ljava/util/List;Lorg/jetbrains/jewel/markdown/rendering/InlinesStyling;)Landroidx/compose/ui/text/AnnotatedString; } public final class org/jetbrains/jewel/markdown/rendering/DefaultInlineMarkdownRenderer$Companion { @@ -351,17 +462,11 @@ public class org/jetbrains/jewel/markdown/rendering/DefaultMarkdownBlockRenderer public fun render (Lorg/jetbrains/jewel/markdown/MarkdownBlock$CodeBlock$FencedCodeBlock;Lorg/jetbrains/jewel/markdown/rendering/MarkdownStyling$Code$Fenced;Landroidx/compose/runtime/Composer;I)V public fun render (Lorg/jetbrains/jewel/markdown/MarkdownBlock$CodeBlock$IndentedCodeBlock;Lorg/jetbrains/jewel/markdown/rendering/MarkdownStyling$Code$Indented;Landroidx/compose/runtime/Composer;I)V public fun render (Lorg/jetbrains/jewel/markdown/MarkdownBlock$CodeBlock;Lorg/jetbrains/jewel/markdown/rendering/MarkdownStyling$Code;Landroidx/compose/runtime/Composer;I)V - public fun render (Lorg/jetbrains/jewel/markdown/MarkdownBlock$Heading$H1;Lorg/jetbrains/jewel/markdown/rendering/MarkdownStyling$Heading$H1;Landroidx/compose/runtime/Composer;I)V - public fun render (Lorg/jetbrains/jewel/markdown/MarkdownBlock$Heading$H2;Lorg/jetbrains/jewel/markdown/rendering/MarkdownStyling$Heading$H2;Landroidx/compose/runtime/Composer;I)V - public fun render (Lorg/jetbrains/jewel/markdown/MarkdownBlock$Heading$H3;Lorg/jetbrains/jewel/markdown/rendering/MarkdownStyling$Heading$H3;Landroidx/compose/runtime/Composer;I)V - public fun render (Lorg/jetbrains/jewel/markdown/MarkdownBlock$Heading$H4;Lorg/jetbrains/jewel/markdown/rendering/MarkdownStyling$Heading$H4;Landroidx/compose/runtime/Composer;I)V - public fun render (Lorg/jetbrains/jewel/markdown/MarkdownBlock$Heading$H5;Lorg/jetbrains/jewel/markdown/rendering/MarkdownStyling$Heading$H5;Landroidx/compose/runtime/Composer;I)V - public fun render (Lorg/jetbrains/jewel/markdown/MarkdownBlock$Heading$H6;Lorg/jetbrains/jewel/markdown/rendering/MarkdownStyling$Heading$H6;Landroidx/compose/runtime/Composer;I)V + public fun render (Lorg/jetbrains/jewel/markdown/MarkdownBlock$Heading;Lorg/jetbrains/jewel/markdown/rendering/MarkdownStyling$Heading$HN;Landroidx/compose/runtime/Composer;I)V public fun render (Lorg/jetbrains/jewel/markdown/MarkdownBlock$Heading;Lorg/jetbrains/jewel/markdown/rendering/MarkdownStyling$Heading;Landroidx/compose/runtime/Composer;I)V public fun render (Lorg/jetbrains/jewel/markdown/MarkdownBlock$HtmlBlock;Lorg/jetbrains/jewel/markdown/rendering/MarkdownStyling$HtmlBlock;Landroidx/compose/runtime/Composer;I)V - public fun render (Lorg/jetbrains/jewel/markdown/MarkdownBlock$Image;Lorg/jetbrains/jewel/markdown/rendering/MarkdownStyling$Image;Landroidx/compose/runtime/Composer;I)V + public fun render (Lorg/jetbrains/jewel/markdown/MarkdownBlock$ListBlock$BulletList;Lorg/jetbrains/jewel/markdown/rendering/MarkdownStyling$List$Unordered;Landroidx/compose/runtime/Composer;I)V public fun render (Lorg/jetbrains/jewel/markdown/MarkdownBlock$ListBlock$OrderedList;Lorg/jetbrains/jewel/markdown/rendering/MarkdownStyling$List$Ordered;Landroidx/compose/runtime/Composer;I)V - public fun render (Lorg/jetbrains/jewel/markdown/MarkdownBlock$ListBlock$UnorderedList;Lorg/jetbrains/jewel/markdown/rendering/MarkdownStyling$List$Unordered;Landroidx/compose/runtime/Composer;I)V public fun render (Lorg/jetbrains/jewel/markdown/MarkdownBlock$ListBlock;Lorg/jetbrains/jewel/markdown/rendering/MarkdownStyling$List;Landroidx/compose/runtime/Composer;I)V public fun render (Lorg/jetbrains/jewel/markdown/MarkdownBlock$ListItem;Landroidx/compose/runtime/Composer;I)V public fun render (Lorg/jetbrains/jewel/markdown/MarkdownBlock$Paragraph;Lorg/jetbrains/jewel/markdown/rendering/MarkdownStyling$Paragraph;Landroidx/compose/runtime/Composer;I)V @@ -371,7 +476,7 @@ public class org/jetbrains/jewel/markdown/rendering/DefaultMarkdownBlockRenderer public abstract interface class org/jetbrains/jewel/markdown/rendering/InlineMarkdownRenderer { public static final field Companion Lorg/jetbrains/jewel/markdown/rendering/InlineMarkdownRenderer$Companion; - public abstract fun renderAsAnnotatedString-44Ri3s0 (Ljava/lang/String;Lorg/jetbrains/jewel/markdown/rendering/InlinesStyling;)Landroidx/compose/ui/text/AnnotatedString; + public abstract fun renderAsAnnotatedString (Ljava/util/List;Lorg/jetbrains/jewel/markdown/rendering/InlinesStyling;)Landroidx/compose/ui/text/AnnotatedString; } public final class org/jetbrains/jewel/markdown/rendering/InlineMarkdownRenderer$Companion { @@ -405,17 +510,11 @@ public abstract interface class org/jetbrains/jewel/markdown/rendering/MarkdownB public abstract fun render (Lorg/jetbrains/jewel/markdown/MarkdownBlock$CodeBlock$FencedCodeBlock;Lorg/jetbrains/jewel/markdown/rendering/MarkdownStyling$Code$Fenced;Landroidx/compose/runtime/Composer;I)V public abstract fun render (Lorg/jetbrains/jewel/markdown/MarkdownBlock$CodeBlock$IndentedCodeBlock;Lorg/jetbrains/jewel/markdown/rendering/MarkdownStyling$Code$Indented;Landroidx/compose/runtime/Composer;I)V public abstract fun render (Lorg/jetbrains/jewel/markdown/MarkdownBlock$CodeBlock;Lorg/jetbrains/jewel/markdown/rendering/MarkdownStyling$Code;Landroidx/compose/runtime/Composer;I)V - public abstract fun render (Lorg/jetbrains/jewel/markdown/MarkdownBlock$Heading$H1;Lorg/jetbrains/jewel/markdown/rendering/MarkdownStyling$Heading$H1;Landroidx/compose/runtime/Composer;I)V - public abstract fun render (Lorg/jetbrains/jewel/markdown/MarkdownBlock$Heading$H2;Lorg/jetbrains/jewel/markdown/rendering/MarkdownStyling$Heading$H2;Landroidx/compose/runtime/Composer;I)V - public abstract fun render (Lorg/jetbrains/jewel/markdown/MarkdownBlock$Heading$H3;Lorg/jetbrains/jewel/markdown/rendering/MarkdownStyling$Heading$H3;Landroidx/compose/runtime/Composer;I)V - public abstract fun render (Lorg/jetbrains/jewel/markdown/MarkdownBlock$Heading$H4;Lorg/jetbrains/jewel/markdown/rendering/MarkdownStyling$Heading$H4;Landroidx/compose/runtime/Composer;I)V - public abstract fun render (Lorg/jetbrains/jewel/markdown/MarkdownBlock$Heading$H5;Lorg/jetbrains/jewel/markdown/rendering/MarkdownStyling$Heading$H5;Landroidx/compose/runtime/Composer;I)V - public abstract fun render (Lorg/jetbrains/jewel/markdown/MarkdownBlock$Heading$H6;Lorg/jetbrains/jewel/markdown/rendering/MarkdownStyling$Heading$H6;Landroidx/compose/runtime/Composer;I)V + public abstract fun render (Lorg/jetbrains/jewel/markdown/MarkdownBlock$Heading;Lorg/jetbrains/jewel/markdown/rendering/MarkdownStyling$Heading$HN;Landroidx/compose/runtime/Composer;I)V public abstract fun render (Lorg/jetbrains/jewel/markdown/MarkdownBlock$Heading;Lorg/jetbrains/jewel/markdown/rendering/MarkdownStyling$Heading;Landroidx/compose/runtime/Composer;I)V public abstract fun render (Lorg/jetbrains/jewel/markdown/MarkdownBlock$HtmlBlock;Lorg/jetbrains/jewel/markdown/rendering/MarkdownStyling$HtmlBlock;Landroidx/compose/runtime/Composer;I)V - public abstract fun render (Lorg/jetbrains/jewel/markdown/MarkdownBlock$Image;Lorg/jetbrains/jewel/markdown/rendering/MarkdownStyling$Image;Landroidx/compose/runtime/Composer;I)V + public abstract fun render (Lorg/jetbrains/jewel/markdown/MarkdownBlock$ListBlock$BulletList;Lorg/jetbrains/jewel/markdown/rendering/MarkdownStyling$List$Unordered;Landroidx/compose/runtime/Composer;I)V public abstract fun render (Lorg/jetbrains/jewel/markdown/MarkdownBlock$ListBlock$OrderedList;Lorg/jetbrains/jewel/markdown/rendering/MarkdownStyling$List$Ordered;Landroidx/compose/runtime/Composer;I)V - public abstract fun render (Lorg/jetbrains/jewel/markdown/MarkdownBlock$ListBlock$UnorderedList;Lorg/jetbrains/jewel/markdown/rendering/MarkdownStyling$List$Unordered;Landroidx/compose/runtime/Composer;I)V public abstract fun render (Lorg/jetbrains/jewel/markdown/MarkdownBlock$ListBlock;Lorg/jetbrains/jewel/markdown/rendering/MarkdownStyling$List;Landroidx/compose/runtime/Composer;I)V public abstract fun render (Lorg/jetbrains/jewel/markdown/MarkdownBlock$ListItem;Landroidx/compose/runtime/Composer;I)V public abstract fun render (Lorg/jetbrains/jewel/markdown/MarkdownBlock$Paragraph;Lorg/jetbrains/jewel/markdown/rendering/MarkdownStyling$Paragraph;Landroidx/compose/runtime/Composer;I)V @@ -552,13 +651,13 @@ public final class org/jetbrains/jewel/markdown/rendering/MarkdownStyling$Headin public final class org/jetbrains/jewel/markdown/rendering/MarkdownStyling$Heading$Companion { } -public final class org/jetbrains/jewel/markdown/rendering/MarkdownStyling$Heading$H1 : org/jetbrains/jewel/markdown/rendering/WithInlinesStyling, org/jetbrains/jewel/markdown/rendering/WithUnderline { +public final class org/jetbrains/jewel/markdown/rendering/MarkdownStyling$Heading$H1 : org/jetbrains/jewel/markdown/rendering/MarkdownStyling$Heading$HN { public static final field $stable I public static final field Companion Lorg/jetbrains/jewel/markdown/rendering/MarkdownStyling$Heading$H1$Companion; public synthetic fun (Lorg/jetbrains/jewel/markdown/rendering/InlinesStyling;FJFLandroidx/compose/foundation/layout/PaddingValues;Lkotlin/jvm/internal/DefaultConstructorMarker;)V public fun equals (Ljava/lang/Object;)Z public fun getInlinesStyling ()Lorg/jetbrains/jewel/markdown/rendering/InlinesStyling; - public final fun getPadding ()Landroidx/compose/foundation/layout/PaddingValues; + public fun getPadding ()Landroidx/compose/foundation/layout/PaddingValues; public fun getUnderlineColor-0d7_KjU ()J public fun getUnderlineGap-D9Ej5fM ()F public fun getUnderlineWidth-D9Ej5fM ()F @@ -569,13 +668,13 @@ public final class org/jetbrains/jewel/markdown/rendering/MarkdownStyling$Headin public final class org/jetbrains/jewel/markdown/rendering/MarkdownStyling$Heading$H1$Companion { } -public final class org/jetbrains/jewel/markdown/rendering/MarkdownStyling$Heading$H2 : org/jetbrains/jewel/markdown/rendering/WithInlinesStyling, org/jetbrains/jewel/markdown/rendering/WithUnderline { +public final class org/jetbrains/jewel/markdown/rendering/MarkdownStyling$Heading$H2 : org/jetbrains/jewel/markdown/rendering/MarkdownStyling$Heading$HN { public static final field $stable I public static final field Companion Lorg/jetbrains/jewel/markdown/rendering/MarkdownStyling$Heading$H2$Companion; public synthetic fun (Lorg/jetbrains/jewel/markdown/rendering/InlinesStyling;FJFLandroidx/compose/foundation/layout/PaddingValues;Lkotlin/jvm/internal/DefaultConstructorMarker;)V public fun equals (Ljava/lang/Object;)Z public fun getInlinesStyling ()Lorg/jetbrains/jewel/markdown/rendering/InlinesStyling; - public final fun getPadding ()Landroidx/compose/foundation/layout/PaddingValues; + public fun getPadding ()Landroidx/compose/foundation/layout/PaddingValues; public fun getUnderlineColor-0d7_KjU ()J public fun getUnderlineGap-D9Ej5fM ()F public fun getUnderlineWidth-D9Ej5fM ()F @@ -586,13 +685,13 @@ public final class org/jetbrains/jewel/markdown/rendering/MarkdownStyling$Headin public final class org/jetbrains/jewel/markdown/rendering/MarkdownStyling$Heading$H2$Companion { } -public final class org/jetbrains/jewel/markdown/rendering/MarkdownStyling$Heading$H3 : org/jetbrains/jewel/markdown/rendering/WithInlinesStyling, org/jetbrains/jewel/markdown/rendering/WithUnderline { +public final class org/jetbrains/jewel/markdown/rendering/MarkdownStyling$Heading$H3 : org/jetbrains/jewel/markdown/rendering/MarkdownStyling$Heading$HN { public static final field $stable I public static final field Companion Lorg/jetbrains/jewel/markdown/rendering/MarkdownStyling$Heading$H3$Companion; public synthetic fun (Lorg/jetbrains/jewel/markdown/rendering/InlinesStyling;FJFLandroidx/compose/foundation/layout/PaddingValues;Lkotlin/jvm/internal/DefaultConstructorMarker;)V public fun equals (Ljava/lang/Object;)Z public fun getInlinesStyling ()Lorg/jetbrains/jewel/markdown/rendering/InlinesStyling; - public final fun getPadding ()Landroidx/compose/foundation/layout/PaddingValues; + public fun getPadding ()Landroidx/compose/foundation/layout/PaddingValues; public fun getUnderlineColor-0d7_KjU ()J public fun getUnderlineGap-D9Ej5fM ()F public fun getUnderlineWidth-D9Ej5fM ()F @@ -603,13 +702,13 @@ public final class org/jetbrains/jewel/markdown/rendering/MarkdownStyling$Headin public final class org/jetbrains/jewel/markdown/rendering/MarkdownStyling$Heading$H3$Companion { } -public final class org/jetbrains/jewel/markdown/rendering/MarkdownStyling$Heading$H4 : org/jetbrains/jewel/markdown/rendering/WithInlinesStyling, org/jetbrains/jewel/markdown/rendering/WithUnderline { +public final class org/jetbrains/jewel/markdown/rendering/MarkdownStyling$Heading$H4 : org/jetbrains/jewel/markdown/rendering/MarkdownStyling$Heading$HN { public static final field $stable I public static final field Companion Lorg/jetbrains/jewel/markdown/rendering/MarkdownStyling$Heading$H4$Companion; public synthetic fun (Lorg/jetbrains/jewel/markdown/rendering/InlinesStyling;FJFLandroidx/compose/foundation/layout/PaddingValues;Lkotlin/jvm/internal/DefaultConstructorMarker;)V public fun equals (Ljava/lang/Object;)Z public fun getInlinesStyling ()Lorg/jetbrains/jewel/markdown/rendering/InlinesStyling; - public final fun getPadding ()Landroidx/compose/foundation/layout/PaddingValues; + public fun getPadding ()Landroidx/compose/foundation/layout/PaddingValues; public fun getUnderlineColor-0d7_KjU ()J public fun getUnderlineGap-D9Ej5fM ()F public fun getUnderlineWidth-D9Ej5fM ()F @@ -620,13 +719,13 @@ public final class org/jetbrains/jewel/markdown/rendering/MarkdownStyling$Headin public final class org/jetbrains/jewel/markdown/rendering/MarkdownStyling$Heading$H4$Companion { } -public final class org/jetbrains/jewel/markdown/rendering/MarkdownStyling$Heading$H5 : org/jetbrains/jewel/markdown/rendering/WithInlinesStyling, org/jetbrains/jewel/markdown/rendering/WithUnderline { +public final class org/jetbrains/jewel/markdown/rendering/MarkdownStyling$Heading$H5 : org/jetbrains/jewel/markdown/rendering/MarkdownStyling$Heading$HN { public static final field $stable I public static final field Companion Lorg/jetbrains/jewel/markdown/rendering/MarkdownStyling$Heading$H5$Companion; public synthetic fun (Lorg/jetbrains/jewel/markdown/rendering/InlinesStyling;FJFLandroidx/compose/foundation/layout/PaddingValues;Lkotlin/jvm/internal/DefaultConstructorMarker;)V public fun equals (Ljava/lang/Object;)Z public fun getInlinesStyling ()Lorg/jetbrains/jewel/markdown/rendering/InlinesStyling; - public final fun getPadding ()Landroidx/compose/foundation/layout/PaddingValues; + public fun getPadding ()Landroidx/compose/foundation/layout/PaddingValues; public fun getUnderlineColor-0d7_KjU ()J public fun getUnderlineGap-D9Ej5fM ()F public fun getUnderlineWidth-D9Ej5fM ()F @@ -637,13 +736,13 @@ public final class org/jetbrains/jewel/markdown/rendering/MarkdownStyling$Headin public final class org/jetbrains/jewel/markdown/rendering/MarkdownStyling$Heading$H5$Companion { } -public final class org/jetbrains/jewel/markdown/rendering/MarkdownStyling$Heading$H6 : org/jetbrains/jewel/markdown/rendering/WithInlinesStyling, org/jetbrains/jewel/markdown/rendering/WithUnderline { +public final class org/jetbrains/jewel/markdown/rendering/MarkdownStyling$Heading$H6 : org/jetbrains/jewel/markdown/rendering/MarkdownStyling$Heading$HN { public static final field $stable I public static final field Companion Lorg/jetbrains/jewel/markdown/rendering/MarkdownStyling$Heading$H6$Companion; public synthetic fun (Lorg/jetbrains/jewel/markdown/rendering/InlinesStyling;FJFLandroidx/compose/foundation/layout/PaddingValues;Lkotlin/jvm/internal/DefaultConstructorMarker;)V public fun equals (Ljava/lang/Object;)Z public fun getInlinesStyling ()Lorg/jetbrains/jewel/markdown/rendering/InlinesStyling; - public final fun getPadding ()Landroidx/compose/foundation/layout/PaddingValues; + public fun getPadding ()Landroidx/compose/foundation/layout/PaddingValues; public fun getUnderlineColor-0d7_KjU ()J public fun getUnderlineGap-D9Ej5fM ()F public fun getUnderlineWidth-D9Ej5fM ()F @@ -654,6 +753,10 @@ public final class org/jetbrains/jewel/markdown/rendering/MarkdownStyling$Headin public final class org/jetbrains/jewel/markdown/rendering/MarkdownStyling$Heading$H6$Companion { } +public abstract interface class org/jetbrains/jewel/markdown/rendering/MarkdownStyling$Heading$HN : org/jetbrains/jewel/markdown/rendering/WithInlinesStyling, org/jetbrains/jewel/markdown/rendering/WithUnderline { + public abstract fun getPadding ()Landroidx/compose/foundation/layout/PaddingValues; +} + public final class org/jetbrains/jewel/markdown/rendering/MarkdownStyling$HtmlBlock { public static final field $stable I public static final field Companion Lorg/jetbrains/jewel/markdown/rendering/MarkdownStyling$HtmlBlock$Companion; diff --git a/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/InlineMarkdown.kt b/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/InlineMarkdown.kt new file mode 100644 index 000000000..198a88177 --- /dev/null +++ b/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/InlineMarkdown.kt @@ -0,0 +1,96 @@ +package org.jetbrains.jewel.markdown + +import org.commonmark.node.Node +import org.jetbrains.jewel.markdown.InlineMarkdown.Code +import org.jetbrains.jewel.markdown.InlineMarkdown.CustomNode +import org.jetbrains.jewel.markdown.InlineMarkdown.Emphasis +import org.jetbrains.jewel.markdown.InlineMarkdown.HardLineBreak +import org.jetbrains.jewel.markdown.InlineMarkdown.HtmlInline +import org.jetbrains.jewel.markdown.InlineMarkdown.Image +import org.jetbrains.jewel.markdown.InlineMarkdown.Link +import org.jetbrains.jewel.markdown.InlineMarkdown.SoftLineBreak +import org.jetbrains.jewel.markdown.InlineMarkdown.StrongEmphasis +import org.jetbrains.jewel.markdown.InlineMarkdown.Text +import org.commonmark.node.Code as CMCode +import org.commonmark.node.CustomNode as CMCustomNode +import org.commonmark.node.Emphasis as CMEmphasis +import org.commonmark.node.HardLineBreak as CMHardLineBreak +import org.commonmark.node.HtmlInline as CMHtmlInline +import org.commonmark.node.Image as CMImage +import org.commonmark.node.Link as CMLink +import org.commonmark.node.Paragraph as CMParagraph +import org.commonmark.node.SoftLineBreak as CMSoftLineBreak +import org.commonmark.node.StrongEmphasis as CMStrongEmphasis +import org.commonmark.node.Text as CMText + +/** + * A run of inline Markdown used as content for + * [block-level elements][MarkdownBlock]. + */ +public sealed interface InlineMarkdown { + + public val value: Node + + @JvmInline + public value class Emphasis(override val value: CMEmphasis) : InlineMarkdown + + @JvmInline + public value class Image(override val value: CMImage) : InlineMarkdown + + @JvmInline + public value class Code(override val value: CMCode) : InlineMarkdown + + @JvmInline + public value class CustomNode(override val value: CMCustomNode) : InlineMarkdown + + @JvmInline + public value class HardLineBreak(override val value: CMHardLineBreak) : InlineMarkdown + + @JvmInline + public value class SoftLineBreak(override val value: CMSoftLineBreak) : InlineMarkdown + + @JvmInline + public value class HtmlInline(override val value: CMHtmlInline) : InlineMarkdown + + @JvmInline + public value class Link(override val value: CMLink) : InlineMarkdown + + @JvmInline + public value class StrongEmphasis(override val value: CMStrongEmphasis) : InlineMarkdown + + @JvmInline + public value class Paragraph(override val value: CMParagraph) : InlineMarkdown + + @JvmInline + public value class Text(override val value: CMText) : InlineMarkdown + + public val children: Iterator + get() = object : Iterator { + var current = this@InlineMarkdown.value.firstChild + + override fun hasNext(): Boolean = current != null + + override fun next(): InlineMarkdown = + if (hasNext()) { + current.toInlineNode().also { + current = current.next + } + } else { + throw NoSuchElementException() + } + } +} + +public fun Node.toInlineNode(): InlineMarkdown = when (this) { + is CMText -> Text(this) + is CMEmphasis -> Emphasis(this) + is CMImage -> Image(this) + is CMCode -> Code(this) + is CMCustomNode -> CustomNode(this) + is CMHardLineBreak -> HardLineBreak(this) + is CMSoftLineBreak -> SoftLineBreak(this) + is CMHtmlInline -> HtmlInline(this) + is CMLink -> Link(this) + is CMStrongEmphasis -> StrongEmphasis(this) + else -> error("Unexpected block $this") +} diff --git a/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/MarkdownBlock.kt b/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/MarkdownBlock.kt index 5c6a9026d..9ce3b00d9 100644 --- a/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/MarkdownBlock.kt +++ b/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/MarkdownBlock.kt @@ -1,45 +1,48 @@ package org.jetbrains.jewel.markdown -import org.intellij.lang.annotations.Language - public sealed interface MarkdownBlock { - public data class Paragraph(override val inlineContent: InlineMarkdown) : - MarkdownBlock, BlockWithInlineMarkdown - - public sealed interface Heading : MarkdownBlock, BlockWithInlineMarkdown { - - public data class H1(override val inlineContent: InlineMarkdown) : Heading + public data class BlockQuote(val content: List) : MarkdownBlock - public data class H2(override val inlineContent: InlineMarkdown) : Heading + public interface CustomBlock : MarkdownBlock - public data class H3(override val inlineContent: InlineMarkdown) : Heading + public sealed interface CodeBlock : MarkdownBlock { - public data class H4(override val inlineContent: InlineMarkdown) : Heading + public val content: String - public data class H5(override val inlineContent: InlineMarkdown) : Heading + public data class IndentedCodeBlock( + override val content: String, + ) : CodeBlock - public data class H6(override val inlineContent: InlineMarkdown) : Heading + public data class FencedCodeBlock( + override val content: String, + val mimeType: MimeType?, + ) : CodeBlock } - public data class BlockQuote(val content: List) : MarkdownBlock + public data class Heading( + override val inlineContent: List, + val level: Int, + ) : MarkdownBlock, BlockWithInlineMarkdown + + public data class HtmlBlock(val content: String) : MarkdownBlock public sealed interface ListBlock : MarkdownBlock { public val items: List public val isTight: Boolean - public data class OrderedList( + public data class BulletList( override val items: List, override val isTight: Boolean, - val startFrom: Int, - val delimiter: Char, + val bulletMarker: String, ) : ListBlock - public data class UnorderedList( + public data class OrderedList( override val items: List, override val isTight: Boolean, - val bulletMarker: Char, + val startFrom: Int, + val delimiter: String, ) : ListBlock } @@ -47,37 +50,13 @@ public sealed interface MarkdownBlock { val content: List, ) : MarkdownBlock - public sealed interface CodeBlock : MarkdownBlock { - - public val content: String - - public data class IndentedCodeBlock( - override val content: String, - ) : CodeBlock - - public data class FencedCodeBlock( - override val content: String, - val mimeType: MimeType?, - ) : CodeBlock - } - - public data class Image(val url: String, val altString: String?) : MarkdownBlock - public object ThematicBreak : MarkdownBlock - public data class HtmlBlock(val content: String) : MarkdownBlock - - public interface Extension : MarkdownBlock + public data class Paragraph(override val inlineContent: List) : + MarkdownBlock, BlockWithInlineMarkdown } public interface BlockWithInlineMarkdown { - public val inlineContent: InlineMarkdown + public val inlineContent: List } - -/** - * A run of inline Markdown used as content for - * [block-level elements][MarkdownBlock]. - */ -@JvmInline -public value class InlineMarkdown(@Language("Markdown") public val content: String) diff --git a/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/extensions/MarkdownBlockProcessorExtension.kt b/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/extensions/MarkdownBlockProcessorExtension.kt index 996e67a8d..860797a7b 100644 --- a/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/extensions/MarkdownBlockProcessorExtension.kt +++ b/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/extensions/MarkdownBlockProcessorExtension.kt @@ -14,10 +14,10 @@ public interface MarkdownBlockProcessorExtension { public fun canProcess(block: CustomBlock): Boolean /** - * Processes the [block] as a [MarkdownBlock.Extension], if possible. Note + * Processes the [block] as a [MarkdownBlock.CustomBlock], if possible. Note * that you should always check that [canProcess] returns true for the same * [block], as implementations might throw an exception for unsupported * block types. */ - public fun processMarkdownBlock(block: CustomBlock, processor: MarkdownProcessor): MarkdownBlock.Extension? + public fun processMarkdownBlock(block: CustomBlock, processor: MarkdownProcessor): MarkdownBlock.CustomBlock? } diff --git a/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/extensions/MarkdownBlockRendererExtension.kt b/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/extensions/MarkdownBlockRendererExtension.kt index 7b3d728c3..ea5cb42a2 100644 --- a/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/extensions/MarkdownBlockRendererExtension.kt +++ b/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/extensions/MarkdownBlockRendererExtension.kt @@ -2,26 +2,26 @@ package org.jetbrains.jewel.markdown.extensions import androidx.compose.runtime.Composable import org.jetbrains.jewel.markdown.MarkdownBlock -import org.jetbrains.jewel.markdown.MarkdownBlock.Extension +import org.jetbrains.jewel.markdown.MarkdownBlock.CustomBlock import org.jetbrains.jewel.markdown.rendering.InlineMarkdownRenderer import org.jetbrains.jewel.markdown.rendering.MarkdownBlockRenderer /** * An extension for [MarkdownBlockRenderer] that can render one or more - * [MarkdownBlock.Extension]s. + * [MarkdownBlock.CustomBlock]s. */ public interface MarkdownBlockRendererExtension { /** Check whether the provided [block] can be rendered by this extension. */ - public fun canRender(block: Extension): Boolean + public fun canRender(block: CustomBlock): Boolean /** - * Render a [MarkdownBlock.Extension] as a native Composable. Note that if + * Render a [MarkdownBlock.CustomBlock] as a native Composable. Note that if * [canRender] returns `false` for [block], the implementation might throw. */ @Composable public fun render( - block: Extension, + block: CustomBlock, blockRenderer: MarkdownBlockRenderer, inlineRenderer: InlineMarkdownRenderer, ) diff --git a/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/extensions/MarkdownProcessorExtension.kt b/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/extensions/MarkdownProcessorExtension.kt index a8fafd626..3495b290c 100644 --- a/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/extensions/MarkdownProcessorExtension.kt +++ b/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/extensions/MarkdownProcessorExtension.kt @@ -27,7 +27,7 @@ public interface MarkdownProcessorExtension { * An extension for * [`MarkdownParser`][org.jetbrains.jewel.markdown.parsing.MarkdownParser] * that will transform a supported [CustomBlock] into the corresponding - * [MarkdownBlock.Extension]. + * [MarkdownBlock.CustomBlock]. */ public val processorExtension: MarkdownBlockProcessorExtension? } diff --git a/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/extensions/MarkdownRendererExtension.kt b/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/extensions/MarkdownRendererExtension.kt index 6ec625008..bd6fd86d8 100644 --- a/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/extensions/MarkdownRendererExtension.kt +++ b/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/extensions/MarkdownRendererExtension.kt @@ -10,7 +10,7 @@ public interface MarkdownRendererExtension { * An extension for * [`MarkdownBlockRenderer`][org.jetbrains.jewel.markdown.rendering.MarkdownBlockRenderer] * that will render a supported - * [`Extension`][org.jetbrains.jewel.markdown.MarkdownBlock.Extension] into + * [`CustomBlock`][org.jetbrains.jewel.markdown.MarkdownBlock.CustomBlock] into * a native Jewel UI. */ public val blockRenderer: MarkdownBlockRendererExtension diff --git a/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/processing/MarkdownProcessor.kt b/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/processing/MarkdownProcessor.kt index 6509161a7..a30750bc4 100644 --- a/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/processing/MarkdownProcessor.kt +++ b/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/processing/MarkdownProcessor.kt @@ -1,58 +1,61 @@ package org.jetbrains.jewel.markdown.processing +import org.commonmark.node.Block import org.commonmark.node.BlockQuote import org.commonmark.node.BulletList -import org.commonmark.node.Code import org.commonmark.node.CustomBlock import org.commonmark.node.Document -import org.commonmark.node.Emphasis import org.commonmark.node.FencedCodeBlock -import org.commonmark.node.HardLineBreak import org.commonmark.node.Heading import org.commonmark.node.HtmlBlock -import org.commonmark.node.HtmlInline -import org.commonmark.node.Image import org.commonmark.node.IndentedCodeBlock -import org.commonmark.node.Link import org.commonmark.node.ListBlock import org.commonmark.node.ListItem import org.commonmark.node.Node import org.commonmark.node.OrderedList import org.commonmark.node.Paragraph -import org.commonmark.node.SoftLineBreak -import org.commonmark.node.StrongEmphasis -import org.commonmark.node.Text import org.commonmark.node.ThematicBreak +import org.commonmark.parser.IncludeSourceSpans import org.commonmark.parser.Parser -import org.commonmark.renderer.text.TextContentRenderer import org.intellij.lang.annotations.Language +import org.jetbrains.annotations.TestOnly +import org.jetbrains.annotations.VisibleForTesting import org.jetbrains.jewel.foundation.ExperimentalJewelApi import org.jetbrains.jewel.markdown.InlineMarkdown import org.jetbrains.jewel.markdown.MarkdownBlock import org.jetbrains.jewel.markdown.MarkdownBlock.CodeBlock -import org.jetbrains.jewel.markdown.MarkdownBlock.Heading.H1 -import org.jetbrains.jewel.markdown.MarkdownBlock.Heading.H2 -import org.jetbrains.jewel.markdown.MarkdownBlock.Heading.H3 -import org.jetbrains.jewel.markdown.MarkdownBlock.Heading.H4 -import org.jetbrains.jewel.markdown.MarkdownBlock.Heading.H5 -import org.jetbrains.jewel.markdown.MarkdownBlock.Heading.H6 -import org.jetbrains.jewel.markdown.MarkdownBlock.ListBlock.UnorderedList import org.jetbrains.jewel.markdown.MimeType import org.jetbrains.jewel.markdown.extensions.MarkdownProcessorExtension import org.jetbrains.jewel.markdown.rendering.DefaultInlineMarkdownRenderer +import org.jetbrains.jewel.markdown.toInlineNode +/** + * @param optimizeEdits Optional. Indicates whether the processing should only update the changed blocks + * by keeping a previous state in memory. Default is `true`, use `false` for immutable data. + */ @ExperimentalJewelApi -public class MarkdownProcessor(private val extensions: List = emptyList()) { +public class MarkdownProcessor( + private val extensions: List = emptyList(), + private val optimizeEdits: Boolean = true, +) { public constructor(vararg extensions: MarkdownProcessorExtension) : this(extensions.toList()) - private val commonMarkParser = - Parser.builder().extensions(extensions.map { it.parserExtension }).build() + private val commonMarkParser = Parser.builder() + .let { builder -> + builder.extensions(extensions.map(MarkdownProcessorExtension::parserExtension)) + if (optimizeEdits) { + builder.includeSourceSpans(IncludeSourceSpans.BLOCKS) + } + builder.build() + } + + private data class State(val lines: List, val blocks: List, val indexes: List>) - private val textContentRenderer = - TextContentRenderer.builder() - .extensions(extensions.map { it.textRendererExtension }) - .build() + private var currentState = State(emptyList(), emptyList(), emptyList()) + + @TestOnly + internal fun getCurrentIndexesInTest() = currentState.indexes /** * Parses a Markdown document, translating from CommonMark 0.31.2 @@ -83,11 +86,94 @@ public class MarkdownProcessor(private val extensions: List { + return if (!optimizeEdits) { + textToBlocks(rawMarkdown) + } else { + processWithQuickEdits(rawMarkdown) + }.mapNotNull { child -> + child.tryProcessMarkdownBlock() + } + } + + @VisibleForTesting + internal fun processWithQuickEdits(@Language("Markdown") rawMarkdown: String): List { + val (previousLines, previousBlocks, previousIndexes) = currentState + val newLines = rawMarkdown.lines() + val nLinesDelta = newLines.size - previousLines.size + // find a block prior to the first one changed in case some elements merge during the update + var firstBlock = 0 + var firstLine = 0 + var currFirstBlock = 0 + var currFirstLine = 0 + outerLoop@ for ((i, spans) in previousIndexes.withIndex()) { + val (_, end) = spans + for (j in currFirstLine..end) { + if (newLines[j] != previousLines[j]) { + break@outerLoop + } + } + firstBlock = currFirstBlock + firstLine = currFirstLine + currFirstBlock = i + 1 + currFirstLine = end + 1 + } + // find a block following the last one changed in case some elements merge during the update + var lastBlock = previousBlocks.size + var lastLine = previousLines.size + var currLastBlock = lastBlock + var currLastLine = lastLine + outerLoop@ for ((i, spans) in previousIndexes.withIndex().reversed()) { + val (begin, _) = spans + for (j in begin until currLastLine) { + if (previousLines[j] != newLines[j + nLinesDelta]) { + break@outerLoop + } + } + lastBlock = currLastBlock + lastLine = currLastLine + currLastBlock = i + currLastLine = begin + } + if (firstLine > lastLine + nLinesDelta) { + // no change + return previousBlocks + } + val updatedText = newLines.subList(firstLine, lastLine + nLinesDelta).joinToString("\n", postfix = "\n") + val updatedBlocks: List = textToBlocks(updatedText) + val updatedIndexes = + updatedBlocks.map { node -> + // special case for a bug where LinkReferenceDefinition is a Node, + // but it takes over sourceSpans from the following Block + if (node.sourceSpans.isEmpty()) { + node.sourceSpans = node.previous.sourceSpans + } + (node.sourceSpans.first().lineIndex + firstLine) to + (node.sourceSpans.last().lineIndex + firstLine) + } + val suffixIndexes = previousIndexes.subList(lastBlock, previousBlocks.size).map { + (it.first + nLinesDelta) to (it.second + nLinesDelta) + } + val newBlocks = ( + previousBlocks.subList(0, firstBlock) + + updatedBlocks + + previousBlocks.subList(lastBlock, previousBlocks.size) + ) + val newIndexes = previousIndexes.subList(0, firstBlock) + updatedIndexes + suffixIndexes + currentState = State(newLines, newBlocks, newIndexes) + return newBlocks + } + + private fun textToBlocks(strings: String): List { val document = - commonMarkParser.parse(rawMarkdown) as? Document + commonMarkParser.parse(strings) as? Document ?: error("This doesn't look like a Markdown document") - - return processChildren(document) + val updatedBlocks: List = + buildList { + document.forEachChild { child -> + (child as? Block)?.let { add(it) } + } + } + return updatedBlocks } private fun Node.tryProcessMarkdownBlock(): MarkdownBlock? = @@ -98,7 +184,6 @@ public class MarkdownProcessor(private val extensions: List toMarkdownParagraphOrNull() is FencedCodeBlock -> toMarkdownCodeBlockOrNull() is IndentedCodeBlock -> toMarkdownCodeBlockOrNull() - is Image -> toMarkdownImageOrNull() is BulletList -> toMarkdownListOrNull() is OrderedList -> toMarkdownListOrNull() is ThematicBreak -> MarkdownBlock.ThematicBreak @@ -107,7 +192,6 @@ public class MarkdownProcessor(private val extensions: List null } @@ -115,20 +199,16 @@ public class MarkdownProcessor(private val extensions: List H1(contentsAsInlineMarkdown()) - 2 -> H2(contentsAsInlineMarkdown()) - 3 -> H3(contentsAsInlineMarkdown()) - 4 -> H4(contentsAsInlineMarkdown()) - 5 -> H5(contentsAsInlineMarkdown()) - 6 -> H6(contentsAsInlineMarkdown()) - else -> null + if (level > 6) { + null + } else { + MarkdownBlock.Heading(contentsAsInlineMarkdown(), level) } private fun Paragraph.toMarkdownParagraphOrNull(): MarkdownBlock.Paragraph? { val inlineMarkdown = contentsAsInlineMarkdown() - if (inlineMarkdown.isBlank()) return null + if (inlineMarkdown.isEmpty()) return null return MarkdownBlock.Paragraph(inlineMarkdown) } @@ -141,24 +221,18 @@ public class MarkdownProcessor(private val extensions: List = buildList { node.forEachChild { child -> val parsedBlock = child.tryProcessMarkdownBlock() - if (parsedBlock != null) this.add(parsedBlock) + if (parsedBlock != null) { + this.add(parsedBlock) + } } } @@ -189,159 +265,9 @@ public class MarkdownProcessor(private val extensions: List append(child.literal.escapeInlineMarkdownChars()) - is Image -> appendImage(child) - - is Emphasis -> { - append(child.openingDelimiter) - appendInlineMarkdownFrom(child, !ignoreNestedEmphasis) - append(child.closingDelimiter) - } - - is StrongEmphasis -> { - append(child.openingDelimiter) - appendInlineMarkdownFrom(child) - append(child.closingDelimiter) - } - - is Code -> append(child.literal.asInlineCodeString()) - is Link -> appendLink(child, allowLinks) - - is HardLineBreak -> appendLine() - is SoftLineBreak -> append(' ') - is HtmlInline -> append(child.literal.trim()) - } - child = child.next - } - } - - private fun StringBuilder.appendImage(child: Image) { - append("![") - appendInlineMarkdownFrom(child, allowLinks = false) - - // Escape dangling backslashes at the end of the text - val backSlashCount = takeLastWhile { it == '\\' }.length - if (backSlashCount % 2 != 0) append('\\') - - append("](") - append(child.destination.escapeLinkDestination()) - - if (!child.title.isNullOrBlank()) { - append(" \"") - append(child.title.replace("\"", "\\\"").trim()) - append('"') - } - append(')') - } - - private fun StringBuilder.appendLink(child: Link, allowLinks: Boolean) { - val hasText = child.firstChild != null - if (child.destination.isNullOrBlank() && !hasText) { - // Ignore links with no destination and no text - return - } - - if (allowLinks) { - append('[') - - if (hasText) { - // Link text cannot contain links — just in case... - appendInlineMarkdownFrom(child, allowLinks = false) - - // Escape dangling backslashes at the end of the text - val backSlashCount = takeLastWhile { it == '\\' }.length - if (backSlashCount % 2 != 0) append('\\') - } else { - // No text: use the destination - append(child.destination.escapeLinkDestinationForUseInText()) - } - - append("](") - append(child.destination.escapeLinkDestination()) - - if (!child.title.isNullOrBlank()) { - append(" \"") - append(child.title.replace("\"", "\\\"").trim()) - append('"') - } - append(')') - } else { - append(plainTextContents(child)) - } - } - - private fun String.escapeLinkDestinationForUseInText() = - replace("[", "[").replace("]", "]") - - private fun String.escapeLinkDestination(): String { - val escaped = replace(">", "//>").replace("(", "\\(").replace(")", "\\)") - return if (any { it.isWhitespace() && it != '\n' }) "<$escaped>" else escaped - } - - private fun String.escapeInlineMarkdownChars() = - buildString(length) { - var precedingBackslashesCount = 0 - var isNewLine = true - - for (char in this@escapeInlineMarkdownChars) { - when (char) { - '\\' -> precedingBackslashesCount++ - '\n' -> isNewLine = true - else -> { - val isUnescaped = (precedingBackslashesCount % 2) == 0 - if (char in "*_~`<>[]()!" && (isNewLine || isUnescaped)) { - append('\\') - } - - isNewLine = false - precedingBackslashesCount = 0 - } - } - append(char) - } - } - - private fun String.asInlineCodeString(): String { - // Base case: doesn't contain backticks - if (!contains("`")) { - return "`$this`" - } - - var currentCount = 0 - var longestCount = 0 - - // First, count the longest run of backticks in the string - for (char in this) { - if (char == '`') { - currentCount++ - } else { - if (currentCount > longestCount) { - longestCount = currentCount - } - currentCount = 0 - } + private fun Node.contentsAsInlineMarkdown() = buildList { + forEachChild { + add(it.toInlineNode()) } - - if (currentCount > longestCount) longestCount = currentCount - - // Then wrap it in n + 1 backticks to avoid early termination - val backticks = "`".repeat(longestCount + 1) - return "$backticks$this$backticks" } - - private fun InlineMarkdown.isBlank(): Boolean = content.isBlank() - - private fun plainTextContents(node: Node): String = textContentRenderer.render(node) } diff --git a/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/rendering/DefaultInlineMarkdownRenderer.kt b/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/rendering/DefaultInlineMarkdownRenderer.kt index 9a77ae465..94b11a1d6 100644 --- a/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/rendering/DefaultInlineMarkdownRenderer.kt +++ b/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/rendering/DefaultInlineMarkdownRenderer.kt @@ -7,19 +7,6 @@ import androidx.compose.ui.text.ExperimentalTextApi import androidx.compose.ui.text.SpanStyle import androidx.compose.ui.text.UrlAnnotation import androidx.compose.ui.text.buildAnnotatedString -import org.commonmark.node.Block -import org.commonmark.node.Code -import org.commonmark.node.Emphasis -import org.commonmark.node.HardLineBreak -import org.commonmark.node.HtmlInline -import org.commonmark.node.Image -import org.commonmark.node.Link -import org.commonmark.node.Node -import org.commonmark.node.Paragraph -import org.commonmark.node.SoftLineBreak -import org.commonmark.node.StrongEmphasis -import org.commonmark.node.Text -import org.commonmark.parser.Parser import org.commonmark.renderer.text.TextContentRenderer import org.jetbrains.jewel.foundation.ExperimentalJewelApi import org.jetbrains.jewel.markdown.InlineMarkdown @@ -30,78 +17,73 @@ public open class DefaultInlineMarkdownRenderer(rendererExtensions: List, styling: InlinesStyling, ): AnnotatedString = buildAnnotatedString { - val node = commonMarkParser.parse(inlineMarkdown.content) - appendInlineMarkdownFrom(node, styling) + appendInlineMarkdownFrom(inlineMarkdown.iterator(), styling) } @OptIn(ExperimentalTextApi::class) - private fun Builder.appendInlineMarkdownFrom(node: Node, styling: InlinesStyling) { - var child = node.firstChild - - while (child != null) { + private fun Builder.appendInlineMarkdownFrom(inlineMarkdown: Iterator, styling: InlinesStyling) { + for (child in inlineMarkdown) { when (child) { - is Paragraph -> appendInlineMarkdownFrom(child, styling) - is Image -> { - appendInlineContent( - INLINE_IMAGE, - child.destination + "\n" + plainTextRenderer.render(child), - ) + is InlineMarkdown.Paragraph -> { + appendInlineMarkdownFrom(child.children, styling) } - is Text -> append(child.literal) - is Emphasis -> { - withStyles(styling.emphasis, child) { appendInlineMarkdownFrom(it, styling) } - } + is InlineMarkdown.Text -> append(child.value.literal) - is StrongEmphasis -> { - withStyles(styling.strongEmphasis, child) { appendInlineMarkdownFrom(it, styling) } + is InlineMarkdown.Emphasis -> { + withStyles(styling.emphasis, child) { appendInlineMarkdownFrom(it.children, styling) } } - is Code -> { - withStyles(styling.inlineCode, child) { append(it.literal) } + is InlineMarkdown.StrongEmphasis -> { + withStyles(styling.strongEmphasis, child) { appendInlineMarkdownFrom(it.children, styling) } } - is Link -> { + is InlineMarkdown.Link -> { withStyles(styling.link, child) { - pushUrlAnnotation(UrlAnnotation(it.destination)) - appendInlineMarkdownFrom(it, styling) + pushUrlAnnotation(UrlAnnotation(it.value.destination)) + appendInlineMarkdownFrom(it.children, styling) } } - is HardLineBreak, - is SoftLineBreak, + is InlineMarkdown.Code -> { + withStyles(styling.inlineCode, child) { append(it.value.literal) } + } + + is InlineMarkdown.HardLineBreak, + is InlineMarkdown.SoftLineBreak, -> appendLine() - is HtmlInline -> { + is InlineMarkdown.HtmlInline -> { if (styling.renderInlineHtml) { - withStyles(styling.inlineHtml, child) { append(it.literal.trim()) } + withStyles(styling.inlineHtml, child) { append(it.value.literal.trim()) } } } - is Block -> { - error("Only inline Markdown can be rendered to an AnnotatedString. Found: $child") + is InlineMarkdown.Image -> { + appendInlineContent( + INLINE_IMAGE, + child.value.destination + "\n" + plainTextRenderer.render(child.value), + ) } + + is InlineMarkdown.CustomNode -> error("InlineMarkdown.CustomNode render is not implemented") } - child = child.next } } // The T type parameter is needed to avoid issues with capturing lambdas // making smart cast of the child local variable impossible. - private inline fun Builder.withStyles( + private inline fun Builder.withStyles( spanStyle: SpanStyle, node: T, action: Builder.(T) -> Unit, diff --git a/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/rendering/DefaultMarkdownBlockRenderer.kt b/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/rendering/DefaultMarkdownBlockRenderer.kt index 9dc387f69..a88dc96ee 100644 --- a/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/rendering/DefaultMarkdownBlockRenderer.kt +++ b/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/rendering/DefaultMarkdownBlockRenderer.kt @@ -55,19 +55,12 @@ import org.jetbrains.jewel.markdown.MarkdownBlock.BlockQuote import org.jetbrains.jewel.markdown.MarkdownBlock.CodeBlock import org.jetbrains.jewel.markdown.MarkdownBlock.CodeBlock.FencedCodeBlock import org.jetbrains.jewel.markdown.MarkdownBlock.CodeBlock.IndentedCodeBlock -import org.jetbrains.jewel.markdown.MarkdownBlock.Extension +import org.jetbrains.jewel.markdown.MarkdownBlock.CustomBlock import org.jetbrains.jewel.markdown.MarkdownBlock.Heading -import org.jetbrains.jewel.markdown.MarkdownBlock.Heading.H1 -import org.jetbrains.jewel.markdown.MarkdownBlock.Heading.H2 -import org.jetbrains.jewel.markdown.MarkdownBlock.Heading.H3 -import org.jetbrains.jewel.markdown.MarkdownBlock.Heading.H4 -import org.jetbrains.jewel.markdown.MarkdownBlock.Heading.H5 -import org.jetbrains.jewel.markdown.MarkdownBlock.Heading.H6 import org.jetbrains.jewel.markdown.MarkdownBlock.HtmlBlock -import org.jetbrains.jewel.markdown.MarkdownBlock.Image import org.jetbrains.jewel.markdown.MarkdownBlock.ListBlock +import org.jetbrains.jewel.markdown.MarkdownBlock.ListBlock.BulletList import org.jetbrains.jewel.markdown.MarkdownBlock.ListBlock.OrderedList -import org.jetbrains.jewel.markdown.MarkdownBlock.ListBlock.UnorderedList import org.jetbrains.jewel.markdown.MarkdownBlock.ListItem import org.jetbrains.jewel.markdown.MarkdownBlock.Paragraph import org.jetbrains.jewel.markdown.MarkdownBlock.ThematicBreak @@ -76,6 +69,7 @@ import org.jetbrains.jewel.ui.Orientation.Horizontal import org.jetbrains.jewel.ui.component.Divider import org.jetbrains.jewel.ui.component.Text +@Suppress("FunctionName") @ExperimentalJewelApi public open class DefaultMarkdownBlockRenderer( private val rootStyling: MarkdownStyling, @@ -99,20 +93,14 @@ public open class DefaultMarkdownBlockRenderer( is BlockQuote -> render(block, rootStyling.blockQuote) is FencedCodeBlock -> render(block, rootStyling.code.fenced) is IndentedCodeBlock -> render(block, rootStyling.code.indented) - is H1 -> render(block, rootStyling.heading.h1) - is H2 -> render(block, rootStyling.heading.h2) - is H3 -> render(block, rootStyling.heading.h3) - is H4 -> render(block, rootStyling.heading.h4) - is H5 -> render(block, rootStyling.heading.h5) - is H6 -> render(block, rootStyling.heading.h6) + is Heading -> render(block, rootStyling.heading) is HtmlBlock -> render(block, rootStyling.htmlBlock) - is Image -> render(block, rootStyling.image) is OrderedList -> render(block, rootStyling.list.ordered) - is UnorderedList -> render(block, rootStyling.list.unordered) + is BulletList -> render(block, rootStyling.list.unordered) is ListItem -> render(block) is Paragraph -> render(block, rootStyling.paragraph) ThematicBreak -> renderThematicBreak(rootStyling.thematicBreak) - is Extension -> { + is CustomBlock -> { rendererExtensions.find { it.blockRenderer.canRender(block) } ?.blockRenderer?.render(block, this, inlineRenderer) } @@ -127,83 +115,19 @@ public open class DefaultMarkdownBlockRenderer( @Composable override fun render(block: Heading, styling: MarkdownStyling.Heading) { - when (block) { - is H1 -> render(block, styling) - is H2 -> render(block, styling) - is H3 -> render(block, styling) - is H4 -> render(block, styling) - is H5 -> render(block, styling) - is H6 -> render(block, styling) + when (block.level) { + 1 -> render(block, styling.h1) + 2 -> render(block, styling.h2) + 3 -> render(block, styling.h3) + 4 -> render(block, styling.h4) + 5 -> render(block, styling.h5) + 6 -> render(block, styling.h6) + else -> error("Heading level ${block.level} not supported:\n$block") } } @Composable - override fun render(block: H1, styling: MarkdownStyling.Heading.H1) { - val renderedContent = rememberRenderedContent(block, styling.inlinesStyling) - Heading( - renderedContent, - styling.inlinesStyling.textStyle, - styling.padding, - styling.underlineWidth, - styling.underlineColor, - styling.underlineGap, - ) - } - - @Composable - override fun render(block: H2, styling: MarkdownStyling.Heading.H2) { - val renderedContent = rememberRenderedContent(block, styling.inlinesStyling) - Heading( - renderedContent, - styling.inlinesStyling.textStyle, - styling.padding, - styling.underlineWidth, - styling.underlineColor, - styling.underlineGap, - ) - } - - @Composable - override fun render(block: H3, styling: MarkdownStyling.Heading.H3) { - val renderedContent = rememberRenderedContent(block, styling.inlinesStyling) - Heading( - renderedContent, - styling.inlinesStyling.textStyle, - styling.padding, - styling.underlineWidth, - styling.underlineColor, - styling.underlineGap, - ) - } - - @Composable - override fun render(block: H4, styling: MarkdownStyling.Heading.H4) { - val renderedContent = rememberRenderedContent(block, styling.inlinesStyling) - Heading( - renderedContent, - styling.inlinesStyling.textStyle, - styling.padding, - styling.underlineWidth, - styling.underlineColor, - styling.underlineGap, - ) - } - - @Composable - override fun render(block: H5, styling: MarkdownStyling.Heading.H5) { - val renderedContent = rememberRenderedContent(block, styling.inlinesStyling) - Heading( - renderedContent, - styling.inlinesStyling.textStyle, - styling.padding, - styling.underlineWidth, - styling.underlineColor, - styling.underlineGap, - ) - } - - @Composable - override fun render(block: H6, styling: MarkdownStyling.Heading.H6) { + override fun render(block: Heading, styling: MarkdownStyling.Heading.HN) { val renderedContent = rememberRenderedContent(block, styling.inlinesStyling) Heading( renderedContent, @@ -267,7 +191,7 @@ public open class DefaultMarkdownBlockRenderer( override fun render(block: ListBlock, styling: MarkdownStyling.List) { when (block) { is OrderedList -> render(block, styling.ordered) - is UnorderedList -> render(block, styling.unordered) + is BulletList -> render(block, styling.unordered) } } @@ -304,7 +228,7 @@ public open class DefaultMarkdownBlockRenderer( } @Composable - override fun render(block: UnorderedList, styling: MarkdownStyling.List.Unordered) { + override fun render(block: BulletList, styling: MarkdownStyling.List.Unordered) { val itemSpacing = if (block.isTight) { styling.itemVerticalSpacingTight @@ -414,18 +338,6 @@ public open class DefaultMarkdownBlockRenderer( } } - @Composable - override fun render(block: Image, styling: MarkdownStyling.Image) { - // TODO implement image rendering support (will require image loading) - Text( - "⚠️ Images are not supported yet", - Modifier.border(1.dp, Color.Red) - .padding(horizontal = 8.dp, vertical = 4.dp) - .pointerHoverIcon(PointerIcon.Default, overrideDescendants = true), - color = Color.Red, - ) - } - @Composable override fun renderThematicBreak(styling: MarkdownStyling.ThematicBreak) { Box(Modifier.padding(styling.padding).height(styling.lineWidth).background(styling.lineColor)) diff --git a/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/rendering/InlineMarkdownRenderer.kt b/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/rendering/InlineMarkdownRenderer.kt index 49d69ebaa..210818511 100644 --- a/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/rendering/InlineMarkdownRenderer.kt +++ b/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/rendering/InlineMarkdownRenderer.kt @@ -12,7 +12,7 @@ public interface InlineMarkdownRenderer { * Render the [inlineMarkdown] as an [AnnotatedString], using the [styling] * provided. */ - public fun renderAsAnnotatedString(inlineMarkdown: InlineMarkdown, styling: InlinesStyling): AnnotatedString + public fun renderAsAnnotatedString(inlineMarkdown: List, styling: InlinesStyling): AnnotatedString public companion object { diff --git a/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/rendering/MarkdownBlockRenderer.kt b/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/rendering/MarkdownBlockRenderer.kt index 794f792c1..03d8e94a4 100644 --- a/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/rendering/MarkdownBlockRenderer.kt +++ b/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/rendering/MarkdownBlockRenderer.kt @@ -7,17 +7,10 @@ import org.jetbrains.jewel.markdown.MarkdownBlock.BlockQuote import org.jetbrains.jewel.markdown.MarkdownBlock.CodeBlock import org.jetbrains.jewel.markdown.MarkdownBlock.CodeBlock.FencedCodeBlock import org.jetbrains.jewel.markdown.MarkdownBlock.CodeBlock.IndentedCodeBlock -import org.jetbrains.jewel.markdown.MarkdownBlock.Heading.H1 -import org.jetbrains.jewel.markdown.MarkdownBlock.Heading.H2 -import org.jetbrains.jewel.markdown.MarkdownBlock.Heading.H3 -import org.jetbrains.jewel.markdown.MarkdownBlock.Heading.H4 -import org.jetbrains.jewel.markdown.MarkdownBlock.Heading.H5 -import org.jetbrains.jewel.markdown.MarkdownBlock.Heading.H6 import org.jetbrains.jewel.markdown.MarkdownBlock.HtmlBlock -import org.jetbrains.jewel.markdown.MarkdownBlock.Image import org.jetbrains.jewel.markdown.MarkdownBlock.ListBlock +import org.jetbrains.jewel.markdown.MarkdownBlock.ListBlock.BulletList import org.jetbrains.jewel.markdown.MarkdownBlock.ListBlock.OrderedList -import org.jetbrains.jewel.markdown.MarkdownBlock.ListBlock.UnorderedList import org.jetbrains.jewel.markdown.MarkdownBlock.ListItem @ExperimentalJewelApi @@ -36,22 +29,7 @@ public interface MarkdownBlockRenderer { public fun render(block: MarkdownBlock.Heading, styling: MarkdownStyling.Heading) @Composable - public fun render(block: H1, styling: MarkdownStyling.Heading.H1) - - @Composable - public fun render(block: H2, styling: MarkdownStyling.Heading.H2) - - @Composable - public fun render(block: H3, styling: MarkdownStyling.Heading.H3) - - @Composable - public fun render(block: H4, styling: MarkdownStyling.Heading.H4) - - @Composable - public fun render(block: H5, styling: MarkdownStyling.Heading.H5) - - @Composable - public fun render(block: H6, styling: MarkdownStyling.Heading.H6) + public fun render(block: MarkdownBlock.Heading, styling: MarkdownStyling.Heading.HN) @Composable public fun render(block: BlockQuote, styling: MarkdownStyling.BlockQuote) @@ -63,7 +41,7 @@ public interface MarkdownBlockRenderer { public fun render(block: OrderedList, styling: MarkdownStyling.List.Ordered) @Composable - public fun render(block: UnorderedList, styling: MarkdownStyling.List.Unordered) + public fun render(block: BulletList, styling: MarkdownStyling.List.Unordered) @Composable public fun render(block: ListItem) @@ -77,9 +55,6 @@ public interface MarkdownBlockRenderer { @Composable public fun render(block: FencedCodeBlock, styling: MarkdownStyling.Code.Fenced) - @Composable - public fun render(block: Image, styling: MarkdownStyling.Image) - @Composable public fun renderThematicBreak(styling: MarkdownStyling.ThematicBreak) diff --git a/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/rendering/MarkdownStyling.kt b/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/rendering/MarkdownStyling.kt index 8c7a33142..28b23d79d 100644 --- a/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/rendering/MarkdownStyling.kt +++ b/markdown/core/src/main/kotlin/org/jetbrains/jewel/markdown/rendering/MarkdownStyling.kt @@ -52,14 +52,18 @@ public class MarkdownStyling( public val h6: H6, ) { + public interface HN : WithInlinesStyling, WithUnderline { + public val padding: PaddingValues + } + @GenerateDataFunctions public class H1( override val inlinesStyling: InlinesStyling, override val underlineWidth: Dp, override val underlineColor: Color, override val underlineGap: Dp, - public val padding: PaddingValues, - ) : WithInlinesStyling, WithUnderline { + override val padding: PaddingValues, + ) : HN { public companion object } @@ -70,8 +74,8 @@ public class MarkdownStyling( override val underlineWidth: Dp, override val underlineColor: Color, override val underlineGap: Dp, - public val padding: PaddingValues, - ) : WithInlinesStyling, WithUnderline { + override val padding: PaddingValues, + ) : HN { public companion object } @@ -82,8 +86,8 @@ public class MarkdownStyling( override val underlineWidth: Dp, override val underlineColor: Color, override val underlineGap: Dp, - public val padding: PaddingValues, - ) : WithInlinesStyling, WithUnderline { + override val padding: PaddingValues, + ) : HN { public companion object } @@ -94,8 +98,8 @@ public class MarkdownStyling( override val underlineWidth: Dp, override val underlineColor: Color, override val underlineGap: Dp, - public val padding: PaddingValues, - ) : WithInlinesStyling, WithUnderline { + override val padding: PaddingValues, + ) : HN { public companion object } @@ -106,8 +110,8 @@ public class MarkdownStyling( override val underlineWidth: Dp, override val underlineColor: Color, override val underlineGap: Dp, - public val padding: PaddingValues, - ) : WithInlinesStyling, WithUnderline { + override val padding: PaddingValues, + ) : HN { public companion object } @@ -118,8 +122,8 @@ public class MarkdownStyling( override val underlineWidth: Dp, override val underlineColor: Color, override val underlineGap: Dp, - public val padding: PaddingValues, - ) : WithInlinesStyling, WithUnderline { + override val padding: PaddingValues, + ) : HN { public companion object } diff --git a/markdown/core/src/test/kotlin/org/jetbrains/jewel/markdown/MarkdownProcessorDocumentParsingExtraTest.kt b/markdown/core/src/test/kotlin/org/jetbrains/jewel/markdown/MarkdownProcessorDocumentParsingExtraTest.kt index 2156fb674..15bf4c97e 100644 --- a/markdown/core/src/test/kotlin/org/jetbrains/jewel/markdown/MarkdownProcessorDocumentParsingExtraTest.kt +++ b/markdown/core/src/test/kotlin/org/jetbrains/jewel/markdown/MarkdownProcessorDocumentParsingExtraTest.kt @@ -7,6 +7,17 @@ class MarkdownProcessorDocumentParsingExtraTest { private val processor = MarkdownProcessor() + @Test + fun `should parse spec sample 22b correctly (Backslash escapes)`() { + val parsed = processor.processMarkdownDocument("[](/bar\\* \"ti\\*tle\")") + + /* + * Expected HTML: + *

foo

+ */ + parsed.assertEquals(paragraph("[](/bar* \"ti*tle\")")) + } + @Test fun `should parse spec sample 461b correctly (Emphasis and strong emphasis)`() { val parsed = processor.processMarkdownDocument("*_foo *bar*_*") diff --git a/markdown/core/src/test/kotlin/org/jetbrains/jewel/markdown/MarkdownProcessorDocumentParsingTest.kt b/markdown/core/src/test/kotlin/org/jetbrains/jewel/markdown/MarkdownProcessorDocumentParsingTest.kt index 22f59c8ca..ce1cdc54a 100644 --- a/markdown/core/src/test/kotlin/org/jetbrains/jewel/markdown/MarkdownProcessorDocumentParsingTest.kt +++ b/markdown/core/src/test/kotlin/org/jetbrains/jewel/markdown/MarkdownProcessorDocumentParsingTest.kt @@ -2,6 +2,7 @@ package org.jetbrains.jewel.markdown import org.jetbrains.jewel.markdown.MarkdownBlock.ThematicBreak import org.jetbrains.jewel.markdown.processing.MarkdownProcessor +import org.junit.Ignore import org.junit.Test /** @@ -217,12 +218,7 @@ class MarkdownProcessorDocumentParsingTest { fun `should parse spec sample 12 correctly (Backslash escapes)`() { val parsed = processor.processMarkdownDocument( - "\\!\\\"\\#\\\$\\%\\&\\'\\(\\)\\*\\+\\,\\-\\.\\/\\:\\;\\<\\=\\>\\?\\@" + - "\\[\\\\\\\\]\\^\\_\\`\\{\\|\\}\\~\n", - // ^^ - // Note: this was slightly edited by adding a backslash here - // because the `\[\\\]` sequence wouldn't be representable otherwise - // (CommonMark un-escapes characters, and it's a lossy transform) + "\\!\\\"\\#\\$\\%\\&\\'\\(\\)\\*\\+\\,\\-\\.\\/\\:\\;\\<\\=\\>\\?\\@\\[\\\\\\]\\^\\_\\`\\{\\|\\}\\~\n", ) /* @@ -283,7 +279,7 @@ class MarkdownProcessorDocumentParsingTest { "\\* not a list " + "# not a heading " + "\\[foo\\]: /url \"not a reference\" " + - "ö not a character entity", + "\\ö not a character entity", ), ) } @@ -296,7 +292,7 @@ class MarkdownProcessorDocumentParsingTest { * Expected HTML: *

\emphasis

*/ - parsed.assertEquals(paragraph("\\*emphasis*")) + parsed.assertEquals(paragraph("\\\\*emphasis*")) } @Test @@ -315,7 +311,7 @@ class MarkdownProcessorDocumentParsingTest { *

foo
* bar

*/ - parsed.assertEquals(paragraph("foo\nbar")) + parsed.assertEquals(paragraph("foo \nbar")) } @Test @@ -326,7 +322,7 @@ class MarkdownProcessorDocumentParsingTest { * Expected HTML: *

\[\`

*/ - parsed.assertEquals(paragraph("``\\[\\```")) + parsed.assertEquals(paragraph("`` \\[\\` ``")) } @Test @@ -369,7 +365,7 @@ class MarkdownProcessorDocumentParsingTest { * Expected HTML: *

https://example.com?find=\*

*/ - parsed.assertEquals(paragraph("[https://example.com?find=\\*](https://example.com?find=\\*)")) + parsed.assertEquals(paragraph("[https://example.com?find=\\\\*](https://example.com?find=\\\\*)")) } @Test @@ -394,17 +390,6 @@ class MarkdownProcessorDocumentParsingTest { parsed.assertEquals(paragraph("[foo](/bar* \"ti*tle\")")) } - @Test - fun `should parse spec sample 22b correctly (Backslash escapes)`() { - val parsed = processor.processMarkdownDocument("[](/bar\\* \"ti\\*tle\")") - - /* - * Expected HTML: - *

foo

- */ - parsed.assertEquals(paragraph("[/bar*](/bar* \"ti*tle\")")) - } - @Test fun `should parse spec sample 23 correctly (Backslash escapes)`() { val parsed = @@ -655,7 +640,7 @@ class MarkdownProcessorDocumentParsingTest { */ parsed.assertEquals( paragraph("\\* foo"), - unorderedList(listItem(paragraph("foo")), bulletMarker = '*'), + unorderedList(listItem(paragraph("foo")), bulletMarker = "*"), ) } @@ -1037,9 +1022,9 @@ class MarkdownProcessorDocumentParsingTest { * */ parsed.assertEquals( - unorderedList(listItem(paragraph("Foo")), bulletMarker = '*'), + unorderedList(listItem(paragraph("Foo")), bulletMarker = "*"), ThematicBreak, - unorderedList(listItem(paragraph("Bar")), bulletMarker = '*'), + unorderedList(listItem(paragraph("Bar")), bulletMarker = "*"), ) } @@ -4358,7 +4343,7 @@ class MarkdownProcessorDocumentParsingTest { * line2 * ">foo

*/ - parsed.assertEquals(paragraph("[foo](/url \"title\nline1\nline2\")")) + parsed.assertEquals(paragraph("[foo](/url \" title\nline1\nline2 \")")) } @Test @@ -4997,7 +4982,7 @@ class MarkdownProcessorDocumentParsingTest { *

aaa
* bbb

*/ - parsed.assertEquals(paragraph("aaa\nbbb")) + parsed.assertEquals(paragraph("aaa \nbbb")) } @Test @@ -6530,7 +6515,7 @@ class MarkdownProcessorDocumentParsingTest { *
  • * */ - parsed.assertEquals(unorderedList(listItem(), bulletMarker = '*')) + parsed.assertEquals(unorderedList(listItem(), bulletMarker = "*")) } @Test @@ -6962,7 +6947,7 @@ class MarkdownProcessorDocumentParsingTest { unorderedList(listItem(paragraph("bar"))), ), startFrom = 10, - delimiter = ')', + delimiter = ")", ), ) } @@ -6991,7 +6976,7 @@ class MarkdownProcessorDocumentParsingTest { orderedList( listItem(paragraph("foo")), startFrom = 10, - delimiter = ')', + delimiter = ")", ), unorderedList(listItem(paragraph("bar"))), ) @@ -7115,7 +7100,7 @@ class MarkdownProcessorDocumentParsingTest { ), unorderedList( listItem(paragraph("baz")), - bulletMarker = '+', + bulletMarker = "+", ), ) } @@ -7150,7 +7135,7 @@ class MarkdownProcessorDocumentParsingTest { orderedList( listItem(paragraph("baz")), startFrom = 3, - delimiter = ')', + delimiter = ")", ), ) } @@ -7624,7 +7609,7 @@ class MarkdownProcessorDocumentParsingTest { listItem(), listItem(paragraph("c")), isTight = false, - bulletMarker = '*', + bulletMarker = "*", ), ) } @@ -7817,7 +7802,7 @@ class MarkdownProcessorDocumentParsingTest { unorderedList( listItem(paragraph("a"), blockQuote(paragraph("b"))), listItem(paragraph("c")), - bulletMarker = '*', + bulletMarker = "*", ), ) } @@ -7972,11 +7957,11 @@ class MarkdownProcessorDocumentParsingTest { paragraph("foo"), unorderedList( listItem(paragraph("bar")), - bulletMarker = '*', + bulletMarker = "*", ), paragraph("baz"), ), - bulletMarker = '*', + bulletMarker = "*", isTight = false, ), ) @@ -8079,7 +8064,7 @@ class MarkdownProcessorDocumentParsingTest { * Expected HTML: *

    ``

    */ - parsed.assertEquals(paragraph("````````")) + parsed.assertEquals(paragraph("``")) } @Test @@ -8090,7 +8075,7 @@ class MarkdownProcessorDocumentParsingTest { * Expected HTML: *

    ``

    */ - parsed.assertEquals(paragraph("``` `` ```")) + parsed.assertEquals(paragraph(" `` ")) } @Test @@ -8368,7 +8353,6 @@ class MarkdownProcessorDocumentParsingTest { parsed.assertEquals(paragraph("\\* a \\*")) } - @org.junit.Ignore("need to update escapeInlineMarkdownChars implementation") @Test fun `should parse spec sample 354 correctly (Emphasis and strong emphasis)`() { val parsed = processor.processMarkdownDocument( @@ -9924,7 +9908,7 @@ class MarkdownProcessorDocumentParsingTest { * Expected HTML: *

    */ - parsed.assertEquals(paragraph("[./target.md](./target.md)")) + parsed.assertEquals(paragraph("[](./target.md)")) } @Test @@ -9957,7 +9941,7 @@ class MarkdownProcessorDocumentParsingTest { * Expected HTML: *

    */ - parsed.assertEquals() + parsed.assertEquals(paragraph("[]()")) } @Test @@ -10377,6 +10361,7 @@ class MarkdownProcessorDocumentParsingTest { parsed.assertEquals(paragraph("\\[foo *\\[bar [baz](/uri)\\]\\(/uri\\)*\\]\\(/uri\\)")) } + @Ignore @Test fun `should parse spec sample 520 correctly (Links)`() { val parsed = processor.processMarkdownDocument("![[[foo](uri1)](uri2)](uri3)") @@ -11400,7 +11385,7 @@ class MarkdownProcessorDocumentParsingTest { * Expected HTML: *

    foo bar

    */ - parsed.assertEquals(paragraph("![foo \"bar\" (/url)](/url2)")) + parsed.assertEquals(paragraph("![foo bar](/url2)")) } @Test @@ -11822,6 +11807,7 @@ class MarkdownProcessorDocumentParsingTest { parsed.assertEquals(paragraph("\\")) } + @Ignore @Test fun `should parse spec sample 603 correctly (Autolinks)`() { val parsed = processor.processMarkdownDocument("") @@ -12228,7 +12214,7 @@ class MarkdownProcessorDocumentParsingTest { *

    foo
    * baz

    */ - parsed.assertEquals(paragraph("foo\nbaz")) + parsed.assertEquals(paragraph("foo \nbaz")) } @Test @@ -12247,7 +12233,7 @@ class MarkdownProcessorDocumentParsingTest { *

    foo
    * baz

    */ - parsed.assertEquals(paragraph("foo\nbaz")) + parsed.assertEquals(paragraph("foo \nbaz")) } @Test @@ -12266,7 +12252,7 @@ class MarkdownProcessorDocumentParsingTest { *

    foo
    * baz

    */ - parsed.assertEquals(paragraph("foo\nbaz")) + parsed.assertEquals(paragraph("foo \nbaz")) } @Test @@ -12285,7 +12271,7 @@ class MarkdownProcessorDocumentParsingTest { *

    foo
    * bar

    */ - parsed.assertEquals(paragraph("foo\nbar")) + parsed.assertEquals(paragraph("foo \nbar")) } @Test @@ -12304,7 +12290,7 @@ class MarkdownProcessorDocumentParsingTest { *

    foo
    * bar

    */ - parsed.assertEquals(paragraph("foo\nbar")) + parsed.assertEquals(paragraph("foo \nbar")) } @Test @@ -12323,7 +12309,7 @@ class MarkdownProcessorDocumentParsingTest { *

    foo
    * bar

    */ - parsed.assertEquals(paragraph("*foo\nbar*")) + parsed.assertEquals(paragraph("*foo \nbar*")) } @Test @@ -12342,7 +12328,7 @@ class MarkdownProcessorDocumentParsingTest { *

    foo
    * bar

    */ - parsed.assertEquals(paragraph("*foo\nbar*")) + parsed.assertEquals(paragraph("*foo \nbar*")) } @Test diff --git a/markdown/core/src/test/kotlin/org/jetbrains/jewel/markdown/TestUtils.kt b/markdown/core/src/test/kotlin/org/jetbrains/jewel/markdown/TestUtils.kt index 2827bcbd8..25c191520 100644 --- a/markdown/core/src/test/kotlin/org/jetbrains/jewel/markdown/TestUtils.kt +++ b/markdown/core/src/test/kotlin/org/jetbrains/jewel/markdown/TestUtils.kt @@ -1,22 +1,23 @@ package org.jetbrains.jewel.markdown +import org.commonmark.internal.InlineParserContextImpl +import org.commonmark.internal.InlineParserImpl +import org.commonmark.internal.LinkReferenceDefinitions +import org.commonmark.node.Node +import org.commonmark.parser.Parser +import org.commonmark.parser.SourceLine +import org.commonmark.parser.SourceLines +import org.commonmark.renderer.html.HtmlRenderer import org.intellij.lang.annotations.Language import org.jetbrains.jewel.markdown.MarkdownBlock.BlockQuote import org.jetbrains.jewel.markdown.MarkdownBlock.CodeBlock import org.jetbrains.jewel.markdown.MarkdownBlock.CodeBlock.FencedCodeBlock import org.jetbrains.jewel.markdown.MarkdownBlock.CodeBlock.IndentedCodeBlock import org.jetbrains.jewel.markdown.MarkdownBlock.Heading -import org.jetbrains.jewel.markdown.MarkdownBlock.Heading.H1 -import org.jetbrains.jewel.markdown.MarkdownBlock.Heading.H2 -import org.jetbrains.jewel.markdown.MarkdownBlock.Heading.H3 -import org.jetbrains.jewel.markdown.MarkdownBlock.Heading.H4 -import org.jetbrains.jewel.markdown.MarkdownBlock.Heading.H5 -import org.jetbrains.jewel.markdown.MarkdownBlock.Heading.H6 import org.jetbrains.jewel.markdown.MarkdownBlock.HtmlBlock -import org.jetbrains.jewel.markdown.MarkdownBlock.Image import org.jetbrains.jewel.markdown.MarkdownBlock.ListBlock +import org.jetbrains.jewel.markdown.MarkdownBlock.ListBlock.BulletList import org.jetbrains.jewel.markdown.MarkdownBlock.ListBlock.OrderedList -import org.jetbrains.jewel.markdown.MarkdownBlock.ListBlock.UnorderedList import org.jetbrains.jewel.markdown.MarkdownBlock.ListItem import org.jetbrains.jewel.markdown.MarkdownBlock.Paragraph import org.jetbrains.jewel.markdown.MarkdownBlock.ThematicBreak @@ -76,7 +77,6 @@ private fun MarkdownBlock.findDifferenceWith( is FencedCodeBlock -> diffFencedCodeBlock(this, expected, indent) is IndentedCodeBlock -> diffIndentedCodeBlock(this, expected, indent) is Heading -> diffHeading(this, expected, indent) - is Image -> diffImage(this, expected, indent) is ListBlock -> diffList(this, expected, indentSize, indent) is ListItem -> content.findDifferences((expected as ListItem).content, indentSize) is ThematicBreak -> emptyList() // They can only differ in their node @@ -84,12 +84,23 @@ private fun MarkdownBlock.findDifferenceWith( } } +private var htmlRenderer = HtmlRenderer.builder().build() + +fun BlockWithInlineMarkdown.toHtml() = buildString { + for (node in this@toHtml.inlineContent) { + // new lines are rendered as spaces in tests + append(htmlRenderer.render(node.value).replace("\n", " ")) + } +} + private fun diffParagraph(actual: Paragraph, expected: MarkdownBlock, indent: String) = buildList { - if (actual.inlineContent != (expected as Paragraph).inlineContent) { + val actualInlineHtml = actual.toHtml() + val expectedInlineHtml = (expected as Paragraph).toHtml() + if (actualInlineHtml != expectedInlineHtml) { add( "$indent * Paragraph raw content mismatch.\n\n" + - "$indent Actual: ${actual.inlineContent}\n" + - "$indent Expected: ${expected.inlineContent}\n", + "$indent Actual: $actualInlineHtml\n" + + "$indent Expected: $expectedInlineHtml\n", ) } } @@ -135,29 +146,13 @@ private fun diffIndentedCodeBlock(actual: CodeBlock, expected: MarkdownBlock, in } private fun diffHeading(actual: Heading, expected: MarkdownBlock, indent: String) = buildList { - if (actual.inlineContent != (expected as Heading).inlineContent) { + val actualInlineHtml = actual.toHtml() + val expectedInlineHtml = (expected as Heading).toHtml() + if (actualInlineHtml != expectedInlineHtml) { add( "$indent * Heading raw content mismatch.\n\n" + - "$indent Actual: ${actual.inlineContent}\n" + - "$indent Expected: ${expected.inlineContent}", - ) - } -} - -private fun diffImage(actual: Image, expected: MarkdownBlock, indent: String) = buildList { - if (actual.url != (expected as Image).url) { - add( - "$indent * Image URL mismatch.\n\n" + - "$indent Actual: ${actual.url}\n" + - "$indent Expected: ${expected.url}", - ) - } - - if (actual.altString != expected.altString) { - add( - "$indent * Image alt string mismatch.\n\n" + - "$indent Actual: ${actual.altString}\n" + - "$indent Expected: ${expected.altString}", + "$indent Actual: $actualInlineHtml\n" + + "$indent Expected: $expectedInlineHtml", ) } } @@ -193,8 +188,8 @@ private fun diffList(actual: ListBlock, expected: MarkdownBlock, indentSize: Int } } - is UnorderedList -> { - if (actual.bulletMarker != (expected as UnorderedList).bulletMarker) { + is BulletList -> { + if (actual.bulletMarker != (expected as BulletList).bulletMarker) { add( "$indent * List bulletMarker mismatch.\n\n" + "$indent Actual: ${actual.bulletMarker}\n" + @@ -205,7 +200,42 @@ private fun diffList(actual: ListBlock, expected: MarkdownBlock, indentSize: Int } } -fun paragraph(@Language("Markdown") content: String) = Paragraph(InlineMarkdown(content)) +private val parser = Parser.builder().build() + +private fun Node.children() = buildList { + var child = firstChild + while (child != null) { + add(child) + child = child.next + } +} + +/** skip root Document and Paragraph nodes */ +private fun inlineMarkdowns(content: String): List { + val document = parser.parse(content).firstChild ?: return emptyList() + return if (document.firstChild is org.commonmark.node.Paragraph) { + document.firstChild + } else { + document + }.children().map { x -> x.toInlineNode() } +} + +private val inlineParser = InlineParserImpl(InlineParserContextImpl(emptyList(), LinkReferenceDefinitions())) + +fun paragraph(@Language("Markdown") content: String): Paragraph = Paragraph( + object : org.commonmark.node.CustomBlock() {}.let { block -> + inlineParser.parse(SourceLines.of(content.lines().map { SourceLine.of(it, null) }), block) + block + }.children().map { x -> x.toInlineNode() }, +) + +fun heading(level: Int, @Language("Markdown") content: String) = Heading( + object : org.commonmark.node.CustomBlock() {}.let { block -> + inlineParser.parse(SourceLines.of(SourceLine.of(content, null)), block) + block + }.children().map { x -> x.toInlineNode() }, + level, +) fun indentedCodeBlock(content: String) = IndentedCodeBlock(content) @@ -217,27 +247,16 @@ fun blockQuote(vararg contents: MarkdownBlock) = BlockQuote(contents.toList()) fun unorderedList( vararg items: ListItem, isTight: Boolean = true, - bulletMarker: Char = '-', -) = UnorderedList(items.toList(), isTight, bulletMarker) + bulletMarker: String = "-", +) = BulletList(items.toList(), isTight, bulletMarker) fun orderedList( vararg items: ListItem, isTight: Boolean = true, startFrom: Int = 1, - delimiter: Char = '.', + delimiter: String = ".", ) = OrderedList(items.toList(), isTight, startFrom, delimiter) fun listItem(vararg items: MarkdownBlock) = ListItem(items.toList()) -fun heading(level: Int, @Language("Markdown") content: String) = - when (level) { - 1 -> H1(InlineMarkdown(content)) - 2 -> H2(InlineMarkdown(content)) - 3 -> H3(InlineMarkdown(content)) - 4 -> H4(InlineMarkdown(content)) - 5 -> H5(InlineMarkdown(content)) - 6 -> H6(InlineMarkdown(content)) - else -> error("Invalid heading level $level") - } - fun htmlBlock(content: String) = HtmlBlock(content) diff --git a/markdown/core/src/test/kotlin/org/jetbrains/jewel/markdown/processing/MarkdownProcessorTest.kt b/markdown/core/src/test/kotlin/org/jetbrains/jewel/markdown/processing/MarkdownProcessorTest.kt new file mode 100644 index 000000000..214c6b168 --- /dev/null +++ b/markdown/core/src/test/kotlin/org/jetbrains/jewel/markdown/processing/MarkdownProcessorTest.kt @@ -0,0 +1,641 @@ +package org.jetbrains.jewel.markdown.processing + +import org.commonmark.node.Block +import org.commonmark.node.Document +import org.commonmark.node.Node +import org.commonmark.parser.IncludeSourceSpans +import org.commonmark.parser.Parser +import org.commonmark.renderer.html.HtmlRenderer +import org.intellij.lang.annotations.Language +import org.junit.Assert.assertArrayEquals +import org.junit.Assert.assertEquals +import org.junit.Assert.assertNotSame +import org.junit.Assert.assertSame +import org.junit.Test + +private val rawMarkdown = """ + Paragraph 0 + # Header 1 + Paragraph 2 + * list item 3-1 + * list item 3-2 + * list item 3-3 + ## Header 4 + Paragraph 5 + continue paragraph 5 + + + ``` + line 6-1 + line 6-2 + ``` + Paragraph 7 + + Paragraph 8 +""".trimIndent() + +class MarkdownProcessorTest { + + private val htmlRenderer = HtmlRenderer.builder().build() + + @Test + fun `first blocks stay the same`() { + val processor = MarkdownProcessor() + val firstRun = processor.processWithQuickEdits(rawMarkdown) + val secondRun = processor.processWithQuickEdits( + """ + Paragraph 0 + # Header 1 + Paragraph 2 + + * list item 3-1 + * list item 3-2 + """.trimIndent(), + ) + assertSame(firstRun[0], secondRun[0]) + assertSame(firstRun[1], secondRun[1]) + assertNotSame(firstRun[2], secondRun[2]) + assertHtmlEquals( + """ +

    Paragraph 0

    +

    Header 1

    +

    Paragraph 2

    +
      +
    • list item 3-1
    • +
    • list item 3-2
    • +
    + + """.trimIndent(), + secondRun, + ) + } + + @Test + fun `first block edited`() { + val processor = MarkdownProcessor() + val firstRun = processor.processWithQuickEdits(rawMarkdown) + val secondRun = processor.processWithQuickEdits( + """ + Paragraph *CHANGE* + # Header 1 + Paragraph 2 + * list item 3-1 + * list item 3-2 + * list item 3-3 + ## Header 4 + Paragraph 5 + continue paragraph 5 + + + ``` + line 6-1 + line 6-2 + ``` + Paragraph 7 + + Paragraph 8 + """.trimIndent(), + ) + assertHtmlEquals( + """ +

    Paragraph CHANGE

    +

    Header 1

    +

    Paragraph 2

    +
      +
    • list item 3-1
    • +
    • list item 3-2
    • +
    • list item 3-3
    • +
    +

    Header 4

    +

    Paragraph 5 + continue paragraph 5

    +
    line 6-1
    +            line 6-2
    +            
    +

    Paragraph 7

    +

    Paragraph 8

    + + """.trimIndent(), + secondRun, + ) + assertNotSame(firstRun[0], secondRun[0]) + assertNotSame(firstRun[1], secondRun[1]) + assertSame(firstRun[2], secondRun[2]) + } + + @Test + fun `last block edited`() { + val processor = MarkdownProcessor() + val firstRun = processor.processWithQuickEdits(rawMarkdown) + val secondRun = processor.processWithQuickEdits( + """ + Paragraph 0 + # Header 1 + Paragraph 2 + * list item 3-1 + * list item 3-2 + * list item 3-3 + ## Header 4 + Paragraph 5 + continue paragraph 5 + + + ``` + line 6-1 + line 6-2 + ``` + Paragraph 7 + + Paragraph *CHANGE* + """.trimIndent(), + ) + assertHtmlEquals( + """ +

    Paragraph 0

    +

    Header 1

    +

    Paragraph 2

    +
      +
    • list item 3-1
    • +
    • list item 3-2
    • +
    • list item 3-3
    • +
    +

    Header 4

    +

    Paragraph 5 + continue paragraph 5

    +
    line 6-1
    +            line 6-2
    +            
    +

    Paragraph 7

    +

    Paragraph CHANGE

    + + """.trimIndent(), + secondRun, + ) + assertSame(firstRun[5], secondRun[5]) + assertSame(firstRun[6], secondRun[6]) + assertNotSame(firstRun[7], secondRun[7]) + assertNotSame(firstRun[8], secondRun[8]) + } + + @Test + fun `middle block edited`() { + val processor = MarkdownProcessor() + val firstRun = processor.processWithQuickEdits(rawMarkdown) + val secondRun = processor.processWithQuickEdits( + """ + Paragraph 0 + # Header 1 + Paragraph 2 + * list item 3-1 + * list item *CHANGE* + * list item 3-3 + ## Header 4 + Paragraph 5 + continue paragraph 5 + + + ``` + line 6-1 + line 6-2 + ``` + Paragraph 7 + + Paragraph 8 + """.trimIndent(), + ) + assertHtmlEquals( + """ +

    Paragraph 0

    +

    Header 1

    +

    Paragraph 2

    +
      +
    • list item 3-1
    • +
    • list item CHANGE
    • +
    • list item 3-3
    • +
    +

    Header 4

    +

    Paragraph 5 + continue paragraph 5

    +
    line 6-1
    +            line 6-2
    +            
    +

    Paragraph 7

    +

    Paragraph 8

    + + """.trimIndent(), + secondRun, + ) + assertSame(firstRun[0], secondRun[0]) + assertSame(firstRun[1], secondRun[1]) + assertNotSame(firstRun[2], secondRun[2]) + assertNotSame(firstRun[3], secondRun[3]) + assertNotSame(firstRun[4], secondRun[4]) + assertSame(firstRun[5], secondRun[5]) + } + + @Test + fun `blocks merged`() { + val processor = MarkdownProcessor() + val firstRun = processor.processWithQuickEdits(rawMarkdown) + val secondRun = processor.processWithQuickEdits( + """ + Paragraph 0 + # Header 1 + Paragraph 2 + * list item 3-1 + * list item 3-2 + * list item 3-3 + ## Header 4 + Paragraph 5 + continue paragraph 5 + + + ``` + line 6-1 + line 6-2 + ``` + Paragraph 7 + Paragraph 8 + """.trimIndent(), + ) + assertHtmlEquals( + """ +

    Paragraph 0

    +

    Header 1

    +

    Paragraph 2

    +
      +
    • list item 3-1
    • +
    • list item 3-2
    • +
    • list item 3-3
    • +
    +

    Header 4

    +

    Paragraph 5 + continue paragraph 5

    +
    line 6-1
    +            line 6-2
    +            
    +

    Paragraph 7 + Paragraph 8

    + + """.trimIndent(), + secondRun, + ) + assertSame(firstRun[5], secondRun[5]) + assertSame(firstRun[6], secondRun[6]) + assertNotSame(firstRun[7], secondRun[7]) + } + + @Test + fun `blocks split`() { + val processor = MarkdownProcessor() + val firstRun = processor.processWithQuickEdits(rawMarkdown) + val secondRun = processor.processWithQuickEdits( + """ + Paragraph 0 + # Header 1 + Paragraph 2 + * list item 3-1 + * list item 3-2 + * list item 3-3 + ## Header 4 + Paragraph 5 + + continue paragraph 5 + ``` + line 6-1 + line 6-2 + ``` + Paragraph 7 + + Paragraph 8 + """.trimIndent(), + ) + assertHtmlEquals( + """ +

    Paragraph 0

    +

    Header 1

    +

    Paragraph 2

    +
      +
    • list item 3-1
    • +
    • list item 3-2
    • +
    • list item 3-3
    • +
    +

    Header 4

    +

    Paragraph 5

    +

    continue paragraph 5

    +
    line 6-1
    +            line 6-2
    +            
    +

    Paragraph 7

    +

    Paragraph 8

    + + """.trimIndent(), + secondRun, + ) + assertSame(firstRun[3], secondRun[3]) + assertNotSame(firstRun[4], secondRun[4]) + assertNotSame(firstRun[5], secondRun[5]) + assertSame(firstRun[7], secondRun[8]) + } + + @Test + fun `blocks deleted`() { + val processor = MarkdownProcessor() + val firstRun = processor.processWithQuickEdits(rawMarkdown) + val secondRun = processor.processWithQuickEdits( + """ + Paragraph 0 + # Header 1 + Paragraph 2 + * list item 3-1 + * list item 3-2 + * list item 3-3 + ``` + line 6-1 + line 6-2 + ``` + Paragraph 7 + + Paragraph 8 + """.trimIndent(), + ) + assertHtmlEquals( + """ +

    Paragraph 0

    +

    Header 1

    +

    Paragraph 2

    +
      +
    • list item 3-1
    • +
    • list item 3-2
    • +
    • list item 3-3
    • +
    +
    line 6-1
    +            line 6-2
    +            
    +

    Paragraph 7

    +

    Paragraph 8

    + + """.trimIndent(), + secondRun, + ) + assertSame(firstRun[2], secondRun[2]) + assertNotSame(firstRun[3], secondRun[3]) + assertNotSame(firstRun[4], secondRun[4]) + assertNotSame(firstRun[6], secondRun[4]) + assertSame(firstRun[7], secondRun[5]) + } + + @Test + fun `blocks added`() { + val processor = MarkdownProcessor() + val firstRun = processor.processWithQuickEdits(rawMarkdown) + val secondDocument = """ + Paragraph 0 + # Header 1 + Paragraph 2 + * list item 3-1 + * list item 3-2 + * list item 3-3 + ## Header 4 + + + *CHANGE* + + Paragraph 5 + continue paragraph 5 + + + ``` + line 6-1 + line 6-2 + ``` + Paragraph 7 + + Paragraph 8 + """.trimIndent() + val secondRun = processor.processWithQuickEdits( + secondDocument, + ) + assertHtmlEquals( + """ +

    Paragraph 0

    +

    Header 1

    +

    Paragraph 2

    +
      +
    • list item 3-1
    • +
    • list item 3-2
    • +
    • list item 3-3
    • +
    +

    Header 4

    +

    CHANGE

    +

    Paragraph 5 + continue paragraph 5

    +
    line 6-1
    +            line 6-2
    +            
    +

    Paragraph 7

    +

    Paragraph 8

    + + """.trimIndent(), + secondRun, + ) + assertSame(firstRun[2], secondRun[2]) + assertSame(firstRun[3], secondRun[3]) + assertNotSame(firstRun[4], secondRun[4]) + assertNotSame(firstRun[5], secondRun[6]) + assertSame(firstRun[6], secondRun[7]) + assertIndexesEqual(secondDocument, processor.getCurrentIndexesInTest()) + } + + @Test + fun `no changes`() { + val processor = MarkdownProcessor() + val firstRun = processor.processWithQuickEdits(rawMarkdown) + val secondRun = processor.processWithQuickEdits(rawMarkdown) + assertHtmlEquals( + """ +

    Paragraph 0

    +

    Header 1

    +

    Paragraph 2

    +
      +
    • list item 3-1
    • +
    • list item 3-2
    • +
    • list item 3-3
    • +
    +

    Header 4

    +

    Paragraph 5 + continue paragraph 5

    +
    line 6-1
    +            line 6-2
    +            
    +

    Paragraph 7

    +

    Paragraph 8

    + + """.trimIndent(), + secondRun, + ) + assertSame(firstRun[0], secondRun[0]) + } + + @Test + fun `empty line added`() { + val processor = MarkdownProcessor() + val firstRun = processor.processWithQuickEdits(rawMarkdown) + val secondRun = processor.processWithQuickEdits("\n" + rawMarkdown) + assertHtmlEquals( + """ +

    Paragraph 0

    +

    Header 1

    +

    Paragraph 2

    +
      +
    • list item 3-1
    • +
    • list item 3-2
    • +
    • list item 3-3
    • +
    +

    Header 4

    +

    Paragraph 5 + continue paragraph 5

    +
    line 6-1
    +            line 6-2
    +            
    +

    Paragraph 7

    +

    Paragraph 8

    + + """.trimIndent(), + secondRun, + ) + assertNotSame(firstRun[0], secondRun[0]) + assertSame(firstRun[1], secondRun[1]) + } + + @Test + fun `chained changes`() { + val processor = MarkdownProcessor() + processor.processWithQuickEdits( + """ + # Header 0 + # Header 1 + # Header 2 + + + + + # Header 3 + # Header 4 + # Header 5 + # Header 6 + # Header 7 + # Header 8 + # Header 9 + + """.trimIndent(), + ) + processor.processWithQuickEdits( + """ + # Header 0 + # Header 1 + some paragraph + + + + + # Header 2 + # Header 3 + # Header 7 + # Header 8 + # Header 9 + + """.trimIndent(), + ) + val forthRun = processor.processWithQuickEdits( + """ + # Header 0 + # Header 1 + + + some paragraph + # Header 2 + # Header 7 + # Header 8 + # Header 9 + + """.trimIndent(), + ) + val fifthDocument = """ + # Header 0 + # Header 1 + + + some paragraph + # Header 2 + # Header 7 + + + - list item 1 + - list item 2 + # Header 8 + # Header 9 + + """.trimIndent() + val fifthRun = processor.processWithQuickEdits( + fifthDocument, + ) + + assertIndexesEqual(fifthDocument, processor.getCurrentIndexesInTest()) + + assertSame(forthRun[0], fifthRun[0]) + assertSame(forthRun[1], fifthRun[1]) + assertSame(forthRun[2], fifthRun[2]) + assertSame(forthRun[3], fifthRun[3]) + assertNotSame(forthRun[4], fifthRun[4]) + assertSame(forthRun[6], fifthRun[7]) + assertHtmlEquals( + """ +

    Header 0

    +

    Header 1

    +

    some paragraph

    +

    Header 2

    +

    Header 7

    +
      +
    • list item 1
    • +
    • list item 2
    • +
    +

    Header 8

    +

    Header 9

    + + """.trimIndent(), + fifthRun, + ) + } + + private fun assertHtmlEquals(@Language("html") text: String, actual: List) { + assertEquals(text, actual.joinToString("") { htmlRenderer.render(it) }) + } +} + +private fun Node.children(): List { + var child = firstChild + return buildList { + while (child != null) { + add(child) + child = child.next + } + } +} + +private fun assertIndexesEqual( + lastProcessedDocument: String, + currentIndexes: List>, +) { + val commonmarkDocument = + Parser.builder().includeSourceSpans(IncludeSourceSpans.BLOCKS).build() + .parse(lastProcessedDocument) as Document + val expected = + (commonmarkDocument).children().map { + it.sourceSpans.first().lineIndex to it.sourceSpans.last().lineIndex + }.toTypedArray() + assertArrayEquals( + expected, + currentIndexes.toTypedArray(), + ) +} diff --git a/markdown/extension/gfm-alerts/api/gfm-alerts.api b/markdown/extension/gfm-alerts/api/gfm-alerts.api index 1ebaa5a29..c292a1850 100644 --- a/markdown/extension/gfm-alerts/api/gfm-alerts.api +++ b/markdown/extension/gfm-alerts/api/gfm-alerts.api @@ -1,4 +1,4 @@ -public abstract interface class org/jetbrains/jewel/markdown/extensions/github/alerts/Alert : org/jetbrains/jewel/markdown/MarkdownBlock$Extension { +public abstract interface class org/jetbrains/jewel/markdown/extensions/github/alerts/Alert : org/jetbrains/jewel/markdown/MarkdownBlock$CustomBlock { public abstract fun getContent ()Ljava/util/List; } @@ -115,8 +115,8 @@ public final class org/jetbrains/jewel/markdown/extensions/github/alerts/Caution public final class org/jetbrains/jewel/markdown/extensions/github/alerts/GitHubAlertBlockRenderer : org/jetbrains/jewel/markdown/extensions/MarkdownBlockRendererExtension { public static final field $stable I public fun (Lorg/jetbrains/jewel/markdown/extensions/github/alerts/AlertStyling;Lorg/jetbrains/jewel/markdown/rendering/MarkdownStyling;)V - public fun canRender (Lorg/jetbrains/jewel/markdown/MarkdownBlock$Extension;)Z - public fun render (Lorg/jetbrains/jewel/markdown/MarkdownBlock$Extension;Lorg/jetbrains/jewel/markdown/rendering/MarkdownBlockRenderer;Lorg/jetbrains/jewel/markdown/rendering/InlineMarkdownRenderer;Landroidx/compose/runtime/Composer;I)V + public fun canRender (Lorg/jetbrains/jewel/markdown/MarkdownBlock$CustomBlock;)Z + public fun render (Lorg/jetbrains/jewel/markdown/MarkdownBlock$CustomBlock;Lorg/jetbrains/jewel/markdown/rendering/MarkdownBlockRenderer;Lorg/jetbrains/jewel/markdown/rendering/InlineMarkdownRenderer;Landroidx/compose/runtime/Composer;I)V } public final class org/jetbrains/jewel/markdown/extensions/github/alerts/GitHubAlertProcessorExtension : org/jetbrains/jewel/markdown/extensions/MarkdownProcessorExtension { diff --git a/markdown/extension/gfm-alerts/src/main/kotlin/org/jetbrains/jewel/markdown/extensions/github/alerts/Alert.kt b/markdown/extension/gfm-alerts/src/main/kotlin/org/jetbrains/jewel/markdown/extensions/github/alerts/Alert.kt index 4a5e7f7e5..79247d6e3 100644 --- a/markdown/extension/gfm-alerts/src/main/kotlin/org/jetbrains/jewel/markdown/extensions/github/alerts/Alert.kt +++ b/markdown/extension/gfm-alerts/src/main/kotlin/org/jetbrains/jewel/markdown/extensions/github/alerts/Alert.kt @@ -2,7 +2,7 @@ package org.jetbrains.jewel.markdown.extensions.github.alerts import org.jetbrains.jewel.markdown.MarkdownBlock -public sealed interface Alert : MarkdownBlock.Extension { +public sealed interface Alert : MarkdownBlock.CustomBlock { public val content: List diff --git a/markdown/extension/gfm-alerts/src/main/kotlin/org/jetbrains/jewel/markdown/extensions/github/alerts/GitHubAlertBlockRenderer.kt b/markdown/extension/gfm-alerts/src/main/kotlin/org/jetbrains/jewel/markdown/extensions/github/alerts/GitHubAlertBlockRenderer.kt index dd3c34956..5ffdddb5b 100644 --- a/markdown/extension/gfm-alerts/src/main/kotlin/org/jetbrains/jewel/markdown/extensions/github/alerts/GitHubAlertBlockRenderer.kt +++ b/markdown/extension/gfm-alerts/src/main/kotlin/org/jetbrains/jewel/markdown/extensions/github/alerts/GitHubAlertBlockRenderer.kt @@ -19,7 +19,7 @@ import androidx.compose.ui.input.pointer.pointerHoverIcon import androidx.compose.ui.unit.LayoutDirection.Ltr import androidx.compose.ui.unit.dp import org.jetbrains.jewel.foundation.theme.LocalContentColor -import org.jetbrains.jewel.markdown.MarkdownBlock.Extension +import org.jetbrains.jewel.markdown.MarkdownBlock.CustomBlock import org.jetbrains.jewel.markdown.extensions.MarkdownBlockRendererExtension import org.jetbrains.jewel.markdown.extensions.github.alerts.Alert.Caution import org.jetbrains.jewel.markdown.extensions.github.alerts.Alert.Important @@ -37,12 +37,12 @@ public class GitHubAlertBlockRenderer( private val rootStyling: MarkdownStyling, ) : MarkdownBlockRendererExtension { - override fun canRender(block: Extension): Boolean = + override fun canRender(block: CustomBlock): Boolean = block is Alert @Composable override fun render( - block: Extension, + block: CustomBlock, blockRenderer: MarkdownBlockRenderer, inlineRenderer: InlineMarkdownRenderer, ) { diff --git a/markdown/extension/gfm-alerts/src/main/kotlin/org/jetbrains/jewel/markdown/extensions/github/alerts/GitHubAlertProcessorExtension.kt b/markdown/extension/gfm-alerts/src/main/kotlin/org/jetbrains/jewel/markdown/extensions/github/alerts/GitHubAlertProcessorExtension.kt index 31a0a4bda..44b672306 100644 --- a/markdown/extension/gfm-alerts/src/main/kotlin/org/jetbrains/jewel/markdown/extensions/github/alerts/GitHubAlertProcessorExtension.kt +++ b/markdown/extension/gfm-alerts/src/main/kotlin/org/jetbrains/jewel/markdown/extensions/github/alerts/GitHubAlertProcessorExtension.kt @@ -40,7 +40,7 @@ public object GitHubAlertProcessorExtension : MarkdownProcessorExtension { override fun canProcess(block: CustomBlock): Boolean = block is AlertBlock - override fun processMarkdownBlock(block: CustomBlock, processor: MarkdownProcessor): MarkdownBlock.Extension? { + override fun processMarkdownBlock(block: CustomBlock, processor: MarkdownProcessor): MarkdownBlock.CustomBlock? { val children = processor.processChildren(block) if (children.isEmpty()) return null