Mercurial Hosting > luan
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/src/luan/modules/parsers/BBCode.java Fri Aug 14 06:35:20 2015 -0600 @@ -0,0 +1,298 @@ +package luan.modules.parsers; + + +public final class BBCode { + + public static String toHtml(String bbcode) { + return new BBCode(bbcode,true).parse(); + } + + public static String toText(String bbcode) { + return new BBCode(bbcode,false).parse(); + } + + private final Parser parser; + private final boolean toHtml; + + private BBCode(String text,boolean toHtml) { + this.parser = new Parser(text); + this.toHtml = toHtml; + } + + private String parse() { + StringBuilder sb = new StringBuilder(); + while( !parser.endOfInput() ) { + String block = parseBlock(); + if( block != null ) + sb.append(block); + else { + sb.append( parser.currentChar() ); + parser.anyChar(); + } + } + return sb.toString(); + } + + private String parseWellFormed() { + StringBuilder sb = new StringBuilder(); + while( !parser.endOfInput() ) { + String block = parseBlock(); + if( block != null ) { + sb.append(block); + continue; + } + if( couldBeTag() ) + break; + sb.append( parser.currentChar() ); + parser.anyChar(); + } + return sb.toString(); + } + + private boolean couldBeTag() { + if( parser.currentChar() != '[' ) + return false; + return parser.testIgnoreCase("[b]") + || parser.testIgnoreCase("[/b]") + || parser.testIgnoreCase("[i]") + || parser.testIgnoreCase("[/i]") + || parser.testIgnoreCase("[u]") + || parser.testIgnoreCase("[/u]") + || parser.testIgnoreCase("[url]") + || parser.testIgnoreCase("[url=") + || parser.testIgnoreCase("[/url]") + || parser.testIgnoreCase("[code]") + || parser.testIgnoreCase("[/code]") + || parser.testIgnoreCase("[img]") + || parser.testIgnoreCase("[/img]") + || parser.testIgnoreCase("[color=") + || parser.testIgnoreCase("[/color]") + || parser.testIgnoreCase("[size=") + || parser.testIgnoreCase("[/size]") + || parser.testIgnoreCase("[youtube]") + || parser.testIgnoreCase("[/youtube]") + || parser.testIgnoreCase("[quote]") + || parser.testIgnoreCase("[quote=") + || parser.testIgnoreCase("[/quote]") + ; + } + + private String parseBlock() { + if( parser.currentChar() != '[' ) + return null; + String s; + s = parseB(); if(s!=null) return s; + s = parseI(); if(s!=null) return s; + s = parseU(); if(s!=null) return s; + s = parseUrl1(); if(s!=null) return s; + s = parseUrl2(); if(s!=null) return s; + s = parseCode(); if(s!=null) return s; + s = parseImg(); if(s!=null) return s; + s = parseColor(); if(s!=null) return s; + s = parseSize(); if(s!=null) return s; + s = parseYouTube(); if(s!=null) return s; + s = parseQuote1(); if(s!=null) return s; + s = parseQuote2(); if(s!=null) return s; + return null; + } + + private String parseB() { + parser.begin(); + if( !parser.matchIgnoreCase("[b]") ) + return parser.failure(null); + String content = parseWellFormed(); + if( !parser.matchIgnoreCase("[/b]") ) + return parser.failure(null); + String rtn = toHtml ? "<b>"+content+"</b>" : content; + return parser.success(rtn); + } + + private String parseI() { + parser.begin(); + if( !parser.matchIgnoreCase("[i]") ) + return parser.failure(null); + String content = parseWellFormed(); + if( !parser.matchIgnoreCase("[/i]") ) + return parser.failure(null); + String rtn = toHtml ? "<i>"+content+"</i>" : content; + return parser.success(rtn); + } + + private String parseU() { + parser.begin(); + if( !parser.matchIgnoreCase("[u]") ) + return parser.failure(null); + String content = parseWellFormed(); + if( !parser.matchIgnoreCase("[/u]") ) + return parser.failure(null); + String rtn = toHtml ? "<u>"+content+"</u>" : content; + return parser.success(rtn); + } + + private String parseUrl1() { + parser.begin(); + if( !parser.matchIgnoreCase("[url]") ) + return parser.failure(null); + String url = parseRealUrl(); + if( !parser.matchIgnoreCase("[/url]") ) + return parser.failure(null); + String rtn = toHtml ? "<a href='"+url+"'>"+url+"</u>" : url; + return parser.success(rtn); + } + + private String parseUrl2() { + parser.begin(); + if( !parser.matchIgnoreCase("[url=") ) + return parser.failure(null); + String url = parseRealUrl(); + if( !parser.match(']') ) + return parser.failure(null); + String content = parseWellFormed(); + if( !parser.matchIgnoreCase("[/url]") ) + return parser.failure(null); + String rtn = toHtml ? "<a href='"+url+"'>"+content+"</u>" : content; + return parser.success(rtn); + } + + private String parseRealUrl() { + parser.begin(); + while( parser.match(' ') ); + int start = parser.currentIndex(); + if( !parser.matchIgnoreCase("http") ) + return parser.failure(null); + parser.matchIgnoreCase("s"); + if( !parser.matchIgnoreCase("://") ) + return parser.failure(null); + while( parser.noneOf(" []'") ); + String url = parser.textFrom(start); + while( parser.match(' ') ); + return parser.success(url); + } + + private String parseCode() { + parser.begin(); + if( !parser.matchIgnoreCase("[code]") ) + return parser.failure(null); + int start = parser.currentIndex(); + while( !parser.testIgnoreCase("[/code]") ) { + if( !parser.anyChar() ) + return parser.failure(null); + } + String content = parser.textFrom(start); + if( !parser.matchIgnoreCase("[/code]") ) throw new RuntimeException(); + String rtn = toHtml ? "<code>"+content+"</code>" : content; + return parser.success(rtn); + } + + private String parseImg() { + parser.begin(); + if( !parser.matchIgnoreCase("[img]") ) + return parser.failure(null); + String url = parseRealUrl(); + if( !parser.matchIgnoreCase("[/img]") ) + return parser.failure(null); + String rtn = toHtml ? "<img src='"+url+"'>" : ""; + return parser.success(rtn); + } + + private String parseColor() { + parser.begin(); + if( !parser.matchIgnoreCase("[color=") ) + return parser.failure(null); + int start = parser.currentIndex(); + parser.match('#'); + while( parser.inCharRange('0','9') + || parser.inCharRange('a','z') + || parser.inCharRange('A','Z') + ); + String color = parser.textFrom(start); + if( !parser.match(']') ) + return parser.failure(null); + String content = parseWellFormed(); + if( !parser.matchIgnoreCase("[/color]") ) + return parser.failure(null); + String rtn = toHtml ? "<span style='color: "+color+"'>"+content+"</span>" : content; + return parser.success(rtn); + } + + private String parseSize() { + parser.begin(); + if( !parser.matchIgnoreCase("[size=") ) + return parser.failure(null); + int start = parser.currentIndex(); + while( parser.match('.') || parser.inCharRange('0','9') ); + String size = parser.textFrom(start); + if( !parser.match(']') ) + return parser.failure(null); + String content = parseWellFormed(); + if( !parser.matchIgnoreCase("[/size]") ) + return parser.failure(null); + String rtn = toHtml ? "<span style='font-size: "+size+"em'>"+content+"</span>" : content; + return parser.success(rtn); + } + + private String parseYouTube() { + parser.begin(); + if( !parser.matchIgnoreCase("[youtube]") ) + return parser.failure(null); + int start = parser.currentIndex(); + while( parser.inCharRange('0','9') + || parser.inCharRange('a','z') + || parser.inCharRange('A','Z') + || parser.match('-') + || parser.match('_') + ); + String id = parser.textFrom(start); + if( id.length()==0 || !parser.matchIgnoreCase("[/youtube]") ) + return parser.failure(null); + String rtn = toHtml ? "<iframe width='420' height='315' src='https://www.youtube.com/embed/"+id+"' frameborder='0' allowfullscreen></iframe>" : ""; + return parser.success(rtn); + } + + private String parseQuote1() { + parser.begin(); + if( !parser.matchIgnoreCase("[quote]") ) + return parser.failure(null); + String content = parseWellFormed(); + if( !parser.matchIgnoreCase("[/quote]") ) + return parser.failure(null); + String rtn = toHtml ? "<blockquote>"+content+"</blockquote>" : ""; + return parser.success(rtn); + } + + private String parseQuote2() { + parser.begin(); + if( !parser.matchIgnoreCase("[quote=") ) + return parser.failure(null); + int start = parser.currentIndex(); + while( parser.noneOf("[];") ); + String name = parser.textFrom(start).trim(); + if( name.length() == 0 ) + return parser.failure(null); + String src = null; + if( parser.match(';') ) { + start = parser.currentIndex(); + while( parser.noneOf("[]'") ); + src = parser.textFrom(start).trim(); + if( src.length() == 0 ) + return parser.failure(null); + } + if( !parser.match(']') ) + return parser.failure(null); + String content = parseWellFormed(); + if( !parser.matchIgnoreCase("[/quote]") ) + return parser.failure(null); + if( !toHtml ) + return parser.success(""); + StringBuilder sb = new StringBuilder(); + sb.append( "<blockquote><div quoted>" ); + if( src != null ) + sb.append( "<a href='/thread?id=" ).append( src ).append( "'>" ); + sb.append( name ).append( " wrote" ); + if( src != null ) + sb.append( "</a>" ); + sb.append( ":</div>" ).append( content ).append( "</blockquote>" ); + return parser.success(sb.toString()); + } + +}