pagelexer_intro.go (3813B)
1 // Copyright 2018 The Hugo Authors. All rights reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // http://www.apache.org/licenses/LICENSE-2.0 7 // 8 // Unless required by applicable law or agreed to in writing, software 9 // distributed under the License is distributed on an "AS IS" BASIS, 10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package pageparser 15 16 func lexIntroSection(l *pageLexer) stateFunc { 17 l.summaryDivider = summaryDivider 18 19 LOOP: 20 for { 21 r := l.next() 22 if r == eof { 23 break 24 } 25 26 switch { 27 case r == '+': 28 return l.lexFrontMatterSection(TypeFrontMatterTOML, r, "TOML", delimTOML) 29 case r == '-': 30 return l.lexFrontMatterSection(TypeFrontMatterYAML, r, "YAML", delimYAML) 31 case r == '{': 32 return lexFrontMatterJSON 33 case r == '#': 34 return lexFrontMatterOrgMode 35 case r == byteOrderMark: 36 l.emit(TypeIgnore) 37 case !isSpace(r) && !isEndOfLine(r): 38 if r == '<' { 39 l.backup() 40 if l.hasPrefix(htmlCommentStart) { 41 // This may be commented out front matter, which should 42 // still be read. 43 l.consumeToNextLine() 44 l.isInHTMLComment = true 45 l.emit(TypeIgnore) 46 continue LOOP 47 } else { 48 return l.errorf("plain HTML documents not supported") 49 } 50 } 51 break LOOP 52 } 53 } 54 55 // Now move on to the shortcodes. 56 return lexMainSection 57 } 58 59 func lexEndFrontMatterHTMLComment(l *pageLexer) stateFunc { 60 l.isInHTMLComment = false 61 right := l.index(htmlCommentEnd) 62 if right == -1 { 63 return l.errorf("starting HTML comment with no end") 64 } 65 l.pos += right + len(htmlCommentEnd) 66 l.emit(TypeIgnore) 67 68 // Now move on to the shortcodes. 69 return lexMainSection 70 } 71 72 func lexFrontMatterJSON(l *pageLexer) stateFunc { 73 // Include the left delimiter 74 l.backup() 75 76 var ( 77 inQuote bool 78 level int 79 ) 80 81 for { 82 83 r := l.next() 84 85 switch { 86 case r == eof: 87 return l.errorf("unexpected EOF parsing JSON front matter") 88 case r == '{': 89 if !inQuote { 90 level++ 91 } 92 case r == '}': 93 if !inQuote { 94 level-- 95 } 96 case r == '"': 97 inQuote = !inQuote 98 case r == '\\': 99 // This may be an escaped quote. Make sure it's not marked as a 100 // real one. 101 l.next() 102 } 103 104 if level == 0 { 105 break 106 } 107 } 108 109 l.consumeCRLF() 110 l.emit(TypeFrontMatterJSON) 111 112 return lexMainSection 113 } 114 115 func lexFrontMatterOrgMode(l *pageLexer) stateFunc { 116 /* 117 #+TITLE: Test File For chaseadamsio/goorgeous 118 #+AUTHOR: Chase Adams 119 #+DESCRIPTION: Just another golang parser for org content! 120 */ 121 122 l.summaryDivider = summaryDividerOrg 123 124 l.backup() 125 126 if !l.hasPrefix(delimOrg) { 127 return lexMainSection 128 } 129 130 // Read lines until we no longer see a #+ prefix 131 LOOP: 132 for { 133 134 r := l.next() 135 136 switch { 137 case r == '\n': 138 if !l.hasPrefix(delimOrg) { 139 break LOOP 140 } 141 case r == eof: 142 break LOOP 143 144 } 145 } 146 147 l.emit(TypeFrontMatterORG) 148 149 return lexMainSection 150 } 151 152 // Handle YAML or TOML front matter. 153 func (l *pageLexer) lexFrontMatterSection(tp ItemType, delimr rune, name string, delim []byte) stateFunc { 154 for i := 0; i < 2; i++ { 155 if r := l.next(); r != delimr { 156 return l.errorf("invalid %s delimiter", name) 157 } 158 } 159 160 // Let front matter start at line 1 161 wasEndOfLine := l.consumeCRLF() 162 // We don't care about the delimiters. 163 l.ignore() 164 165 var r rune 166 167 for { 168 if !wasEndOfLine { 169 r = l.next() 170 if r == eof { 171 return l.errorf("EOF looking for end %s front matter delimiter", name) 172 } 173 } 174 175 if wasEndOfLine || isEndOfLine(r) { 176 if l.hasPrefix(delim) { 177 l.emit(tp) 178 l.pos += 3 179 l.consumeCRLF() 180 l.ignore() 181 break 182 } 183 } 184 185 wasEndOfLine = false 186 } 187 188 return lexMainSection 189 }