module.exports = grammar({ name: 'html', extras: $ => [ $.comment, /\s+/, ], externals: $ => [ $._start_tag_name, $._script_start_tag_name, $._style_start_tag_name, $._end_tag_name, $.erroneous_end_tag_name, '/>', $._implicit_end_tag, $.raw_text, $.comment, ], rules: { fragment: $ => repeat($._node), doctype: $ => seq( ']+/, '>' ), _doctype: $ => /[Dd][Oo][Cc][Tt][Yy][Pp][Ee]/, _node: $ => choice( $.doctype, $.text, $.element, $.script_element, $.style_element, $.erroneous_end_tag ), element: $ => choice( seq( $.start_tag, repeat($._node), choice($.end_tag, $._implicit_end_tag) ), $.self_closing_tag ), script_element: $ => seq( alias($.script_start_tag, $.start_tag), optional($.raw_text), $.end_tag ), style_element: $ => seq( alias($.style_start_tag, $.start_tag), optional($.raw_text), $.end_tag ), start_tag: $ => seq( '<', alias($._start_tag_name, $.tag_name), repeat($.attribute), '>' ), script_start_tag: $ => seq( '<', alias($._script_start_tag_name, $.tag_name), repeat($.attribute), '>' ), style_start_tag: $ => seq( '<', alias($._style_start_tag_name, $.tag_name), repeat($.attribute), '>' ), self_closing_tag: $ => seq( '<', alias($._start_tag_name, $.tag_name), repeat($.attribute), '/>' ), end_tag: $ => seq( '' ), erroneous_end_tag: $ => seq( '' ), attribute: $ => seq( $.attribute_name, optional(seq( '=', choice( $.attribute_value, $.quoted_attribute_value ) )) ), attribute_name: $ => /[^<>"'/=\s]+/, attribute_value: $ => /[^<>"'=\s]+/, quoted_attribute_value: $ => choice( seq("'", optional(alias(/[^']+/, $.attribute_value)), "'"), seq('"', optional(alias(/[^"]+/, $.attribute_value)), '"') ), text: $ => /[^<>\s]([^<>]*[^<>\s])?/ } });