2021-09-13 15:51:13 +08:00
|
|
|
#![allow(non_snake_case)]
|
2021-09-13 16:45:36 +08:00
|
|
|
use crate::core::Attributes;
|
2021-08-16 23:07:40 +08:00
|
|
|
use derive_more::Display;
|
|
|
|
|
use lazy_static::lazy_static;
|
|
|
|
|
use std::{collections::HashSet, fmt, fmt::Formatter, iter::FromIterator};
|
|
|
|
|
|
|
|
|
|
lazy_static! {
|
|
|
|
|
static ref BLOCK_KEYS: HashSet<AttributeKey> = HashSet::from_iter(vec![
|
|
|
|
|
AttributeKey::Header,
|
2021-08-17 11:23:28 +08:00
|
|
|
AttributeKey::LeftAlignment,
|
|
|
|
|
AttributeKey::CenterAlignment,
|
|
|
|
|
AttributeKey::RightAlignment,
|
|
|
|
|
AttributeKey::JustifyAlignment,
|
|
|
|
|
AttributeKey::Indent,
|
2021-08-16 23:07:40 +08:00
|
|
|
AttributeKey::Align,
|
|
|
|
|
AttributeKey::CodeBlock,
|
2021-08-17 11:23:28 +08:00
|
|
|
AttributeKey::List,
|
|
|
|
|
AttributeKey::Bullet,
|
|
|
|
|
AttributeKey::Ordered,
|
|
|
|
|
AttributeKey::Checked,
|
|
|
|
|
AttributeKey::UnChecked,
|
2021-08-16 23:07:40 +08:00
|
|
|
AttributeKey::QuoteBlock,
|
|
|
|
|
]);
|
|
|
|
|
static ref INLINE_KEYS: HashSet<AttributeKey> = HashSet::from_iter(vec![
|
|
|
|
|
AttributeKey::Bold,
|
|
|
|
|
AttributeKey::Italic,
|
|
|
|
|
AttributeKey::Underline,
|
|
|
|
|
AttributeKey::StrikeThrough,
|
|
|
|
|
AttributeKey::Link,
|
|
|
|
|
AttributeKey::Color,
|
2021-08-17 11:23:28 +08:00
|
|
|
AttributeKey::Font,
|
|
|
|
|
AttributeKey::Size,
|
2021-08-16 23:07:40 +08:00
|
|
|
AttributeKey::Background,
|
|
|
|
|
]);
|
2021-09-13 15:51:13 +08:00
|
|
|
static ref INGORE_KEYS: HashSet<AttributeKey> = HashSet::from_iter(vec![AttributeKey::Width, AttributeKey::Height,]);
|
2021-08-16 23:07:40 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, PartialEq, Eq, Clone)]
|
|
|
|
|
pub enum AttributeScope {
|
|
|
|
|
Inline,
|
|
|
|
|
Block,
|
|
|
|
|
Embeds,
|
|
|
|
|
Ignore,
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-13 15:51:13 +08:00
|
|
|
macro_rules! inline_attribute {
|
|
|
|
|
(
|
|
|
|
|
$key: ident,
|
|
|
|
|
$value: ty
|
|
|
|
|
) => {
|
|
|
|
|
pub fn $key(value: $value) -> Self {
|
|
|
|
|
Self {
|
|
|
|
|
key: AttributeKey::$key,
|
|
|
|
|
value: value.into(),
|
|
|
|
|
scope: AttributeScope::Inline,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
macro_rules! block_attribute {
|
|
|
|
|
(
|
|
|
|
|
$key: ident,
|
|
|
|
|
$value: ident
|
|
|
|
|
) => {
|
|
|
|
|
pub fn $key(value: $value) -> Self {
|
|
|
|
|
Self {
|
|
|
|
|
key: AttributeKey::$key,
|
|
|
|
|
value: value.into(),
|
|
|
|
|
scope: AttributeScope::Block,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
macro_rules! ignore_attribute {
|
|
|
|
|
(
|
|
|
|
|
$key: ident,
|
|
|
|
|
$value: ident
|
|
|
|
|
) => {
|
|
|
|
|
pub fn $key(value: $value) -> Self {
|
|
|
|
|
Self {
|
|
|
|
|
key: AttributeKey::$key,
|
|
|
|
|
value: value.into(),
|
|
|
|
|
scope: AttributeScope::Ignore,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
2021-08-16 23:07:40 +08:00
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
|
pub struct Attribute {
|
|
|
|
|
pub key: AttributeKey,
|
|
|
|
|
pub value: AttributeValue,
|
|
|
|
|
pub scope: AttributeScope,
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-13 15:51:13 +08:00
|
|
|
impl Attribute {
|
2021-09-13 16:45:36 +08:00
|
|
|
// inline
|
2021-09-13 15:51:13 +08:00
|
|
|
inline_attribute!(Bold, bool);
|
|
|
|
|
inline_attribute!(Italic, bool);
|
|
|
|
|
inline_attribute!(Underline, bool);
|
|
|
|
|
inline_attribute!(StrikeThrough, bool);
|
|
|
|
|
inline_attribute!(Link, &str);
|
|
|
|
|
inline_attribute!(Color, String);
|
|
|
|
|
inline_attribute!(Font, usize);
|
|
|
|
|
inline_attribute!(Size, usize);
|
|
|
|
|
inline_attribute!(Background, String);
|
|
|
|
|
|
2021-09-13 16:45:36 +08:00
|
|
|
// block
|
2021-09-13 15:51:13 +08:00
|
|
|
block_attribute!(Header, usize);
|
|
|
|
|
block_attribute!(LeftAlignment, usize);
|
|
|
|
|
block_attribute!(CenterAlignment, usize);
|
|
|
|
|
block_attribute!(RightAlignment, usize);
|
|
|
|
|
block_attribute!(JustifyAlignment, bool);
|
|
|
|
|
block_attribute!(Indent, String);
|
|
|
|
|
block_attribute!(Align, String);
|
|
|
|
|
block_attribute!(CodeBlock, String);
|
|
|
|
|
block_attribute!(List, String);
|
|
|
|
|
block_attribute!(Bullet, bool);
|
|
|
|
|
block_attribute!(Ordered, bool);
|
|
|
|
|
block_attribute!(Checked, bool);
|
|
|
|
|
block_attribute!(UnChecked, bool);
|
|
|
|
|
block_attribute!(QuoteBlock, bool);
|
|
|
|
|
|
2021-09-13 16:45:36 +08:00
|
|
|
// ignore
|
2021-09-13 15:51:13 +08:00
|
|
|
ignore_attribute!(Width, usize);
|
|
|
|
|
ignore_attribute!(Height, usize);
|
|
|
|
|
}
|
|
|
|
|
|
2021-08-16 23:07:40 +08:00
|
|
|
impl fmt::Display for Attribute {
|
|
|
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
|
|
|
|
let s = format!("{:?}:{} {:?}", self.key, self.value.as_ref(), self.scope);
|
|
|
|
|
f.write_str(&s)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl std::convert::Into<Attributes> for Attribute {
|
|
|
|
|
fn into(self) -> Attributes {
|
|
|
|
|
let mut attributes = Attributes::new();
|
|
|
|
|
attributes.add(self);
|
|
|
|
|
attributes
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Clone, Debug, Display, Hash, Eq, PartialEq, serde::Serialize, serde::Deserialize)]
|
|
|
|
|
#[serde(rename_all = "camelCase")]
|
|
|
|
|
pub enum AttributeKey {
|
|
|
|
|
#[display(fmt = "bold")]
|
|
|
|
|
Bold,
|
|
|
|
|
#[display(fmt = "italic")]
|
|
|
|
|
Italic,
|
|
|
|
|
#[display(fmt = "underline")]
|
|
|
|
|
Underline,
|
|
|
|
|
#[display(fmt = "strike_through")]
|
|
|
|
|
StrikeThrough,
|
|
|
|
|
#[display(fmt = "font")]
|
|
|
|
|
Font,
|
|
|
|
|
#[display(fmt = "size")]
|
|
|
|
|
Size,
|
|
|
|
|
#[display(fmt = "link")]
|
|
|
|
|
Link,
|
|
|
|
|
#[display(fmt = "color")]
|
|
|
|
|
Color,
|
|
|
|
|
#[display(fmt = "background")]
|
|
|
|
|
Background,
|
|
|
|
|
#[display(fmt = "indent")]
|
|
|
|
|
Indent,
|
|
|
|
|
#[display(fmt = "align")]
|
|
|
|
|
Align,
|
|
|
|
|
#[display(fmt = "code_block")]
|
|
|
|
|
CodeBlock,
|
|
|
|
|
#[display(fmt = "list")]
|
|
|
|
|
List,
|
|
|
|
|
#[display(fmt = "quote_block")]
|
|
|
|
|
QuoteBlock,
|
|
|
|
|
#[display(fmt = "width")]
|
|
|
|
|
Width,
|
|
|
|
|
#[display(fmt = "height")]
|
|
|
|
|
Height,
|
|
|
|
|
#[display(fmt = "header")]
|
|
|
|
|
Header,
|
|
|
|
|
#[display(fmt = "left")]
|
|
|
|
|
LeftAlignment,
|
|
|
|
|
#[display(fmt = "center")]
|
|
|
|
|
CenterAlignment,
|
|
|
|
|
#[display(fmt = "right")]
|
|
|
|
|
RightAlignment,
|
|
|
|
|
#[display(fmt = "justify")]
|
|
|
|
|
JustifyAlignment,
|
|
|
|
|
#[display(fmt = "bullet")]
|
|
|
|
|
Bullet,
|
|
|
|
|
#[display(fmt = "ordered")]
|
|
|
|
|
Ordered,
|
|
|
|
|
#[display(fmt = "checked")]
|
|
|
|
|
Checked,
|
|
|
|
|
#[display(fmt = "unchecked")]
|
|
|
|
|
UnChecked,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
|
|
|
|
pub struct AttributeValue(pub(crate) String);
|
|
|
|
|
|
|
|
|
|
impl AsRef<str> for AttributeValue {
|
|
|
|
|
fn as_ref(&self) -> &str { &self.0 }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl std::convert::From<&usize> for AttributeValue {
|
2021-09-13 16:45:36 +08:00
|
|
|
fn from(val: &usize) -> Self { AttributeValue::from(*val) }
|
2021-09-13 15:51:13 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl std::convert::From<usize> for AttributeValue {
|
|
|
|
|
fn from(val: usize) -> Self {
|
|
|
|
|
if val > (0 as usize) {
|
|
|
|
|
AttributeValue(format!("{}", val))
|
|
|
|
|
} else {
|
|
|
|
|
AttributeValue(format!(""))
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-08-16 23:07:40 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl std::convert::From<&str> for AttributeValue {
|
|
|
|
|
fn from(val: &str) -> Self { AttributeValue(val.to_owned()) }
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-13 15:51:13 +08:00
|
|
|
impl std::convert::From<String> for AttributeValue {
|
|
|
|
|
fn from(val: String) -> Self { AttributeValue(val) }
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-13 16:45:36 +08:00
|
|
|
impl std::convert::From<&bool> for AttributeValue {
|
|
|
|
|
fn from(val: &bool) -> Self { AttributeValue::from(*val) }
|
|
|
|
|
}
|
|
|
|
|
|
2021-08-16 23:07:40 +08:00
|
|
|
impl std::convert::From<bool> for AttributeValue {
|
|
|
|
|
fn from(val: bool) -> Self {
|
|
|
|
|
let val = match val {
|
|
|
|
|
true => "true",
|
|
|
|
|
false => "",
|
|
|
|
|
};
|
|
|
|
|
AttributeValue(val.to_owned())
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-08-17 11:23:28 +08:00
|
|
|
|
|
|
|
|
pub fn is_block_except_header(k: &AttributeKey) -> bool {
|
|
|
|
|
if k == &AttributeKey::Header {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
BLOCK_KEYS.contains(k)
|
|
|
|
|
}
|