Skip to content

Commit f2fad1c

Browse files
committed
Add support for alerts extension
1 parent da4e454 commit f2fad1c

File tree

6 files changed

+118
-4
lines changed

6 files changed

+118
-4
lines changed

README.md

+2
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,8 @@ Commonmarker.to_html('"Hi *there*"', options: {
209209
| `underline` | Enables the underline extension. | `false` |
210210
| `spoiler` | Enables the spoiler extension. | `false` |
211211
| `greentext` | Enables the greentext extension. | `false` |
212+
| `subscript` | Enables the subscript extension. | `false` |
213+
| `alerts` | Enables the alerts extension. | `false` |
212214

213215
For more information on these options, see [the comrak documentation](https://github.com/kivikakk/comrak#usage).
214216

ext/commonmarker/src/node.rs

+46-4
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
use comrak::arena_tree::Node as ComrakNode;
22
use comrak::nodes::{
3-
Ast as ComrakAst, AstNode as ComrakAstNode, ListDelimType, ListType, NodeCode, NodeCodeBlock,
4-
NodeDescriptionItem, NodeFootnoteDefinition, NodeFootnoteReference, NodeHeading, NodeHtmlBlock,
5-
NodeLink, NodeList, NodeMath, NodeMultilineBlockQuote, NodeShortCode, NodeTable,
6-
NodeValue as ComrakNodeValue, NodeWikiLink, TableAlignment,
3+
AlertType, Ast as ComrakAst, AstNode as ComrakAstNode, ListDelimType, ListType, NodeAlert,
4+
NodeCode, NodeCodeBlock, NodeDescriptionItem, NodeFootnoteDefinition, NodeFootnoteReference,
5+
NodeHeading, NodeHtmlBlock, NodeLink, NodeList, NodeMath, NodeMultilineBlockQuote,
6+
NodeShortCode, NodeTable, NodeValue as ComrakNodeValue, NodeWikiLink, TableAlignment,
77
};
88
use magnus::RArray;
99
use magnus::{function, method, scan_args, Module, Object, RHash, RModule, Symbol, Value};
@@ -473,6 +473,47 @@ impl CommonmarkerNode {
473473
ComrakNodeValue::WikiLink(NodeWikiLink { url })
474474
}
475475

476+
"alert" => {
477+
let kwargs = scan_args::get_kwargs::<
478+
_,
479+
(Symbol,),
480+
(Option<String>, Option<bool>, Option<usize>, Option<usize>),
481+
(),
482+
>(
483+
args.keywords,
484+
&["type"],
485+
&["title", "multiline", "fence_length", "fence_offset"],
486+
)?;
487+
488+
let (alert_name,) = kwargs.required;
489+
let (title, multiline, fence_length, fence_offset) = kwargs.optional;
490+
491+
let alert_type = match alert_name.to_string().as_str() {
492+
"note" => AlertType::Note,
493+
"tip" => AlertType::Tip,
494+
"important" => AlertType::Important,
495+
"warning" => AlertType::Warning,
496+
_ => {
497+
return Err(magnus::Error::new(
498+
magnus::exception::arg_error(),
499+
"alert type must be `note`, `tip`, `important`, or `warning`",
500+
));
501+
}
502+
};
503+
504+
ComrakNodeValue::Alert(NodeAlert {
505+
alert_type,
506+
// Overridden title. If None, then use the default title.
507+
title,
508+
// Originated from a multiline blockquote.
509+
multiline: multiline.unwrap_or(false),
510+
// The length of the fence (multiline only).
511+
fence_length: fence_length.unwrap_or(0),
512+
// The indentation level of the fence marker (multiline only)
513+
fence_offset: fence_offset.unwrap_or(0),
514+
})
515+
}
516+
476517
_ => panic!("unknown node type {}", node_type),
477518
};
478519

@@ -565,6 +606,7 @@ impl CommonmarkerNode {
565606
ComrakNodeValue::Subscript => Symbol::new("subscript"),
566607
ComrakNodeValue::SpoileredText => Symbol::new("spoilered_text"),
567608
ComrakNodeValue::EscapedTag(_) => Symbol::new("escaped_tag"),
609+
ComrakNodeValue::Alert(..) => Symbol::new("alert"),
568610
}
569611
}
570612

ext/commonmarker/src/options.rs

+4
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ const EXTENSION_UNDERLINE: &str = "underline";
117117
const EXTENSION_SPOILER: &str = "spoiler";
118118
const EXTENSION_GREENTEXT: &str = "greentext";
119119
const EXTENSION_SUBSCRIPT: &str = "subscript";
120+
const EXTENSION_ALERTS: &str = "alerts";
120121

121122
fn iterate_extension_options(comrak_options: &mut ComrakOptions, options_hash: RHash) {
122123
options_hash
@@ -189,6 +190,9 @@ fn iterate_extension_options(comrak_options: &mut ComrakOptions, options_hash: R
189190
Ok(Cow::Borrowed(EXTENSION_SUBSCRIPT)) => {
190191
comrak_options.extension.subscript = TryConvert::try_convert(value)?;
191192
}
193+
Ok(Cow::Borrowed(EXTENSION_ALERTS)) => {
194+
comrak_options.extension.alerts = TryConvert::try_convert(value)?;
195+
}
192196
_ => {}
193197
}
194198
Ok(ForEach::Continue)

lib/commonmarker/config.rb

+1
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ module Config
4646
spoiler: false,
4747
greentext: false,
4848
subscript: false,
49+
alerts: false,
4950
}.freeze,
5051
format: [:html].freeze,
5152
}.freeze

