github.com/SuCicada/su-hugo@v1.0.0/parser/pageparser/pagelexer_intro.go (about)

     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  }