Mercurial > yakumo_izuru > aya
comparison vendor/github.com/eknkc/amber/parser/nodes.go @ 66:787b5ee0289d draft
Use vendored modules
Signed-off-by: Izuru Yakumo <yakumo.izuru@chaotic.ninja>
author | yakumo.izuru |
---|---|
date | Sun, 23 Jul 2023 13:18:53 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
65:6d985efa0f7a | 66:787b5ee0289d |
---|---|
1 package parser | |
2 | |
3 import ( | |
4 "regexp" | |
5 "strings" | |
6 ) | |
7 | |
8 var selfClosingTags = [...]string{ | |
9 "meta", | |
10 "img", | |
11 "link", | |
12 "input", | |
13 "source", | |
14 "area", | |
15 "base", | |
16 "col", | |
17 "br", | |
18 "hr", | |
19 } | |
20 | |
21 var doctypes = map[string]string{ | |
22 "5": `<!DOCTYPE html>`, | |
23 "default": `<!DOCTYPE html>`, | |
24 "xml": `<?xml version="1.0" encoding="utf-8" ?>`, | |
25 "transitional": `<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">`, | |
26 "strict": `<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">`, | |
27 "frameset": `<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">`, | |
28 "1.1": `<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">`, | |
29 "basic": `<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN" "http://www.w3.org/TR/xhtml-basic/xhtml-basic11.dtd">`, | |
30 "mobile": `<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.2//EN" "http://www.openmobilealliance.org/tech/DTD/xhtml-mobile12.dtd">`, | |
31 } | |
32 | |
33 type Node interface { | |
34 Pos() SourcePosition | |
35 } | |
36 | |
37 type SourcePosition struct { | |
38 LineNum int | |
39 ColNum int | |
40 TokenLength int | |
41 Filename string | |
42 } | |
43 | |
44 func (s *SourcePosition) Pos() SourcePosition { | |
45 return *s | |
46 } | |
47 | |
48 type Doctype struct { | |
49 SourcePosition | |
50 Value string | |
51 } | |
52 | |
53 func newDoctype(value string) *Doctype { | |
54 dt := new(Doctype) | |
55 dt.Value = value | |
56 return dt | |
57 } | |
58 | |
59 func (d *Doctype) String() string { | |
60 if defined := doctypes[d.Value]; len(defined) != 0 { | |
61 return defined | |
62 } | |
63 | |
64 return `<!DOCTYPE ` + d.Value + `>` | |
65 } | |
66 | |
67 type Comment struct { | |
68 SourcePosition | |
69 Value string | |
70 Block *Block | |
71 Silent bool | |
72 } | |
73 | |
74 func newComment(value string) *Comment { | |
75 dt := new(Comment) | |
76 dt.Value = value | |
77 dt.Block = nil | |
78 dt.Silent = false | |
79 return dt | |
80 } | |
81 | |
82 type Text struct { | |
83 SourcePosition | |
84 Value string | |
85 Raw bool | |
86 } | |
87 | |
88 func newText(value string, raw bool) *Text { | |
89 dt := new(Text) | |
90 dt.Value = value | |
91 dt.Raw = raw | |
92 return dt | |
93 } | |
94 | |
95 type Block struct { | |
96 SourcePosition | |
97 Children []Node | |
98 } | |
99 | |
100 func newBlock() *Block { | |
101 block := new(Block) | |
102 block.Children = make([]Node, 0) | |
103 return block | |
104 } | |
105 | |
106 func (b *Block) push(node Node) { | |
107 b.Children = append(b.Children, node) | |
108 } | |
109 | |
110 func (b *Block) pushFront(node Node) { | |
111 b.Children = append([]Node{node}, b.Children...) | |
112 } | |
113 | |
114 func (b *Block) CanInline() bool { | |
115 if len(b.Children) == 0 { | |
116 return true | |
117 } | |
118 | |
119 allText := true | |
120 | |
121 for _, child := range b.Children { | |
122 if txt, ok := child.(*Text); !ok || txt.Raw { | |
123 allText = false | |
124 break | |
125 } | |
126 } | |
127 | |
128 return allText | |
129 } | |
130 | |
131 const ( | |
132 NamedBlockDefault = iota | |
133 NamedBlockAppend | |
134 NamedBlockPrepend | |
135 ) | |
136 | |
137 type NamedBlock struct { | |
138 Block | |
139 Name string | |
140 Modifier int | |
141 } | |
142 | |
143 func newNamedBlock(name string) *NamedBlock { | |
144 bb := new(NamedBlock) | |
145 bb.Name = name | |
146 bb.Block.Children = make([]Node, 0) | |
147 bb.Modifier = NamedBlockDefault | |
148 return bb | |
149 } | |
150 | |
151 type Attribute struct { | |
152 SourcePosition | |
153 Name string | |
154 Value string | |
155 IsRaw bool | |
156 Condition string | |
157 } | |
158 | |
159 type Tag struct { | |
160 SourcePosition | |
161 Block *Block | |
162 Name string | |
163 IsInterpolated bool | |
164 Attributes []Attribute | |
165 } | |
166 | |
167 func newTag(name string) *Tag { | |
168 tag := new(Tag) | |
169 tag.Block = nil | |
170 tag.Name = name | |
171 tag.Attributes = make([]Attribute, 0) | |
172 tag.IsInterpolated = false | |
173 return tag | |
174 | |
175 } | |
176 | |
177 func (t *Tag) IsSelfClosing() bool { | |
178 for _, tag := range selfClosingTags { | |
179 if tag == t.Name { | |
180 return true | |
181 } | |
182 } | |
183 | |
184 return false | |
185 } | |
186 | |
187 func (t *Tag) IsRawText() bool { | |
188 return t.Name == "style" || t.Name == "script" | |
189 } | |
190 | |
191 type Condition struct { | |
192 SourcePosition | |
193 Positive *Block | |
194 Negative *Block | |
195 Expression string | |
196 } | |
197 | |
198 func newCondition(exp string) *Condition { | |
199 cond := new(Condition) | |
200 cond.Expression = exp | |
201 return cond | |
202 } | |
203 | |
204 type Each struct { | |
205 SourcePosition | |
206 X string | |
207 Y string | |
208 Expression string | |
209 Block *Block | |
210 } | |
211 | |
212 func newEach(exp string) *Each { | |
213 each := new(Each) | |
214 each.Expression = exp | |
215 return each | |
216 } | |
217 | |
218 type Assignment struct { | |
219 SourcePosition | |
220 X string | |
221 Expression string | |
222 } | |
223 | |
224 func newAssignment(x, expression string) *Assignment { | |
225 assgn := new(Assignment) | |
226 assgn.X = x | |
227 assgn.Expression = expression | |
228 return assgn | |
229 } | |
230 | |
231 type Mixin struct { | |
232 SourcePosition | |
233 Block *Block | |
234 Name string | |
235 Args []string | |
236 } | |
237 | |
238 func newMixin(name, args string) *Mixin { | |
239 mixin := new(Mixin) | |
240 mixin.Name = name | |
241 | |
242 delExp := regexp.MustCompile(`,\s`) | |
243 mixin.Args = delExp.Split(args, -1) | |
244 | |
245 for i := 0; i < len(mixin.Args); i++ { | |
246 mixin.Args[i] = strings.TrimSpace(mixin.Args[i]) | |
247 if mixin.Args[i] == "" { | |
248 mixin.Args = append(mixin.Args[:i], mixin.Args[i+1:]...) | |
249 i-- | |
250 } | |
251 } | |
252 | |
253 return mixin | |
254 } | |
255 | |
256 type MixinCall struct { | |
257 SourcePosition | |
258 Name string | |
259 Args []string | |
260 } | |
261 | |
262 func newMixinCall(name, args string) *MixinCall { | |
263 mixinCall := new(MixinCall) | |
264 mixinCall.Name = name | |
265 | |
266 if args != "" { | |
267 const t = "%s" | |
268 quoteExp := regexp.MustCompile(`"(.*?)"`) | |
269 delExp := regexp.MustCompile(`,\s`) | |
270 | |
271 quotes := quoteExp.FindAllString(args, -1) | |
272 replaced := quoteExp.ReplaceAllString(args, t) | |
273 mixinCall.Args = delExp.Split(replaced, -1) | |
274 | |
275 qi := 0 | |
276 for i, arg := range mixinCall.Args { | |
277 if arg == t { | |
278 mixinCall.Args[i] = quotes[qi] | |
279 qi++ | |
280 } | |
281 } | |
282 } | |
283 | |
284 return mixinCall | |
285 } |