-
Notifications
You must be signed in to change notification settings - Fork 1
/
markdown.pest
103 lines (85 loc) · 4.15 KB
/
markdown.pest
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
// character sets
WHITESPACES = _{ (!vertical_space ~ " ") | "\t" }
SPACES = _{ " "+ }
EMPTY_LINE = _{ (" ")* ~ NEWLINE }
SYMBOLS = _{ SYMBOL | PUNCTUATION }
INLINE_SYMBOLS = _{ "`" | "[" | "*" | "![" }
SYM_NOT_INLINE = _{ !INLINE_SYMBOLS ~ SYMBOLS }
URL_CHARS = _{ ASCII_ALPHANUMERIC | ":" | "/" | "." | "_" | "-" | "%" | "@" | "#" | "(" | (")" ~ &(URL_CHARS* ~ ")")) }
// Common
char_not_sym_nospace = _{ LETTER | NUMBER }
char_not_sym = _{ char_not_sym_nospace | WHITESPACES }
anychar = _{ char_not_sym | SYMBOLS }
char = _{ char_not_sym | SYM_NOT_INLINE }
text = { char+ }
slug = { (ASCII_ALPHANUMERIC | "_" | "-" | ".")+ }
// headers
h1 = { "# " ~ rich_txt }
h2 = { "## " ~ rich_txt }
h3 = { "### " ~ rich_txt }
h4 = { "#### " ~ rich_txt }
h5 = { "##### " ~ rich_txt }
h6 = { "###### " ~ rich_txt }
// list
list_element_under = _{ NEWLINE ~ !("- ") ~ (comment | rich_txt_some) }
list_element = { "- " ~ rich_txt ~ list_element_under* }
list = { list_element ~ (NEWLINE+ ~ list_element)* ~ (NEWLINE | EOI) }
// quote
quote_txt = _{ inline_symbol | text | INLINE_SYMBOLS }
quote_line = { quote_txt+ ~ vertical_space? ~ &(NEWLINE | EOI) }
quote = { "> " ~ quote_line* ~ (NEWLINE ~ ("> ")? ~ quote_line)* ~ (NEWLINE | EOI) }
// code
INLINE_CODE_DELIMITER = _{ "`" ~ !("`") }
inline_code_code = { (char_not_sym | (!INLINE_CODE_DELIMITER ~ SYMBOLS))+ }
inline_code = { (INLINE_CODE_DELIMITER ~ inline_code_code* ~ INLINE_CODE_DELIMITER)+ }
CODEBLOCK_DELIMITER = _{ "```" }
codeblock_code = { ((char_not_sym | (!CODEBLOCK_DELIMITER ~ SYMBOLS)))+ }
codeblock = { CODEBLOCK_DELIMITER ~ (WHITESPACES* ~ slug)? ~ NEWLINE ~ (codeblock_code | NEWLINE)* ~ CODEBLOCK_DELIMITER }
// comments
comment_word = _{ (char_not_sym_nospace | (!("-->") ~ SYMBOLS))+ }
comment_text = { (comment_word ~ (NEWLINE | WHITESPACES))* ~ comment_word }
comment = { "<!--" ~ (WHITESPACES | NEWLINE)* ~ comment_text ~ (WHITESPACES | NEWLINE)* ~ "-->" }
// Bold
BOLD_DELIMITER = _{ "**" }
bold_text = { (char_not_sym | SYM_NOT_INLINE)+ }
bold_content = _{ !BOLD_DELIMITER ~ (italic | inline_code | link | reflink | image | NEWLINE | bold_text) }
bold = { BOLD_DELIMITER ~ bold_content* ~ BOLD_DELIMITER }
// Italic
ITALIC_DELIMITER = _{ "*" ~ (&BOLD_DELIMITER | !("*")) }
italic_text = { (char_not_sym | SYM_NOT_INLINE)+ }
italic_content = _{ !ITALIC_DELIMITER ~ (bold | inline_code | link | reflink | image | NEWLINE | italic_text) }
italic = { ITALIC_DELIMITER ~ italic_content* ~ ITALIC_DELIMITER }
// Direct Links
url = { URL_CHARS* }
link_text = { (char_not_sym | (!(INLINE_SYMBOLS | "]") ~ SYMBOLS))+ | NEWLINE }
link = { "[" ~ (inline_symbol | link_text)* ~ "](" ~ url ~ ")" }
// Links using references & labels
reflink = { "[" ~ (inline_symbol | link_text)* ~ "][" ~ slug ~ "]" }
refurl_url = { (URL_CHARS | ")")* }
refurl = { "[" ~ slug ~ "]:" ~ WHITESPACES* ~ refurl_url }
// Images
img_tag_key = { slug }
img_tag_val = { char_not_sym_nospace+ | ("\"" ~ (!("]" | "\"") ~ anychar)* ~ "\"") }
img_tag = { img_tag_key ~ WHITESPACES* ~ ":" ~ WHITESPACES* ~ img_tag_val }
image_tags = { "[" ~ (img_tag ~ "," ~ WHITESPACES*)* ~ img_tag ~ "]" }
image = { "" ~ image_tags? }
// Paragraph
paragraph_newline = { NEWLINE }
paragraph_line = _{ SPACES? ~ (!block_type ~ rich_txt_some ~ vertical_space?)+ }
paragraph = {
paragraph_line ~ (paragraph_newline ~ paragraph_line)* ~ &(NEWLINE | EOI)
}
// Separator
horiz_sep = { ("-"){3, } }
vertical_space = { " " ~ &(NEWLINE | EOI) }
// Meta
rich_txt = { rich_txt_maybe }
rich_txt_maybe = _{ (inline_symbol | text)* }
rich_txt_some = _{ (inline_symbol | text)+ }
inline_symbol = _{ bold | italic | inline_code | link | reflink | refurl | image }
block_type = _{ h1 | h2 | h3 | h4 | h5 | h6 | quote | codeblock | comment | list }
text_line = _{ block_type | horiz_sep | &NEWLINE | paragraph }
file = {
SOI ~ (text_line ~ NEWLINE ~ EMPTY_LINE*)* ~ text_line? ~ SPACES? ~ EOI
}
// TODO Strikethrough text