Skip to content

Commit 3ba29d4

Browse files
committed
Allow Custom Alert Titles
1 parent 22d6637 commit 3ba29d4

13 files changed

Lines changed: 678 additions & 138 deletions

File tree

‎CHANGELOG.md‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ with the exception that 0.x versions can break between minor versions.
1414
### Added
1515
- New extension for alerts (aka callouts/admonitions)
1616
- Syntax:
17-
```
17+
```markdown
1818
> [!NOTE]
1919
> The text of the note.
2020
```
@@ -102,9 +102,9 @@ with the exception that 0.x versions can break between minor versions.
102102
### Added
103103
- New extension for footnotes!
104104
- Syntax:
105-
```
105+
```markdown
106106
Main text[^1]
107-
107+
108108
[^1]: Additional text in a footnote
109109
```
110110
- Inline footnotes like `^[inline footnote]` are also supported when enabled
@@ -269,7 +269,7 @@ with the exception that 0.x versions can break between minor versions.
269269
- Use class `ImageAttributesExtension` in artifact `commonmark-ext-image-attributes`
270270
- Extension for task lists (GitHub-style), thanks @dohertyfjatl
271271
- Syntax:
272-
```
272+
```markdown
273273
- [x] task #1
274274
- [ ] task #2
275275
```

‎commonmark-ext-gfm-alerts/README.md‎

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Enables highlighting important information using blockquote syntax with five sta
66

77
## Usage
88

9-
#### Markdown Syntax
9+
### Markdown Syntax
1010

1111
```markdown
1212
> [!NOTE]
@@ -16,15 +16,15 @@ Enables highlighting important information using blockquote syntax with five sta
1616
> Critical information
1717
```
1818

19-
#### Standard GFM Types
19+
### Standard GFM Types
2020

2121
```java
2222
var extension = AlertsExtension.create();
2323
var parser = Parser.builder().extensions(List.of(extension)).build();
2424
var renderer = HtmlRenderer.builder().extensions(List.of(extension)).build();
2525
```
2626

27-
#### Custom Alert Types
27+
### Custom Alert Types
2828

2929
Add custom types beyond the five standard GFM types:
3030

@@ -36,7 +36,24 @@ var extension = AlertsExtension.builder()
3636

3737
Custom types must be UPPERCASE. Standard type titles can also be overridden for localization.
3838

39-
#### Styling
39+
### Custom Alert Titles
40+
41+
Allow authors to provide custom titles per alert by adding text after the alert
42+
marker on the same line:
43+
44+
```java
45+
var extension = AlertsExtension.builder().allowCustomTitles().build();
46+
```
47+
48+
```markdown
49+
> [!NOTE] Keep in mind
50+
> Useful information
51+
52+
> [!WARNING] Be **very** careful
53+
> Critical information
54+
```
55+
56+
### Styling
4057

4158
Alerts render as `<div>` elements with CSS classes:
4259

@@ -51,9 +68,9 @@ Basic CSS example:
5168

5269
```css
5370
.markdown-alert {
54-
padding: 0.5rem 1rem;
55-
margin-bottom: 1rem;
56-
border-left: 4px solid;
71+
padding: 0.5rem 1rem;
72+
margin-bottom: 1rem;
73+
border-left: 4px solid;
5774
}
5875

