@@ -4,6 +4,7 @@ mod inlines;
4
4
pub mod shortcodes;
5
5
mod table;
6
6
7
+ pub mod alert;
7
8
pub mod math;
8
9
pub mod multiline_block_quote;
9
10
@@ -29,6 +30,7 @@ use std::sync::Arc;
29
30
use typed_arena:: Arena ;
30
31
31
32
use crate :: adapters:: HeadingAdapter ;
33
+ use crate :: parser:: alert:: { AlertType , NodeAlert } ;
32
34
use crate :: parser:: multiline_block_quote:: NodeMultilineBlockQuote ;
33
35
34
36
#[ cfg( feature = "bon" ) ]
@@ -420,6 +422,23 @@ pub struct ExtensionOptions<'c> {
420
422
#[ cfg_attr( feature = "bon" , builder( default ) ) ]
421
423
pub multiline_block_quotes : bool ,
422
424
425
+ /// Enables GitHub style alerts
426
+ ///
427
+ /// ```md
428
+ /// > [!note]
429
+ /// > Something of note
430
+ /// ```
431
+ ///
432
+ /// ```
433
+ /// # use comrak::{markdown_to_html, Options};
434
+ /// let mut options = Options::default();
435
+ /// options.extension.alerts = true;
436
+ /// assert_eq!(markdown_to_html("> [!note]\n> Something of note", &options),
437
+ /// "<div class=\"alert alert-note\">\n<p class=\"alert-title\">Note</p>\n<p>Something of note</p>\n</div>\n");
438
+ /// ```
439
+ #[ cfg_attr( feature = "bon" , builder( default ) ) ]
440
+ pub alerts : bool ,
441
+
423
442
/// Enables math using dollar syntax.
424
443
///
425
444
/// ``` md
@@ -1506,6 +1525,11 @@ where
1506
1525
return ( false , container, should_continue) ;
1507
1526
}
1508
1527
}
1528
+ NodeValue :: Alert ( ..) => {
1529
+ if !self . parse_block_quote_prefix ( line) {
1530
+ return ( false , container, should_continue) ;
1531
+ }
1532
+ }
1509
1533
_ => { }
1510
1534
}
1511
1535
}
@@ -1985,6 +2009,59 @@ where
1985
2009
true
1986
2010
}
1987
2011
2012
+ fn detect_alert ( & mut self , line : & [ u8 ] , indented : bool , alert_type : & mut AlertType ) -> bool {
2013
+ !indented
2014
+ && self . options . extension . alerts
2015
+ && line[ self . first_nonspace ] == b'>'
2016
+ && unwrap_into (
2017
+ scanners:: alert_start ( & line[ self . first_nonspace ..] ) ,
2018
+ alert_type,
2019
+ )
2020
+ }
2021
+
2022
+ fn handle_alert (
2023
+ & mut self ,
2024
+ container : & mut & ' a Node < ' a , RefCell < Ast > > ,
2025
+ line : & [ u8 ] ,
2026
+ indented : bool ,
2027
+ ) -> bool {
2028
+ let mut alert_type: AlertType = Default :: default ( ) ;
2029
+
2030
+ if !self . detect_alert ( line, indented, & mut alert_type) {
2031
+ return false ;
2032
+ }
2033
+
2034
+ let alert_startpos = self . first_nonspace ;
2035
+ let mut title_startpos = self . first_nonspace ;
2036
+
2037
+ while line[ title_startpos] != b']' {
2038
+ title_startpos += 1 ;
2039
+ }
2040
+ title_startpos += 1 ;
2041
+
2042
+ // anything remaining on this line is considered an alert title
2043
+ let mut tmp = entity:: unescape_html ( & line[ title_startpos..] ) ;
2044
+ strings:: trim ( & mut tmp) ;
2045
+ strings:: unescape ( & mut tmp) ;
2046
+
2047
+ let na = NodeAlert {
2048
+ alert_type,
2049
+ multiline : false ,
2050
+ title : if tmp. is_empty ( ) {
2051
+ None
2052
+ } else {
2053
+ Some ( String :: from_utf8 ( tmp) . unwrap ( ) )
2054
+ } ,
2055
+ } ;
2056
+
2057
+ let offset = self . curline_len - self . offset - 1 ;
2058
+ self . advance_offset ( line, offset, false ) ;
2059
+
2060
+ * container = self . add_child ( container, NodeValue :: Alert ( na) , alert_startpos + 1 ) ;
2061
+
2062
+ true
2063
+ }
2064
+
1988
2065
fn open_new_blocks ( & mut self , container : & mut & ' a AstNode < ' a > , line : & [ u8 ] , all_matched : bool ) {
1989
2066
let mut matched: usize = 0 ;
1990
2067
let mut nl: NodeList = NodeList :: default ( ) ;
@@ -2001,6 +2078,7 @@ where
2001
2078
let indented = self . indent >= CODE_INDENT ;
2002
2079
2003
2080
if self . handle_multiline_blockquote ( container, line, indented, & mut matched)
2081
+ || self . handle_alert ( container, line, indented)
2004
2082
|| self . handle_blockquote ( container, line, indented)
2005
2083
|| self . handle_atx_heading ( container, line, indented, & mut matched)
2006
2084
|| self . handle_code_fence ( container, line, indented, & mut matched)
@@ -2394,6 +2472,7 @@ where
2394
2472
|| container. data . borrow ( ) . sourcepos . start . line != self . line_number
2395
2473
}
2396
2474
NodeValue :: MultilineBlockQuote ( ..) => false ,
2475
+ NodeValue :: Alert ( ..) => false ,
2397
2476
_ => true ,
2398
2477
} ;
2399
2478
0 commit comments