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 )