66import org .commonmark .ext .gfm .alerts .internal .AlertMarkdownNodeRenderer ;
77import org .commonmark .parser .Parser ;
88import org .commonmark .renderer .NodeRenderer ;
9+ import org .commonmark .renderer .html .HtmlNodeRendererContext ;
10+ import org .commonmark .renderer .html .HtmlNodeRendererFactory ;
911import org .commonmark .renderer .html .HtmlRenderer ;
1012import org .commonmark .renderer .markdown .MarkdownNodeRendererContext ;
1113import org .commonmark .renderer .markdown .MarkdownNodeRendererFactory ;
4951public class AlertsExtension implements Parser .ParserExtension , HtmlRenderer .HtmlRendererExtension ,
5052 MarkdownRenderer .MarkdownRendererExtension {
5153
52- static final Set <String > STANDARD_TYPES = Set .of ("NOTE" , "TIP" , "IMPORTANT" , "WARNING" , "CAUTION" );
54+ /**
55+ * The standard GitHub Flavored Markdown (GFM) types that the extension
56+ * enables by default. They can be removed individually with
57+ * {@link Builder#removeTypes(String...)}.
58+ */
59+ public static final Map <String , String > STANDARD_TYPES = Map .ofEntries (
60+ Map .entry ("NOTE" , "Note" ),
61+ Map .entry ("TIP" , "Tip" ),
62+ Map .entry ("IMPORTANT" , "Important" ),
63+ Map .entry ("WARNING" , "Warning" ),
64+ Map .entry ("CAUTION" , "Caution" )
65+ );
5366
54- private final Map <String , String > customTypes ;
67+ /**
68+ * A map of alert marker ({@code [!TYPE]}) to the default title for that marker.
69+ */
70+ private final Map <String , String > allowedTypes ;
5571 private final boolean customTitlesAllowed ;
5672 private final boolean nestedAlertsAllowed ;
5773
5874 private AlertsExtension (Builder builder ) {
59- this .customTypes = new HashMap <>(builder .customTypes );
75+ this .allowedTypes = new HashMap <>(builder .allowedTypes );
6076 this .customTitlesAllowed = builder .customTitlesAllowed ;
6177 this .nestedAlertsAllowed = builder .nestedAlertsAllowed ;
6278 }
@@ -71,15 +87,14 @@ public static Builder builder() {
7187
7288 @ Override
7389 public void extend (Parser .Builder parserBuilder ) {
74- var allowedTypes = new HashSet <>(STANDARD_TYPES );
75- allowedTypes .addAll (customTypes .keySet ());
90+ var allowedTypesSet = new HashSet <>(allowedTypes .keySet ());
7691 parserBuilder .customBlockParserFactory (
77- new AlertBlockParser .Factory (allowedTypes , customTitlesAllowed , nestedAlertsAllowed ));
92+ new AlertBlockParser .Factory (allowedTypesSet , customTitlesAllowed , nestedAlertsAllowed ));
7893 }
7994
8095 @ Override
8196 public void extend (HtmlRenderer .Builder rendererBuilder ) {
82- rendererBuilder .nodeRendererFactory (context -> new AlertHtmlNodeRenderer (context , customTypes ));
97+ rendererBuilder .nodeRendererFactory (context -> new AlertHtmlNodeRenderer (context , allowedTypes ));
8398 }
8499
85100 @ Override
@@ -101,18 +116,18 @@ public Set<Character> getSpecialCharacters() {
101116 * Builder for configuring the alerts extension.
102117 */
103118 public static class Builder {
104- private final Map <String , String > customTypes = new HashMap <>();
119+ private final Map <String , String > allowedTypes = new HashMap <>(STANDARD_TYPES );
105120 private boolean customTitlesAllowed = false ;
106121 private boolean nestedAlertsAllowed = false ;
107122
108123 /**
109- * Adds a custom alert type with a display title.
124+ * Adds a custom alert type with a default title.
110125 * <p>
111- * This can also be used to override the display title of standard GFM types
126+ * This can also be used to override the default title of standard GFM types
112127 * (e.g., for localization).
113128 *
114129 * @param type the alert type (must be uppercase)
115- * @param title the display title for this alert type
130+ * @param title the default title for this alert type
116131 * @return {@code this}
117132 */
118133 public Builder addCustomType (String type , String title ) {
@@ -125,7 +140,34 @@ public Builder addCustomType(String type, String title) {
125140 if (!type .equals (type .toUpperCase (Locale .ROOT ))) {
126141 throw new IllegalArgumentException ("Type must be uppercase: " + type );
127142 }
128- customTypes .put (type , title );
143+ allowedTypes .put (type , title );
144+ return this ;
145+ }
146+
147+ /**
148+ * Removes alert types from the allowed list.
149+ *
150+ * @param types the alert types to remove (must be uppercase)
151+ * @return {@code this}
152+ * @see AlertsExtension#STANDARD_TYPES
153+ */
154+ public Builder removeTypes (String ... types ) {
155+ if (types == null ) {
156+ throw new IllegalArgumentException ("Types must not be null" );
157+ }
158+
159+ for (String type : types ) {
160+ if (type == null || type .isEmpty ()) {
161+ throw new IllegalArgumentException ("Each type must not be null or empty" );
162+ }
163+
164+ if (!type .equals (type .toUpperCase (Locale .ROOT ))) {
165+ throw new IllegalArgumentException ("Type must be uppercase: " + type );
166+ }
167+
168+ allowedTypes .remove (type );
169+ }
170+
129171 return this ;
130172 }
131173
0 commit comments