comparison core/src/luan/modules/parsers/BBCode.java @ 585:bb3818249dfb

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