Mercurial Hosting > luan
annotate core/src/luan/modules/parsers/BBCode.java @ 638:3ab4f282f0bd 0.16
minor
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Thu, 03 Mar 2016 22:52:41 -0700 |
parents | 6ea90dc10375 |
children | cdc70de628b5 |
rev | line source |
---|---|
585 | 1 package luan.modules.parsers; |
2 | |
637
6ea90dc10375
bbcode parser now takes a quoter function
Franklin Schmidt <fschmidt@gmail.com>
parents:
588
diff
changeset
|
3 import java.util.List; |
6ea90dc10375
bbcode parser now takes a quoter function
Franklin Schmidt <fschmidt@gmail.com>
parents:
588
diff
changeset
|
4 import java.util.ArrayList; |
6ea90dc10375
bbcode parser now takes a quoter function
Franklin Schmidt <fschmidt@gmail.com>
parents:
588
diff
changeset
|
5 import luan.Luan; |
6ea90dc10375
bbcode parser now takes a quoter function
Franklin Schmidt <fschmidt@gmail.com>
parents:
588
diff
changeset
|
6 import luan.LuanState; |
6ea90dc10375
bbcode parser now takes a quoter function
Franklin Schmidt <fschmidt@gmail.com>
parents:
588
diff
changeset
|
7 import luan.LuanFunction; |
6ea90dc10375
bbcode parser now takes a quoter function
Franklin Schmidt <fschmidt@gmail.com>
parents:
588
diff
changeset
|
8 import luan.LuanException; |
6ea90dc10375
bbcode parser now takes a quoter function
Franklin Schmidt <fschmidt@gmail.com>
parents:
588
diff
changeset
|
9 import luan.modules.Utils; |
6ea90dc10375
bbcode parser now takes a quoter function
Franklin Schmidt <fschmidt@gmail.com>
parents:
588
diff
changeset
|
10 |
585 | 11 |
12 public final class BBCode { | |
13 | |
637
6ea90dc10375
bbcode parser now takes a quoter function
Franklin Schmidt <fschmidt@gmail.com>
parents:
588
diff
changeset
|
14 public static String toHtml(LuanState luan,String bbcode,LuanFunction quoter) throws LuanException { |
638 | 15 return new BBCode(luan,bbcode,quoter,true).parse(); |
585 | 16 } |
17 | |
637
6ea90dc10375
bbcode parser now takes a quoter function
Franklin Schmidt <fschmidt@gmail.com>
parents:
588
diff
changeset
|
18 public static String toText(LuanState luan,String bbcode,LuanFunction quoter) throws LuanException { |
638 | 19 return new BBCode(luan,bbcode,quoter,false).parse(); |
585 | 20 } |
21 | |
637
6ea90dc10375
bbcode parser now takes a quoter function
Franklin Schmidt <fschmidt@gmail.com>
parents:
588
diff
changeset
|
22 private final LuanState luan; |
585 | 23 private final Parser parser; |
638 | 24 private final LuanFunction quoter; |
585 | 25 private final boolean toHtml; |
26 | |
638 | 27 private BBCode(LuanState luan,String text,LuanFunction quoter,boolean toHtml) throws LuanException { |
637
6ea90dc10375
bbcode parser now takes a quoter function
Franklin Schmidt <fschmidt@gmail.com>
parents:
588
diff
changeset
|
28 Utils.checkNotNull(luan,text,1); |
638 | 29 Utils.checkNotNull(luan,quoter,2); |
637
6ea90dc10375
bbcode parser now takes a quoter function
Franklin Schmidt <fschmidt@gmail.com>
parents:
588
diff
changeset
|
30 this.luan = luan; |
585 | 31 this.parser = new Parser(text); |
638 | 32 this.quoter = quoter; |
585 | 33 this.toHtml = toHtml; |
34 } | |
35 | |
637
6ea90dc10375
bbcode parser now takes a quoter function
Franklin Schmidt <fschmidt@gmail.com>
parents:
588
diff
changeset
|
36 private String parse() throws LuanException { |
585 | 37 StringBuilder sb = new StringBuilder(); |
38 while( !parser.endOfInput() ) { | |
39 String block = parseBlock(); | |
40 if( block != null ) | |
41 sb.append(block); | |
42 else { | |
43 sb.append( parser.currentChar() ); | |
44 parser.anyChar(); | |
45 } | |
46 } | |
47 return sb.toString(); | |
48 } | |
49 | |
637
6ea90dc10375
bbcode parser now takes a quoter function
Franklin Schmidt <fschmidt@gmail.com>
parents:
588
diff
changeset
|
50 private String parseWellFormed() throws LuanException { |
585 | 51 StringBuilder sb = new StringBuilder(); |
52 while( !parser.endOfInput() ) { | |
53 String block = parseBlock(); | |
54 if( block != null ) { | |
55 sb.append(block); | |
56 continue; | |
57 } | |
58 if( couldBeTag() ) | |
59 break; | |
60 sb.append( parser.currentChar() ); | |
61 parser.anyChar(); | |
62 } | |
63 return sb.toString(); | |
64 } | |
65 | |
66 private boolean couldBeTag() { | |
67 if( parser.currentChar() != '[' ) | |
68 return false; | |
69 return parser.testIgnoreCase("[b]") | |
70 || parser.testIgnoreCase("[/b]") | |
71 || parser.testIgnoreCase("[i]") | |
72 || parser.testIgnoreCase("[/i]") | |
73 || parser.testIgnoreCase("[u]") | |
74 || parser.testIgnoreCase("[/u]") | |
75 || parser.testIgnoreCase("[url]") | |
76 || parser.testIgnoreCase("[url=") | |
77 || parser.testIgnoreCase("[/url]") | |
78 || parser.testIgnoreCase("[code]") | |
79 || parser.testIgnoreCase("[/code]") | |
80 || parser.testIgnoreCase("[img]") | |
81 || parser.testIgnoreCase("[/img]") | |
82 || parser.testIgnoreCase("[color=") | |
83 || parser.testIgnoreCase("[/color]") | |
84 || parser.testIgnoreCase("[size=") | |
85 || parser.testIgnoreCase("[/size]") | |
86 || parser.testIgnoreCase("[youtube]") | |
87 || parser.testIgnoreCase("[/youtube]") | |
88 || parser.testIgnoreCase("[quote]") | |
89 || parser.testIgnoreCase("[quote=") | |
90 || parser.testIgnoreCase("[/quote]") | |
91 ; | |
92 } | |
93 | |
637
6ea90dc10375
bbcode parser now takes a quoter function
Franklin Schmidt <fschmidt@gmail.com>
parents:
588
diff
changeset
|
94 private String parseBlock() throws LuanException { |
585 | 95 if( parser.currentChar() != '[' ) |
96 return null; | |
97 String s; | |
98 s = parseB(); if(s!=null) return s; | |
99 s = parseI(); if(s!=null) return s; | |
100 s = parseU(); if(s!=null) return s; | |
101 s = parseUrl1(); if(s!=null) return s; | |
102 s = parseUrl2(); if(s!=null) return s; | |
103 s = parseCode(); if(s!=null) return s; | |
104 s = parseImg(); if(s!=null) return s; | |
105 s = parseColor(); if(s!=null) return s; | |
106 s = parseSize(); if(s!=null) return s; | |
107 s = parseYouTube(); if(s!=null) return s; | |
108 s = parseQuote1(); if(s!=null) return s; | |
109 s = parseQuote2(); if(s!=null) return s; | |
110 return null; | |
111 } | |
112 | |
637
6ea90dc10375
bbcode parser now takes a quoter function
Franklin Schmidt <fschmidt@gmail.com>
parents:
588
diff
changeset
|
113 private String parseB() throws LuanException { |
585 | 114 parser.begin(); |
115 if( !parser.matchIgnoreCase("[b]") ) | |
116 return parser.failure(null); | |
117 String content = parseWellFormed(); | |
118 if( !parser.matchIgnoreCase("[/b]") ) | |
119 return parser.failure(null); | |
120 String rtn = toHtml ? "<b>"+content+"</b>" : content; | |
121 return parser.success(rtn); | |
122 } | |
123 | |
637
6ea90dc10375
bbcode parser now takes a quoter function
Franklin Schmidt <fschmidt@gmail.com>
parents:
588
diff
changeset
|
124 private String parseI() throws LuanException { |
585 | 125 parser.begin(); |
126 if( !parser.matchIgnoreCase("[i]") ) | |
127 return parser.failure(null); | |
128 String content = parseWellFormed(); | |
129 if( !parser.matchIgnoreCase("[/i]") ) | |
130 return parser.failure(null); | |
131 String rtn = toHtml ? "<i>"+content+"</i>" : content; | |
132 return parser.success(rtn); | |
133 } | |
134 | |
637
6ea90dc10375
bbcode parser now takes a quoter function
Franklin Schmidt <fschmidt@gmail.com>
parents:
588
diff
changeset
|
135 private String parseU() throws LuanException { |
585 | 136 parser.begin(); |
137 if( !parser.matchIgnoreCase("[u]") ) | |
138 return parser.failure(null); | |
139 String content = parseWellFormed(); | |
140 if( !parser.matchIgnoreCase("[/u]") ) | |
141 return parser.failure(null); | |
142 String rtn = toHtml ? "<u>"+content+"</u>" : content; | |
143 return parser.success(rtn); | |
144 } | |
145 | |
146 private String parseUrl1() { | |
147 parser.begin(); | |
148 if( !parser.matchIgnoreCase("[url]") ) | |
149 return parser.failure(null); | |
150 String url = parseRealUrl(); | |
151 if( !parser.matchIgnoreCase("[/url]") ) | |
152 return parser.failure(null); | |
153 String rtn = toHtml ? "<a href='"+url+"'>"+url+"</u>" : url; | |
154 return parser.success(rtn); | |
155 } | |
156 | |
637
6ea90dc10375
bbcode parser now takes a quoter function
Franklin Schmidt <fschmidt@gmail.com>
parents:
588
diff
changeset
|
157 private String parseUrl2() throws LuanException { |
585 | 158 parser.begin(); |
159 if( !parser.matchIgnoreCase("[url=") ) | |
160 return parser.failure(null); | |
161 String url = parseRealUrl(); | |
162 if( !parser.match(']') ) | |
163 return parser.failure(null); | |
164 String content = parseWellFormed(); | |
165 if( !parser.matchIgnoreCase("[/url]") ) | |
166 return parser.failure(null); | |
167 String rtn = toHtml ? "<a href='"+url+"'>"+content+"</u>" : content; | |
168 return parser.success(rtn); | |
169 } | |
170 | |
171 private String parseRealUrl() { | |
172 parser.begin(); | |
173 while( parser.match(' ') ); | |
174 int start = parser.currentIndex(); | |
175 if( !parser.matchIgnoreCase("http") ) | |
176 return parser.failure(null); | |
177 parser.matchIgnoreCase("s"); | |
178 if( !parser.matchIgnoreCase("://") ) | |
179 return parser.failure(null); | |
180 while( parser.noneOf(" []'") ); | |
181 String url = parser.textFrom(start); | |
182 while( parser.match(' ') ); | |
183 return parser.success(url); | |
184 } | |
185 | |
186 private String parseCode() { | |
187 parser.begin(); | |
188 if( !parser.matchIgnoreCase("[code]") ) | |
189 return parser.failure(null); | |
190 int start = parser.currentIndex(); | |
191 while( !parser.testIgnoreCase("[/code]") ) { | |
192 if( !parser.anyChar() ) | |
193 return parser.failure(null); | |
194 } | |
195 String content = parser.textFrom(start); | |
196 if( !parser.matchIgnoreCase("[/code]") ) throw new RuntimeException(); | |
197 String rtn = toHtml ? "<code>"+content+"</code>" : content; | |
198 return parser.success(rtn); | |
199 } | |
200 | |
201 private String parseImg() { | |
202 parser.begin(); | |
203 if( !parser.matchIgnoreCase("[img]") ) | |
204 return parser.failure(null); | |
205 String url = parseRealUrl(); | |
206 if( !parser.matchIgnoreCase("[/img]") ) | |
207 return parser.failure(null); | |
208 String rtn = toHtml ? "<img src='"+url+"'>" : ""; | |
209 return parser.success(rtn); | |
210 } | |
211 | |
637
6ea90dc10375
bbcode parser now takes a quoter function
Franklin Schmidt <fschmidt@gmail.com>
parents:
588
diff
changeset
|
212 private String parseColor() throws LuanException { |
585 | 213 parser.begin(); |
214 if( !parser.matchIgnoreCase("[color=") ) | |
215 return parser.failure(null); | |
216 int start = parser.currentIndex(); | |
217 parser.match('#'); | |
218 while( parser.inCharRange('0','9') | |
219 || parser.inCharRange('a','z') | |
220 || parser.inCharRange('A','Z') | |
221 ); | |
222 String color = parser.textFrom(start); | |
223 if( !parser.match(']') ) | |
224 return parser.failure(null); | |
225 String content = parseWellFormed(); | |
226 if( !parser.matchIgnoreCase("[/color]") ) | |
227 return parser.failure(null); | |
228 String rtn = toHtml ? "<span style='color: "+color+"'>"+content+"</span>" : content; | |
229 return parser.success(rtn); | |
230 } | |
231 | |
637
6ea90dc10375
bbcode parser now takes a quoter function
Franklin Schmidt <fschmidt@gmail.com>
parents:
588
diff
changeset
|
232 private String parseSize() throws LuanException { |
585 | 233 parser.begin(); |
234 if( !parser.matchIgnoreCase("[size=") ) | |
235 return parser.failure(null); | |
236 int start = parser.currentIndex(); | |
237 while( parser.match('.') || parser.inCharRange('0','9') ); | |
238 String size = parser.textFrom(start); | |
239 if( !parser.match(']') ) | |
240 return parser.failure(null); | |
241 String content = parseWellFormed(); | |
242 if( !parser.matchIgnoreCase("[/size]") ) | |
243 return parser.failure(null); | |
244 String rtn = toHtml ? "<span style='font-size: "+size+"em'>"+content+"</span>" : content; | |
245 return parser.success(rtn); | |
246 } | |
247 | |
248 private String parseYouTube() { | |
249 parser.begin(); | |
250 if( !parser.matchIgnoreCase("[youtube]") ) | |
251 return parser.failure(null); | |
252 int start = parser.currentIndex(); | |
253 while( parser.inCharRange('0','9') | |
254 || parser.inCharRange('a','z') | |
255 || parser.inCharRange('A','Z') | |
256 || parser.match('-') | |
257 || parser.match('_') | |
258 ); | |
259 String id = parser.textFrom(start); | |
260 if( id.length()==0 || !parser.matchIgnoreCase("[/youtube]") ) | |
261 return parser.failure(null); | |
262 String rtn = toHtml ? "<iframe width='420' height='315' src='https://www.youtube.com/embed/"+id+"' frameborder='0' allowfullscreen></iframe>" : ""; | |
263 return parser.success(rtn); | |
264 } | |
265 | |
637
6ea90dc10375
bbcode parser now takes a quoter function
Franklin Schmidt <fschmidt@gmail.com>
parents:
588
diff
changeset
|
266 private String quote(Object... args) throws LuanException { |
6ea90dc10375
bbcode parser now takes a quoter function
Franklin Schmidt <fschmidt@gmail.com>
parents:
588
diff
changeset
|
267 Object obj = quoter.call(luan,args); |
6ea90dc10375
bbcode parser now takes a quoter function
Franklin Schmidt <fschmidt@gmail.com>
parents:
588
diff
changeset
|
268 if( !(obj instanceof String) ) |
6ea90dc10375
bbcode parser now takes a quoter function
Franklin Schmidt <fschmidt@gmail.com>
parents:
588
diff
changeset
|
269 throw new LuanException(luan,"BBCode quoter function returned "+Luan.type(obj)+" but string required"); |
6ea90dc10375
bbcode parser now takes a quoter function
Franklin Schmidt <fschmidt@gmail.com>
parents:
588
diff
changeset
|
270 return (String)obj; |
6ea90dc10375
bbcode parser now takes a quoter function
Franklin Schmidt <fschmidt@gmail.com>
parents:
588
diff
changeset
|
271 } |
6ea90dc10375
bbcode parser now takes a quoter function
Franklin Schmidt <fschmidt@gmail.com>
parents:
588
diff
changeset
|
272 |
6ea90dc10375
bbcode parser now takes a quoter function
Franklin Schmidt <fschmidt@gmail.com>
parents:
588
diff
changeset
|
273 private String parseQuote1() throws LuanException { |
585 | 274 parser.begin(); |
275 if( !parser.matchIgnoreCase("[quote]") ) | |
276 return parser.failure(null); | |
277 String content = parseWellFormed(); | |
278 if( !parser.matchIgnoreCase("[/quote]") ) | |
279 return parser.failure(null); | |
637
6ea90dc10375
bbcode parser now takes a quoter function
Franklin Schmidt <fschmidt@gmail.com>
parents:
588
diff
changeset
|
280 String rtn = quote(content); |
585 | 281 return parser.success(rtn); |
282 } | |
283 | |
637
6ea90dc10375
bbcode parser now takes a quoter function
Franklin Schmidt <fschmidt@gmail.com>
parents:
588
diff
changeset
|
284 private String parseQuote2() throws LuanException { |
585 | 285 parser.begin(); |
286 if( !parser.matchIgnoreCase("[quote=") ) | |
287 return parser.failure(null); | |
637
6ea90dc10375
bbcode parser now takes a quoter function
Franklin Schmidt <fschmidt@gmail.com>
parents:
588
diff
changeset
|
288 List args = new ArrayList(); |
585 | 289 int start = parser.currentIndex(); |
290 while( parser.noneOf("[];") ); | |
291 String name = parser.textFrom(start).trim(); | |
292 if( name.length() == 0 ) | |
293 return parser.failure(null); | |
637
6ea90dc10375
bbcode parser now takes a quoter function
Franklin Schmidt <fschmidt@gmail.com>
parents:
588
diff
changeset
|
294 args.add(name); |
6ea90dc10375
bbcode parser now takes a quoter function
Franklin Schmidt <fschmidt@gmail.com>
parents:
588
diff
changeset
|
295 while( parser.match(';') ) { |
585 | 296 start = parser.currentIndex(); |
637
6ea90dc10375
bbcode parser now takes a quoter function
Franklin Schmidt <fschmidt@gmail.com>
parents:
588
diff
changeset
|
297 while( parser.noneOf("[];'") ); |
6ea90dc10375
bbcode parser now takes a quoter function
Franklin Schmidt <fschmidt@gmail.com>
parents:
588
diff
changeset
|
298 String src = parser.textFrom(start).trim(); |
6ea90dc10375
bbcode parser now takes a quoter function
Franklin Schmidt <fschmidt@gmail.com>
parents:
588
diff
changeset
|
299 args.add(src); |
585 | 300 } |
301 if( !parser.match(']') ) | |
302 return parser.failure(null); | |
303 String content = parseWellFormed(); | |
637
6ea90dc10375
bbcode parser now takes a quoter function
Franklin Schmidt <fschmidt@gmail.com>
parents:
588
diff
changeset
|
304 args.add(0,content); |
585 | 305 if( !parser.matchIgnoreCase("[/quote]") ) |
306 return parser.failure(null); | |
637
6ea90dc10375
bbcode parser now takes a quoter function
Franklin Schmidt <fschmidt@gmail.com>
parents:
588
diff
changeset
|
307 String rtn = quote(args.toArray()); |
6ea90dc10375
bbcode parser now takes a quoter function
Franklin Schmidt <fschmidt@gmail.com>
parents:
588
diff
changeset
|
308 return parser.success(rtn); |
585 | 309 } |
310 | |
311 } |