4949public class AlertsExtension implements Parser .ParserExtension , HtmlRenderer .HtmlRendererExtension ,
5050 MarkdownRenderer .MarkdownRendererExtension {
5151
52- static final Set <String > STANDARD_TYPES = Set .of ("NOTE" , "TIP" , "IMPORTANT" , "WARNING" , "CAUTION" );
52+ /**
53+ * The standard GitHub Flavored Markdown (GFM) types that the extension
54+ * enables by default. They can be removed individually with
55+ * {@link Builder#removeTypes(String...)}.
56+ */
57+ public static final Map <String , String > STANDARD_TYPES = Map .ofEntries (
58+ Map .entry ("NOTE" , "Note" ),
59+ Map .entry ("TIP" , "Tip" ),
60+ Map .entry ("IMPORTANT" , "Important" ),
61+ Map .entry ("WARNING" , "Warning" ),
62+ Map .entry ("CAUTION" , "Caution" )
63+ );
5364
54- private final Map <String , String > customTypes ;
65+ /**
66+ * A map of alert marker ({@code [!TYPE]}) to the default title for that marker.
67+ */
68+ private final Map <String , String > allowedTypes ;
5569 private final boolean customTitlesAllowed ;
5670 private final boolean nestedAlertsAllowed ;
5771
5872 private AlertsExtension (Builder builder ) {
59- this .customTypes = new HashMap <>(builder .customTypes );
73+ this .allowedTypes = new HashMap <>(builder .allowedTypes );
6074 this .customTitlesAllowed = builder .customTitlesAllowed ;
6175 this .nestedAlertsAllowed = builder .nestedAlertsAllowed ;
6276 }
@@ -71,15 +85,14 @@ public static Builder builder() {
7185
7286 @ Override
7387 public void extend (Parser .Builder parserBuilder ) {
74- var allowedTypes = new HashSet <>(STANDARD_TYPES );
75- allowedTypes .addAll (customTypes .keySet ());
88+ var allowedTypesSet = new HashSet <>(allowedTypes .keySet ());
7689 parserBuilder .customBlockParserFactory (
77- new AlertBlockParser .Factory (allowedTypes , customTitlesAllowed , nestedAlertsAllowed ));
90+ new AlertBlockParser .Factory (allowedTypesSet , customTitlesAllowed , nestedAlertsAllowed ));
7891 }
7992
8093 @ Override
8194 public void extend (HtmlRenderer .Builder rendererBuilder ) {
82- rendererBuilder .nodeRendererFactory (context -> new AlertHtmlNodeRenderer (context , customTypes ));
95+ rendererBuilder .nodeRendererFactory (context -> new AlertHtmlNodeRenderer (context , allowedTypes ));
8396 }
8497
8598 @ Override
@@ -101,18 +114,18 @@ public Set<Character> getSpecialCharacters() {
101114 * Builder for configuring the alerts extension.
102115 */
103116 public static class Builder {
104- private final Map <String , String > customTypes = new HashMap <>();
117+ private final Map <String , String > allowedTypes = new HashMap <>(STANDARD_TYPES );
105118 private boolean customTitlesAllowed = false ;
106119 private boolean nestedAlertsAllowed = false ;
107120
108121 /**
109- * Adds a custom alert type with a display title.
122+ * Adds a custom alert type with a default title.
110123 * <p>
111- * This can also be used to override the display title of standard GFM types
124+ * This can also be used to override the default title of standard GFM types
112125 * (e.g., for localization).
113126 *
114127 * @param type the alert type (must be uppercase)
115- * @param title the display title for this alert type
128+ * @param title the default title for this alert type
116129 * @return {@code this}
117130 */
118131 public Builder addCustomType (String type , String title ) {
@@ -125,7 +138,34 @@ public Builder addCustomType(String type, String title) {
125138 if (!type .equals (type .toUpperCase (Locale .ROOT ))) {
126139 throw new IllegalArgumentException ("Type must be uppercase: " + type );
127140 }
128- customTypes .put (type , title );
141+ allowedTypes .put (type , title );
142+ return this ;
143+ }
144+
145+ /**
146+ * Removes alert types from the allowed list.
147+ *
148+ * @param types the alert types to remove (must be uppercase)
149+ * @return {@code this}
150+ * @see AlertsExtension#STANDARD_TYPES
151+ */
152+ public Builder removeTypes (String ... types ) {
153+ if (types == null ) {
154+ throw new IllegalArgumentException ("Types must not be null" );
155+ }
156+
157+ for (String type : types ) {
158+ if (type == null || type .isEmpty ()) {
159+ throw new IllegalArgumentException ("Each type must not be null or empty" );
160+ }
161+
162+ if (!type .equals (type .toUpperCase (Locale .ROOT ))) {
163+ throw new IllegalArgumentException ("Type must be uppercase: " + type );
164+ }
165+
166+ allowedTypes .remove (type );
167+ }
168+
129169 return this ;
130170 }
131171
0 commit comments