pub type JsResult<T> = Result<T, crate::parser::ParserError>;
pub type OFF = u32;
pub type SZ = u32;
#[repr(u8)]
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub enum BlockType {
Doc,
Quote,
Ul,
Ol,
Li,
Hr,
H,
Code,
Html,
P,
Table,
Thead,
Tbody,
Tr,
Th,
Td,
}
#[repr(u8)]
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub enum SpanType {
Em,
Strong,
A,
Img,
Code,
Del,
Latexmath,
LatexmathDisplay,
Wikilink,
U,
}
#[repr(u8)]
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub enum TextType {
Normal,
NullChar,
Br,
Softbr,
Entity,
Code,
Html,
Latexmath,
}
#[repr(u8)]
#[derive(Copy, Clone, Eq, PartialEq, Debug, Default)]
pub enum Align {
#[default]
Default,
Left,
Center,
Right,
}
pub struct Renderer<'a> {
pub ptr: &'a mut dyn RendererImpl,
}
pub trait RendererImpl {
fn enter_block(&mut self, block_type: BlockType, data: u32, flags: u32) -> JsResult<()>;
fn leave_block(&mut self, block_type: BlockType, data: u32) -> JsResult<()>;
fn enter_span(&mut self, span_type: SpanType, detail: SpanDetail<'_>) -> JsResult<()>;
fn leave_span(&mut self, span_type: SpanType) -> JsResult<()>;
fn text(&mut self, text_type: TextType, content: &[u8]) -> JsResult<()>;
}
impl<'a> Renderer<'a> {
#[inline]
pub fn enter_block(&mut self, block_type: BlockType, data: u32, flags: u32) -> JsResult<()> {
self.ptr.enter_block(block_type, data, flags)
}
#[inline]
pub fn leave_block(&mut self, block_type: BlockType, data: u32) -> JsResult<()> {
self.ptr.leave_block(block_type, data)
}
#[inline]
pub fn enter_span(&mut self, span_type: SpanType, detail: SpanDetail<'_>) -> JsResult<()> {
self.ptr.enter_span(span_type, detail)
}
#[inline]
pub fn leave_span(&mut self, span_type: SpanType) -> JsResult<()> {
self.ptr.leave_span(span_type)
}
#[inline]
pub fn text(&mut self, text_type: TextType, content: &[u8]) -> JsResult<()> {
self.ptr.text(text_type, content)
}
}
#[derive(Copy, Clone)]
pub struct SpanDetail<'a> {
pub href: &'a [u8],
pub title: &'a [u8],
pub autolink: bool,
pub autolink_email: bool,
pub permissive_autolink: bool,
pub autolink_www: bool,
}
impl<'a> Default for SpanDetail<'a> {
fn default() -> Self {
Self {
href: b"",
title: b"",
autolink: false,
autolink_email: false,
permissive_autolink: false,
autolink_www: false,
}
}
}
impl<'a> SpanDetail<'a> {
#[inline]
pub unsafe fn detach_lifetime(self) -> SpanDetail<'static> {
SpanDetail {
href: unsafe { &*core::ptr::from_ref::<[u8]>(self.href) },
title: unsafe { &*core::ptr::from_ref::<[u8]>(self.title) },
autolink: self.autolink,
autolink_email: self.autolink_email,
permissive_autolink: self.permissive_autolink,
autolink_www: self.autolink_www,
}
}
}
#[derive(Copy, Clone)]
pub struct Attribute<'a> {
pub substr_offsets: &'a [SubstrOffset],
pub substr_types: &'a [SubstrType],
}
#[repr(u8)]
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub enum SubstrType {
Normal,
Entity,
}
#[derive(Copy, Clone)]
pub struct SubstrOffset {
pub beg: OFF,
pub end: OFF,
}
impl<'a> Attribute<'a> {
pub fn text<'s>(&self, src: &'s [u8]) -> &'s [u8] {
if self.substr_offsets.is_empty() {
return b"";
}
let first = self.substr_offsets[0].beg;
let last = self.substr_offsets[self.substr_offsets.len() - 1].end;
&src[first as usize..last as usize]
}
}
pub fn alignment_from_data(data: u32) -> Align {
match data & 0b11 {
0 => Align::Default,
1 => Align::Left,
2 => Align::Center,
_ => Align::Right,
}
}
pub fn alignment_name(alignment: Align) -> Option<&'static [u8]> {
match alignment {
Align::Left => Some(b"left"),
Align::Center => Some(b"center"),
Align::Right => Some(b"right"),
Align::Default => None,
}
}
pub fn task_mark_from_data(data: u32) -> u8 {
data as u8
}
pub fn is_task_checked(task_mark: u8) -> bool {
task_mark != 0 && task_mark != b' '
}
pub const BLOCK_FENCED_CODE: u32 = 0x10;