5976
.markdown-alert-note { border-color: #0969da; background-color: #ddf4ff; }

‎commonmark-ext-gfm-alerts/src/main/java/org/commonmark/ext/gfm/alerts/Alert.java‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
/**
66
* Alert block for highlighting important information using {@code [!TYPE]} syntax.
7+
*
8+
* @see AlertTitle
79
*/
810
public class Alert extends CustomBlock {
911

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package org.commonmark.ext.gfm.alerts;
2+
3+
import org.commonmark.node.CustomNode;
4+
5+
/**
6+
* Inline content container for the optional custom title of an {@link Alert}.
7+
*
8+
* <p>
9+
* When present, an {@code AlertTitle} is always the first child of an {@link Alert}.
10+
* Its own children are the parsed inline nodes of the title (i.e., the text after
11+
* the {@code [!TYPE]} marker on the same line). For example, in
12+
*
13+
* <pre><code>
14+
* &gt; [!NOTE] Custom _title_
15+
* &gt; Body text
16+
* </code></pre>
17+
*
18+
* the {@code AlertTitle} contains a {@code Text} node ({@code "Custom "}) followed
19+
* by an {@code Emphasis} node wrapping {@code "title"}.
20+
*
21+
* @see AlertsExtension.Builder#allowCustomTitles()
22+
* @see AlertsExtension.Builder#disallowCustomTitles()
23+
*/
24+
public class AlertTitle extends CustomNode {
25+
}

‎commonmark-ext-gfm-alerts/src/main/java/org/commonmark/ext/gfm/alerts/AlertsExtension.java‎

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package org.commonmark.ext.gfm.alerts;
22

33
import org.commonmark.Extension;
4-
import org.commonmark.ext.gfm.alerts.internal.AlertPostProcessor;
4+
import org.commonmark.ext.gfm.alerts.internal.AlertBlockParser;
55
import org.commonmark.ext.gfm.alerts.internal.AlertHtmlNodeRenderer;
66
import org.commonmark.ext.gfm.alerts.internal.AlertMarkdownNodeRenderer;
77
import org.commonmark.parser.Parser;
@@ -33,9 +33,13 @@ public class AlertsExtension implements Parser.ParserExtension, HtmlRenderer.Htm
3333
static final Set<String> STANDARD_TYPES = Set.of("NOTE", "TIP", "IMPORTANT", "WARNING", "CAUTION");
3434

3535
private final Map<String, String> customTypes;
36+
private final boolean customTitlesAllowed;
37+
private final boolean nestedAlertsAllowed;
3638

3739
private AlertsExtension(Builder builder) {
3840
this.customTypes = new HashMap<>(builder.customTypes);
41+
this.customTitlesAllowed = builder.customTitlesAllowed;
42+
this.nestedAlertsAllowed = builder.nestedAlertsAllowed;
3943
}
4044

4145
public static Extension create() {
@@ -50,7 +54,8 @@ public static Builder builder() {
5054
public void extend(Parser.Builder parserBuilder) {
5155
var allowedTypes = new HashSet<>(STANDARD_TYPES);
5256
allowedTypes.addAll(customTypes.keySet());
53-
parserBuilder.postProcessor(new AlertPostProcessor(allowedTypes));
57+
parserBuilder.customBlockParserFactory(
58+
new AlertBlockParser.Factory(allowedTypes, customTitlesAllowed, nestedAlertsAllowed));
5459
}
5560

5661
@Override
@@ -83,6 +88,8 @@ public Set<Character> getSpecialCharacters() {
8388
*/
8489
public static class Builder {
8590
private final Map<String, String> customTypes = new HashMap<>();
91+
private boolean customTitlesAllowed = false;
92+
private boolean nestedAlertsAllowed = false;
8693

8794
/**
8895
* Adds a custom alert type with a display title.
@@ -108,6 +115,46 @@ public Builder addCustomType(String type, String title) {
108115
return this;
109116
}
110117

118+
/**
119+
* Allows custom titles on alerts. See {@link AlertTitle} for more information.
120+
* @return {@code this}
121+
*/
122+
public Builder allowCustomTitles() {
123+
customTitlesAllowed = true;
124+
return this;
125+
}
126+
127+
/**
128+
* Disallows custom titles on alerts. See {@link AlertTitle} for more information.
129+
* @return {@code this}
130+
*/
131+
public Builder disallowCustomTitles() {
132+
customTitlesAllowed = false;
133+
return this;
134+
}
135+
136+
/**
137+
* Allows alerts to be parsed within blocks other than {@code Document} (the root).
138+
* <p>
139+
* Note that even with this enabled, {@link Parser.Builder#maxOpenBlockParsers(int)}
140+
* will be respected.
141+
* @return {@code this}
142+
*/
143+
public Builder allowNestedAlerts() {
144+
nestedAlertsAllowed = true;
145+
return this;
146+
}
147+
148+
/**
149+
* Prevents alerts from being parsed within blocks other than {@code Document}
150+
* (the root). If they appear, they will be parsed as regular {@code BlockQuote}s.
151+
* @return {@code this}
152+
*/
153+
public Builder disallowNestedAlerts() {
154+
nestedAlertsAllowed = false;
155+
return this;
156+
}
157+
111158
/**
112159
* @return a configured {@link Extension}
113160
*/

0 commit comments

Comments
 (0)