rushdown_link_attribute/
lib.rs1#![doc = include_str!("../README.md")]
2#![cfg_attr(not(feature = "std"), no_std)]
3
4extern crate alloc;
5use alloc::boxed::Box;
6use alloc::rc::Rc;
7use alloc::vec::Vec;
8use core::cell::RefCell;
9use rushdown::ast::Arena;
10use rushdown::ast::NodeRef;
11use rushdown::ast::Text;
12use rushdown::context::ContextKey;
13use rushdown::context::ContextKeyRegistry;
14use rushdown::context::ObjectValue;
15use rushdown::matches_kind;
16use rushdown::parser;
17use rushdown::parser::parse_attributes;
18use rushdown::parser::parser_extension;
19use rushdown::parser::AnyInlineParser;
20use rushdown::parser::InlineParser;
21use rushdown::parser::NoParserOptions;
22use rushdown::parser::Parser;
23use rushdown::parser::ParserExtension;
24use rushdown::text;
25
26#[derive(Debug)]
29struct LinkAttributeParser {
30 list: ContextKey<ObjectValue>,
31}
32
33impl LinkAttributeParser {
34 fn new(reg: Rc<RefCell<ContextKeyRegistry>>) -> Self {
35 Self {
36 list: reg.borrow_mut().create::<ObjectValue>(),
37 }
38 }
39}
40
41impl InlineParser for LinkAttributeParser {
42 fn trigger(&self) -> &[u8] {
43 b"{"
44 }
45
46 fn parse(
47 &self,
48 arena: &mut Arena,
49 parent_ref: NodeRef,
50 reader: &mut text::BlockReader,
51 ctx: &mut parser::Context,
52 ) -> Option<NodeRef> {
53 let prev = arena[parent_ref].last_child()?;
54 if !matches_kind!(arena[prev], Link) && !matches_kind!(arena[prev], Image) {
55 return None;
56 }
57 let attributes = parse_attributes(reader)?;
58 arena[prev].attributes_mut().extend(attributes);
59 let n = arena.new_node(Text::new(text::Index::new(0, 0)));
60
61 let mut list_opt = ctx.get_mut(self.list);
62 if list_opt.is_none() {
63 ctx.insert(self.list, Box::new(Vec::<NodeRef>::new()));
64 list_opt = ctx.get_mut(self.list);
65 }
66 let list = list_opt.unwrap().downcast_mut::<Vec<NodeRef>>().unwrap();
67 list.push(n);
68
69 Some(n)
70 }
71
72 fn close_block(
73 &self,
74 arena: &mut Arena,
75 _node_ref: NodeRef,
76 _reader: &mut text::BlockReader,
77 ctx: &mut parser::Context,
78 ) {
79 if let Some(list) = ctx.get_mut(self.list) {
80 let list = list.downcast_mut::<Vec<NodeRef>>().unwrap();
81 for n in list.drain(..) {
82 n.delete(arena);
83 }
84 }
85 }
86}
87
88impl From<LinkAttributeParser> for AnyInlineParser {
89 fn from(p: LinkAttributeParser) -> Self {
90 AnyInlineParser::Extension(Box::new(p))
91 }
92}
93
94pub fn link_attribute_parser_extension() -> impl ParserExtension {
100 parser_extension(|p: &mut Parser| {
101 p.add_inline_parser(LinkAttributeParser::new, NoParserOptions, 500);
102 })
103}
104
105