test/alert_test.rb

+64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# frozen_string_literal: true
2+
3+
require "test_helper"
4+
5+
class FrontmatterTest < Minitest::Test
6+
def test_renders_alert_notes
7+
md = "> [!note]\n> Something of note"
8+
9+
expected = <<~HTML
10+
<blockquote>
11+
<p>[!note]<br />
12+
Something of note</p>
13+
</blockquote>
14+
HTML
15+
16+
# without extension
17+
assert_equal(expected, Commonmarker.to_html(md))
18+
19+
expected = <<~HTML
20+
<div class="alert alert-note">
21+
<p class="alert-title">Note</p>
22+
<p>Something of note</p>
23+
</div>
24+
HTML
25+
26+
assert_equal(expected, Commonmarker.to_html(md, options: { extension: { alerts: true } }))
27+
end
28+
29+
def test_renders_alert_tip
30+
md = "> [!TIP]\n> Something of tip"
31+
32+
expected = <<~HTML
33+
<blockquote>
34+
<p>[!TIP]<br />
35+
Something of tip</p>
36+
</blockquote>
37+
HTML
38+
39+
# without extension
40+
assert_equal(expected, Commonmarker.to_html(md))
41+
42+
expected = <<~HTML
43+
<div class="alert alert-tip">
44+
<p class="alert-title">Tip</p>
45+
<p>Something of tip</p>
46+
</div>
47+
HTML
48+
49+
assert_equal(expected, Commonmarker.to_html(md, options: { extension: { alerts: true } }))
50+
end
51+
52+
def test_renders_a_complicated_node
53+
node = Commonmarker::Node.new(:alert, type: :warning, title: "This is bad")
54+
55+
assert_equal(:alert, node.type)
56+
57+
expected = <<~HTML
58+
<div class="alert alert-warning">
59+
<p class="alert-title">This is bad</p>
60+
</div>
61+
HTML
62+
assert_equal(expected, node.to_html)
63+
end
64+
end

test/node/creation_test.rb

+1
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ def test_it_can_make_all_the_nodes
4545
[:multiline_block_quote, fence_length: 2, fence_offset: 0],
4646
[:escaped],
4747
[:wikilink, url: "www.yetto.app/billy.png"],
48+
[:alert, type: :note],
4849
]
4950
node_types.each do |type, arguments|
5051
node = arguments.nil? ? Commonmarker::Node.new(type) : Commonmarker::Node.new(type, **arguments)

0 commit comments

Comments
 (0)