Add color formatting

pull/1/head
trivernis 5 years ago
parent d5e2db3e1f
commit 6bf51b91f0

2
Cargo.lock generated

@ -404,7 +404,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "snekdown" name = "snekdown"
version = "0.11.0" version = "0.12.0"
dependencies = [ dependencies = [
"chrono 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", "chrono 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
"colored 1.9.3 (registry+https://github.com/rust-lang/crates.io-index)", "colored 1.9.3 (registry+https://github.com/rust-lang/crates.io-index)",

@ -1,6 +1,6 @@
[package] [package]
name = "snekdown" name = "snekdown"
version = "0.11.0" version = "0.12.0"
authors = ["trivernis <trivernis@protonmail.com>"] authors = ["trivernis <trivernis@protonmail.com>"]
edition = "2018" edition = "2018"
license-file = "LICENSE" license-file = "LICENSE"

@ -158,6 +158,7 @@ _Underlined_
^Superscript^ ^Superscript^
`Monospace` `Monospace`
:Emoji: :Emoji:
§[#0C0]Colored text§[] §[red] red §[]
``` ```
## Roadmap ## Roadmap
@ -166,11 +167,12 @@ The end goal is to have a markup language with features similar to LaTeX.
- [x] Checkboxes - [x] Checkboxes
- [x] Emojis (\:emoji:) - [x] Emojis (\:emoji:)
- [x] Colors
- [ ] Watching and rendering on change
- [ ] Metadata files - [ ] Metadata files
- [ ] Bibliography - [ ] Bibliography
- [ ] Math - [ ] Math
- [ ] Text sizes - [ ] Text sizes
- [ ] Colors
- [ ] Title pages - [ ] Title pages
- [ ] Glossary - [ ] Glossary
- [ ] Cross References - [ ] Cross References

@ -59,6 +59,7 @@ impl ToHtml for Inline {
Inline::Superscript(superscript) => superscript.to_html(), Inline::Superscript(superscript) => superscript.to_html(),
Inline::Checkbox(checkbox) => checkbox.to_html(), Inline::Checkbox(checkbox) => checkbox.to_html(),
Inline::Emoji(emoji) => emoji.to_html(), Inline::Emoji(emoji) => emoji.to_html(),
Inline::Colored(colored) => colored.to_html(),
} }
} }
} }
@ -498,3 +499,13 @@ impl ToHtml for Emoji {
) )
} }
} }
impl ToHtml for Colored {
fn to_html(&self) -> String {
format!(
"<span class='colored' style='color:{};'>{}</span>",
encode_attribute(self.color.as_str()),
self.value.to_html()
)
}
}

@ -158,6 +158,7 @@ pub enum Inline {
Reference(Reference), Reference(Reference),
Checkbox(Checkbox), Checkbox(Checkbox),
Emoji(Emoji), Emoji(Emoji),
Colored(Colored),
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
@ -259,6 +260,12 @@ pub struct Emoji {
pub(crate) name: String, pub(crate) name: String,
} }
#[derive(Clone, Debug)]
pub struct Colored {
pub(crate) value: Box<Inline>,
pub(crate) color: String,
}
// implementations // implementations
impl Document { impl Document {

@ -17,6 +17,7 @@ pub(crate) trait ParseInline {
fn parse_underlined(&mut self) -> ParseResult<UnderlinedText>; fn parse_underlined(&mut self) -> ParseResult<UnderlinedText>;
fn parse_superscript(&mut self) -> ParseResult<SuperscriptText>; fn parse_superscript(&mut self) -> ParseResult<SuperscriptText>;
fn parse_emoji(&mut self) -> ParseResult<Emoji>; fn parse_emoji(&mut self) -> ParseResult<Emoji>;
fn parse_colored(&mut self) -> ParseResult<Colored>;
fn parse_plain(&mut self) -> ParseResult<PlainText>; fn parse_plain(&mut self) -> ParseResult<PlainText>;
} }
@ -47,6 +48,8 @@ impl ParseInline for Parser {
Ok(Inline::Checkbox(checkbox)) Ok(Inline::Checkbox(checkbox))
} else if let Ok(emoji) = self.parse_emoji() { } else if let Ok(emoji) = self.parse_emoji() {
Ok(Inline::Emoji(emoji)) Ok(Inline::Emoji(emoji))
} else if let Ok(colored) = self.parse_colored() {
Ok(Inline::Colored(colored))
} else { } else {
Ok(Inline::Plain(self.parse_plain()?)) Ok(Inline::Plain(self.parse_plain()?))
} }
@ -214,7 +217,7 @@ impl ParseInline for Parser {
let start_index = self.index; let start_index = self.index;
self.assert_special(&EMOJI, start_index)?; self.assert_special(&EMOJI, start_index)?;
self.skip_char(); self.skip_char();
let name = self.get_string_until_or_revert(&[EMOJI], &[], start_index)?; let name = self.get_string_until_or_revert(&[EMOJI], &[SPACE, LB], start_index)?;
self.skip_char(); self.skip_char();
if let Some(emoji) = gh_emoji::get(name.as_str()) { if let Some(emoji) = gh_emoji::get(name.as_str()) {
let emoji_char = *emoji.chars().collect::<Vec<char>>().first().unwrap(); let emoji_char = *emoji.chars().collect::<Vec<char>>().first().unwrap();
@ -226,4 +229,21 @@ impl ParseInline for Parser {
Err(self.revert_with_error(start_index)) Err(self.revert_with_error(start_index))
} }
} }
/// parses colored text
fn parse_colored(&mut self) -> ParseResult<Colored> {
let start_index = self.index;
self.assert_special_sequence(&SQ_COLOR_START, start_index)?;
self.skip_char();
let color =
self.get_string_until_or_revert(&[COLOR_CLOSE], &[SPACE, LB, SEMICOLON], start_index)?;
self.skip_char();
if color.is_empty() {
return Err(ParseError::new(self.index));
}
Ok(Colored {
value: Box::new(self.parse_inline()?),
color,
})
}
} }

