item.go (3759B)
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 import ( 17 "bytes" 18 "fmt" 19 "regexp" 20 "strconv" 21 22 "github.com/yuin/goldmark/util" 23 ) 24 25 type Item struct { 26 Type ItemType 27 Pos int 28 Val []byte 29 isString bool 30 } 31 32 type Items []Item 33 34 func (i Item) ValStr() string { 35 return string(i.Val) 36 } 37 38 func (i Item) ValTyped() any { 39 str := i.ValStr() 40 if i.isString { 41 // A quoted value that is a string even if it looks like a number etc. 42 return str 43 } 44 45 if boolRe.MatchString(str) { 46 return str == "true" 47 } 48 49 if intRe.MatchString(str) { 50 num, err := strconv.Atoi(str) 51 if err != nil { 52 return str 53 } 54 return num 55 } 56 57 if floatRe.MatchString(str) { 58 num, err := strconv.ParseFloat(str, 64) 59 if err != nil { 60 return str 61 } 62 return num 63 } 64 65 return str 66 } 67 68 func (i Item) IsText() bool { 69 return i.Type == tText || i.Type == tIndentation 70 } 71 72 func (i Item) IsIndentation() bool { 73 return i.Type == tIndentation 74 } 75 76 func (i Item) IsNonWhitespace() bool { 77 return len(bytes.TrimSpace(i.Val)) > 0 78 } 79 80 func (i Item) IsShortcodeName() bool { 81 return i.Type == tScName 82 } 83 84 func (i Item) IsInlineShortcodeName() bool { 85 return i.Type == tScNameInline 86 } 87 88 func (i Item) IsLeftShortcodeDelim() bool { 89 return i.Type == tLeftDelimScWithMarkup || i.Type == tLeftDelimScNoMarkup 90 } 91 92 func (i Item) IsRightShortcodeDelim() bool { 93 return i.Type == tRightDelimScWithMarkup || i.Type == tRightDelimScNoMarkup 94 } 95 96 func (i Item) IsShortcodeClose() bool { 97 return i.Type == tScClose 98 } 99 100 func (i Item) IsShortcodeParam() bool { 101 return i.Type == tScParam 102 } 103 104 func (i Item) IsShortcodeParamVal() bool { 105 return i.Type == tScParamVal 106 } 107 108 func (i Item) IsShortcodeMarkupDelimiter() bool { 109 return i.Type == tLeftDelimScWithMarkup || i.Type == tRightDelimScWithMarkup 110 } 111 112 func (i Item) IsFrontMatter() bool { 113 return i.Type >= TypeFrontMatterYAML && i.Type <= TypeFrontMatterORG 114 } 115 116 func (i Item) IsDone() bool { 117 return i.Type == tError || i.Type == tEOF 118 } 119 120 func (i Item) IsEOF() bool { 121 return i.Type == tEOF 122 } 123 124 func (i Item) IsError() bool { 125 return i.Type == tError 126 } 127 128 func (i Item) String() string { 129 switch { 130 case i.Type == tEOF: 131 return "EOF" 132 case i.Type == tError: 133 return string(i.Val) 134 case i.Type == tIndentation: 135 return fmt.Sprintf("%s:[%s]", i.Type, util.VisualizeSpaces(i.Val)) 136 case i.Type > tKeywordMarker: 137 return fmt.Sprintf("<%s>", i.Val) 138 case len(i.Val) > 50: 139 return fmt.Sprintf("%v:%.20q...", i.Type, i.Val) 140 } 141 return fmt.Sprintf("%v:[%s]", i.Type, i.Val) 142 } 143 144 type ItemType int 145 146 const ( 147 tError ItemType = iota 148 tEOF 149 150 // page items 151 TypeLeadSummaryDivider // <!--more-->, # more 152 TypeFrontMatterYAML 153 TypeFrontMatterTOML 154 TypeFrontMatterJSON 155 TypeFrontMatterORG 156 TypeEmoji 157 TypeIgnore // // The BOM Unicode byte order marker and possibly others 158 159 // shortcode items 160 tLeftDelimScNoMarkup 161 tRightDelimScNoMarkup 162 tLeftDelimScWithMarkup 163 tRightDelimScWithMarkup 164 tScClose 165 tScName 166 tScNameInline 167 tScParam 168 tScParamVal 169 170 tIndentation 171 172 tText // plain text 173 174 // preserved for later - keywords come after this 175 tKeywordMarker 176 ) 177 178 var ( 179 boolRe = regexp.MustCompile(`^(true$)|(false$)`) 180 intRe = regexp.MustCompile(`^[-+]?\d+$`) 181 floatRe = regexp.MustCompile(`^[-+]?\d*\.\d+$`) 182 )