// document
document = _{ SOI ~ content ~ EOI }
element = _{ PEEK[..] ~ indent* ~ (void_element | block_element) }
content = _{ element ~ (blank_line* ~ element)* ~ blank_line? }
block_element = _{
doctype | html | head | body | html_comment | code_comment
}
void_element = _{
link
// area | base | br | col | embed | hr | img | input | link | meta |
// source | track | wbr
}
indent = { (" ")+ }
// comment
code_comment_symbol = { "/" }
html_comment_symbol = { "/!" }
symbol = { code_comment_symbol | html_comment_symbol }
comment_text = ${ (!(blank_line) ~ ANY)+ }
code_comment = ${ code_comment_symbol ~ (comment_text | (indent+ ~ (comment_text | blank_line)))* }
html_comment = ${ html_comment_symbol ~ (comment_text | (indent+ ~ (comment_text | blank_line)))* }
comment = { html_comment | code_comment }
// doctype: https://github.com/slim-template/slim/blob/39cc3fb82b34092ec9e92b8057c5b60c426ffca5/test/literate/TESTS.md#doctype-tags
encoding = ${ ident+ }
xml_doctype = {
"xml"
}
// depends on mode
xhtml_doctype = _{
"html" | "5" | "1.1" | "strict" | "frameset" | "mobile" | "basic" |
"transitional"
}
html_doctype = _{
"html" | "5" | "strict" | "frameset" | "transitional"
}
doctype_tag = _{ "doctype" }
doctype_value = {
xml_doctype ~ (" " ~ encoding)? |
xhtml_doctype |
html_doctype
}
doctype = { &doctype_tag ~ doctype_tag ~ (" "|blank_line)* ~ doctype_value }
char = _{'a'..'z' | 'A'..'Z' | '0'..'9' | "-" | "." | "_"}
ident = @{
('a'..'z' | 'A'..'Z') ~
char*
}
link_attr_key = { "rel" | "href" }
link_attr_value = _{ ident+ }
global_attribute = { (ident+ ~ ("=" ~ "\"" ~ ident+ ~ "\"")?)* }
link_attribute = { (link_attr_key ~ "=" ~ "\"" ~ link_attr_value ~ "\"" ~ " "?)* }
// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/html
// Permitted content: One <head> element, followed by one <body> element
html = {
"html" ~ (" " ~ global_attribute)? ~
(NEWLINE+ ~ indent+ ~ head)? ~
(NEWLINE+ ~ indent+ ~ body)?
}
head = { "head" ~ (NEWLINE+ ~ indent+ ~ link)? }
link = { "link" ~ (" " ~ link_attribute)? }
body = { "body" }
// NOTE:
// We may not be able to specificy WHITESPACE like this because of indent-based
// syntax?
// WHITESPACE = _{ " " }
blank_line = _{ " "* ~ NEWLINE }