wayver's git archive


an obsidian renderer
git clone https://git.wayver.dev/sable

sable-markdown/src/parser/inline/html_entity.rs@main

raw
Date Commit Message Author Files + -
2026-02-23 01:55 initial mvp wayverd 139 17808 0
...

1use nom::{
2    IResult, Parser,
3    branch::alt,
4    bytes::complete::tag,
5    character::complete::{alpha1, char, digit1, hex_digit1, one_of},
6    combinator::{map, map_opt, recognize},
7    sequence::{delimited, preceded},
8};
9
10use crate::parser::util::ENTITIES;
11
12pub(super) fn html_entity() -> impl FnMut(&str) -> IResult<&str, String> {
13    move |input: &str| alt((html_entity_alpha(), html_entity_numeric)).parse(input)
14}
15
16fn html_entity_alpha() -> impl FnMut(&str) -> IResult<&str, String> {
17    move |input: &str| {
18        map_opt(recognize((char('&'), alpha1, char(';'))), |s: &str| {
19            ENTITIES.get(s).map(|entity| entity.characters.to_owned())
20        })
21        .parse(input)
22    }
23}
24
25fn html_entity_numeric(input: &str) -> IResult<&str, String> {
26    let base16 = map_opt(preceded(one_of("xX"), hex_digit1), |s: &str| {
27        u32::from_str_radix(s, 16).ok()
28    });
29    let base10 = map_opt(digit1, |s: &str| s.parse::<u32>().ok());
30
31    map(
32        map_opt(
33            delimited(tag("&#"), alt((base10, base16)), char(';')),
34            char::from_u32,
35        ),
36        |c: char| c.to_string(),
37    )
38    .parse(input)
39}
40