@ -26,6 +26,8 @@ pub(crate) const SINGLE_QUOTE: char = '\'';
pub(crate) const DOT: char = '.'; pub(crate) const DOT: char = '.';
pub(crate) const UP: char = '^'; pub(crate) const UP: char = '^';
pub(crate) const COLON: char = ':'; pub(crate) const COLON: char = ':';
pub(crate) const PARAGRAPH: char = '§';
pub(crate) const SEMICOLON: char = ';';
// aliases // aliases
@ -46,6 +48,9 @@ pub(crate) const PHOLDER_CLOSE: char = L_BRACKET;
pub(crate) const CHECK_OPEN: char = R_BRACKET; pub(crate) const CHECK_OPEN: char = R_BRACKET;
pub(crate) const CHECK_CLOSE: char = L_BRACKET; pub(crate) const CHECK_CLOSE: char = L_BRACKET;
pub(crate) const CHECK_CHECKED: char = X; pub(crate) const CHECK_CHECKED: char = X;
pub(crate) const COLOR_START: char = PARAGRAPH;
pub(crate) const COLOR_OPEN: char = R_BRACKET;
pub(crate) const COLOR_CLOSE: char = L_BRACKET;
pub(crate) const ITALIC: char = ASTERISK; pub(crate) const ITALIC: char = ASTERISK;
pub(crate) const MONOSPACE: char = BACKTICK; pub(crate) const MONOSPACE: char = BACKTICK;
@ -71,8 +76,18 @@ pub(crate) const BLOCK_SPECIAL_CHARS: [&[char]; 9] = [
&SQ_CENTERED_START, &SQ_CENTERED_START,
]; ];
pub(crate) const INLINE_SPECIAL_CHARS: [char; 10] = [ pub(crate) const INLINE_SPECIAL_CHARS: [char; 11] = [
BACKTICK, TILDE, UNDERSCR, ASTERISK, DESC_OPEN, IMG_START, URL_OPEN, LB, SUPER, EMOJI, BACKTICK,
TILDE,
UNDERSCR,
ASTERISK,
DESC_OPEN,
IMG_START,
URL_OPEN,
LB,
SUPER,
EMOJI,
COLOR_START,
]; ];
pub(crate) const LIST_SPECIAL_CHARS: [char; 14] = [ pub(crate) const LIST_SPECIAL_CHARS: [char; 14] = [
@ -86,6 +101,7 @@ pub(crate) const SQ_RULER: [char; 5] = [MINUS, SPACE, MINUS, SPACE, MINUS];
pub(crate) const SQ_PHOLDER_START: [char; 2] = [PHOLDER_OPEN, PHOLDER_OPEN]; pub(crate) const SQ_PHOLDER_START: [char; 2] = [PHOLDER_OPEN, PHOLDER_OPEN];
pub(crate) const SQ_PHOLDER_STOP: [char; 2] = [PHOLDER_CLOSE, PHOLDER_CLOSE]; pub(crate) const SQ_PHOLDER_STOP: [char; 2] = [PHOLDER_CLOSE, PHOLDER_CLOSE];
pub(crate) const SQ_CENTERED_START: [char; 2] = [PIPE, PIPE]; pub(crate) const SQ_CENTERED_START: [char; 2] = [PIPE, PIPE];
pub(crate) const SQ_COLOR_START: [char; 2] = [COLOR_START, COLOR_OPEN];
// expressions // expressions

Loading…
Cancel
Save