Diffdown is a real-time collaborative Markdown editor/previewer built on the AT Protocol diffdown.com
at 864c8fd63cccd160a05f67a7ce42eac86768c97c 181 lines 4.8 kB view raw
1@top Document { (entity | DoctypeDecl)+ } 2 3@dialects { noMatch, selfClosing } 4 5entity[@isGroup=Entity] { 6 Text | 7 EntityReference | 8 CharacterReference | 9 InvalidEntity | 10 Element | 11 Comment | 12 ProcessingInst | 13 IncompleteTag | 14 IncompleteCloseTag | 15 MismatchedCloseTag | 16 NoMatchCloseTag 17} 18 19Element { 20 OpenScriptTag ScriptText (CloseScriptTag | missingCloseTag) | 21 OpenStyleTag StyleText (CloseStyleTag | missingCloseTag) | 22 OpenTextareaTag TextareaText (CloseTextareaTag | missingCloseTag) | 23 OpenTag entity* (CloseTag | missingCloseTag) | 24 SelfClosingTag 25} 26 27ScriptText[group="TextContent Entity"] { scriptText* } 28 29StyleText[group="TextContent Entity"] { styleText* } 30 31TextareaText[group="TextContent Entity"] { textareaText* } 32 33@skip { space } { 34 OpenTag[closedBy=CloseTag,isolate=ltr] { 35 StartTag TagName Attribute* EndTag 36 } 37 38 SelfClosingTag[isolate=ltr] { 39 StartSelfClosingTag TagName Attribute* (EndTag | SelfClosingEndTag) | 40 (StartTag | StartScriptTag | StartStyleTag | StartTextareaTag) TagName Attribute* SelfClosingEndTag 41 } 42 43 MismatchedCloseTag[isolate=ltr] { 44 MismatchedStartCloseTag TagName EndTag 45 } 46 47 NoMatchCloseTag[@name=CloseTag,isolate=ltr] { 48 NoMatchStartCloseTag TagName EndTag 49 } 50 51 CloseTag[openedBy=OpenTag,isolate=ltr] { 52 StartCloseTag TagName EndTag 53 } 54 55 OpenScriptTag[@name=OpenTag,closedBy=CloseTag,isolate=ltr] { 56 StartScriptTag TagName Attribute* EndTag 57 } 58 59 CloseScriptTag[@name=CloseTag,openedBy=OpenTag,isolate=ltr] { 60 StartCloseScriptTag TagName EndTag 61 } 62 63 OpenStyleTag[@name=OpenTag,closedBy=CloseTag,isolate=ltr] { 64 StartStyleTag TagName Attribute* EndTag 65 } 66 67 CloseStyleTag[@name=CloseTag,openedBy=OpenTag,isolate=ltr] { 68 StartCloseStyleTag TagName EndTag 69 } 70 71 OpenTextareaTag[@name=OpenTag,closedBy=CloseTag,isolate=ltr] { 72 StartTextareaTag TagName Attribute* EndTag 73 } 74 75 CloseTextareaTag[@name=CloseTag,openedBy=OpenTag,isolate=ltr] { 76 StartCloseTextareaTag TagName EndTag 77 } 78 79 Attribute { 80 AttributeName (Is (AttributeValue | UnquotedAttributeValue))? 81 } 82} 83 84AttributeValue[isolate] { 85 "\"" (attributeContentDouble | EntityReference | CharacterReference | InvalidEntity)* "\"" | 86 "\'" (attributeContentSingle | EntityReference | CharacterReference | InvalidEntity)* "\'" 87} 88 89Comment[isolate] { commentStart commentContent* commentEnd } 90 91@context elementContext from "./tokens.js" 92 93@external tokens scriptTokens from "./tokens.js" { 94 scriptText 95 StartCloseScriptTag[@name=StartCloseTag,closedBy=EndTag] 96} 97 98@external tokens styleTokens from "./tokens.js" { 99 styleText 100 StartCloseStyleTag[@name=StartCloseTag,closedBy=EndTag] 101} 102 103@external tokens textareaTokens from "./tokens.js" { 104 textareaText 105 StartCloseTextareaTag[@name=StartCloseTag,closedBy=EndTag] 106} 107 108@external tokens endTag from "./tokens.js" { 109 EndTag[openedBy="StartTag StartCloseTag"] 110 SelfClosingEndTag[openedBy=StartTag,@dialect=selfClosing] 111} 112 113@external tokens tagStart from "./tokens.js" { 114 StartTag[closedBy="EndTag SelfClosingEndTag"], 115 StartScriptTag[@name=StartTag,closedBy=EndTag], 116 StartStyleTag[@name=StartTag,closedBy=EndTag], 117 StartTextareaTag[@name=StartTag,closedBy=EndTag], 118 StartSelfClosingTag[@name=StartTag,closedBy=EndTag], 119 StartCloseTag[closedBy=EndTag], 120 NoMatchStartCloseTag[@name=StartCloseTag,closedBy=EndTag] 121 MismatchedStartCloseTag[@name=StartCloseTag,closedBy=EndTag], 122 missingCloseTag, 123 IncompleteTag, 124 IncompleteCloseTag 125} 126 127@external tokens commentContent from "./tokens.js" { 128 commentContent 129} 130 131@tokens { 132 nameStart { 133 ":" | @asciiLetter | "_" | 134 $[\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D] | 135 $[\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\u{10000}-\u{EFFFF}] 136 } 137 138 nameChar { 139 nameStart | "-" | "." | @digit | $[\u00B7\u0300-\u036F\u203F-\u2040] 140 } 141 142 identifier { nameStart nameChar* } 143 144 TagName { identifier } 145 146 AttributeName { ![\u0000-\u0020\u007F-\u009F"'<>/=\uFDD0-\uFDEF\uFFFE\uFFFF]+ } 147 148 UnquotedAttributeValue[isolate] { ![ \t\n\r\u000C=<>"'`]+ } 149 150 attributeContentDouble { !["&]+ } 151 152 attributeContentSingle { !['&]+ } 153 154 Is { "=" } 155 156 EntityReference { "&" ![#; ]+ ";" } 157 158 CharacterReference { "&#" ![; ]+ ";" } 159 160 InvalidEntity { "&" } 161 162 @precedence { CharacterReference, EntityReference, InvalidEntity } 163 164 Text[group=TextContent] { ![<&]+ } 165 166 commentStart { "<!--" } 167 commentEnd { "-->" } 168 169 ProcessingInst { "<?" piContent } 170 171 piContent { ![?] piContent | "?" piQuestion } 172 piQuestion { ![>] piContent | ">" } 173 174 DoctypeDecl { "<!" ("doctype" | "DOCTYPE") ![>]* ">" } 175 176 @precedence { commentStart, ProcessingInst, DoctypeDecl } 177 178 space { (" " | "\t" | "\r" | "\n")+ } 179} 180 181@external propSource htmlHighlighting from "./highlight"