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