103 lines
1.7 KiB
JavaScript
103 lines
1.7 KiB
JavaScript
const startTag = ($, tag) => seq(
|
|
'<',
|
|
alias(tag, $.tag_name),
|
|
repeat($.attribute),
|
|
'>'
|
|
)
|
|
|
|
module.exports = grammar({
|
|
name: 'html',
|
|
|
|
externals: $ => [
|
|
$.tag_name,
|
|
|
|
],
|
|
|
|
rules: {
|
|
fragment: $ => repeat($._node),
|
|
|
|
_node: $ => choice(
|
|
$.text,
|
|
$.element,
|
|
$.void_element
|
|
),
|
|
|
|
element: $ => seq(
|
|
$.start_tag,
|
|
repeat($._node),
|
|
$.end_tag
|
|
),
|
|
|
|
void_element: $ => choice(
|
|
seq($.void_start_tag, optional($.end_tag)),
|
|
$.self_closing_tag
|
|
),
|
|
|
|
start_tag: $ => startTag($, $.tag_name),
|
|
|
|
void_start_tag: $ => startTag($, $.void_tag_name),
|
|
|
|
self_closing_tag: $ => seq(
|
|
'<',
|
|
choice($.tag_name, $.void_tag_name),
|
|
repeat($.attribute),
|
|
'/',
|
|
'>'
|
|
),
|
|
|
|
attribute: $ => seq(
|
|
alias($._attribute_part, $.attribute_name),
|
|
optional(seq(
|
|
'=',
|
|
choice(
|
|
alias($._attribute_part, $.attribute_value),
|
|
$.quoted_attribute_value
|
|
)
|
|
))
|
|
),
|
|
|
|
_attribute_part: $ => /[^<>"'/=\s]+/,
|
|
|
|
quoted_attribute_value: $ => choice(
|
|
seq("'", optional(alias(/[^']+/, $.attribute_value)), "'"),
|
|
seq('"', optional(alias(/[^"]+/, $.attribute_value)), '"')
|
|
),
|
|
|
|
end_tag: $ => seq(
|
|
'</',
|
|
choice($.tag_name, $.void_tag_name),
|
|
'>'
|
|
),
|
|
|
|
tag_name: $ => /[a-zA-Z\-]+/,
|
|
|
|
void_tag_name: $ => token(prec(1, choice(
|
|
'area',
|
|
'base',
|
|
'basefont',
|
|
'bgsound',
|
|
'br',
|
|
'col',
|
|
'command',
|
|
'embed',
|
|
'frame',
|
|
'hr',
|
|
'image',
|
|
'img',
|
|
'input',
|
|
'isindex',
|
|
'keygen',
|
|
'link',
|
|
'menuitem',
|
|
'meta',
|
|
'nextid',
|
|
'param',
|
|
'source',
|
|
'track',
|
|
'wbr'
|
|
))),
|
|
|
|
text: $ => /[^<>]+/
|
|
}
|
|
});
|