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