Mercurial Hosting > luan
changeset 1705:a6e27c8e7ef4
bbcode now returns data
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Sun, 03 Jul 2022 21:59:38 -0600 |
parents | 19df8abc9805 |
children | 93b9fd13a06c |
files | src/goodjava/bbcode/BBCode.java src/luan/modules/Parsers.luan src/luan/modules/parsers/BBCodeLuan.java |
diffstat | 3 files changed, 130 insertions(+), 152 deletions(-) [+] |
line wrap: on
line diff
--- a/src/goodjava/bbcode/BBCode.java Fri Jul 01 15:53:03 2022 -0600 +++ b/src/goodjava/bbcode/BBCode.java Sun Jul 03 21:59:38 2022 -0600 @@ -2,6 +2,8 @@ import java.util.List; import java.util.ArrayList; +import java.util.Map; +import java.util.LinkedHashMap; import java.util.regex.Matcher; import java.util.regex.Pattern; import goodjava.parser.Parser; @@ -9,59 +11,65 @@ public final class BBCode { - public enum Target { HTML, TEXT } + public final class Element { + public final String name; + public final String param; + public final Object contents; // String, Element, or List + public final Map<String,String> extra; + + private Element(String name,Object contents) { + this(name,null,contents); + } - public interface Quoter { - public String quote(Target target,String text,String param); + private Element(String name,String param,Object contents) { + this(name,param,contents,null); + } + + private Element(String name,String param,Object contents,Map<String,String> extra) { + this.name = name.toLowerCase(); + this.param = param; + this.contents = contents; + this.extra = extra; + } } - public static final Quoter defaultQuoter = new Quoter() { - public String quote(Target target,String text,String param) { - StringBuilder sb = new StringBuilder(); - sb.append( "<blockquote>" ); - if( param != null ) { - sb.append( htmlEncode(param) ); - sb.append( " wrote:\n" ); - } - sb.append( text ); - sb.append( "</blockquote>" ); - return sb.toString(); - } - }; + public static Object parse(String text) { + if( text.indexOf('[') == -1 ) + return text; + return new BBCode(text).parse(); + } - public Target target = Target.HTML; - public Quoter quoter = defaultQuoter; private final Parser parser; - public BBCode(String text) { + private BBCode(String text) { this.parser = new Parser(text); } - public String parse() { - StringBuilder sb = new StringBuilder(); + private Object parse() { + List list = new ArrayList(); StringBuilder text = new StringBuilder(); while( !parser.endOfInput() ) { - String block = parseBlock(); + Element block = parseBlock(); if( block != null ) { - sb.append( textToString(text) ); - sb.append(block); + add(list,text); + list.add( block ); } else { text.append( parser.currentChar() ); parser.anyChar(); } } - sb.append( textToString(text) ); - return sb.toString(); + add(list,text); + return list.size()==1 ? list.get(0) : list; } - private String parseWellFormed() { - StringBuilder sb = new StringBuilder(); + private Object parseWellFormed() { + List list = new ArrayList(); StringBuilder text = new StringBuilder(); while( !parser.endOfInput() ) { - String block = parseBlock(); + Element block = parseBlock(); if( block != null ) { - sb.append( textToString(text) ); - sb.append(block); + add(list,text); + list.add( block ); continue; } if( couldBeTag() ) @@ -69,16 +77,15 @@ text.append( parser.currentChar() ); parser.anyChar(); } - sb.append( textToString(text) ); - return sb.toString(); + add(list,text); + return list.size()==1 ? list.get(0) : list; } - private String textToString(StringBuilder text) { - String s = text.toString(); - text.setLength(0); - if( target == Target.HTML ) - s = htmlEncode(s); - return s; + private void add(List list,StringBuilder text) { + if( text.length() > 0 ) { + list.add( text.toString() ); + text.setLength(0); + } } private boolean couldBeTag() { @@ -109,10 +116,10 @@ ; } - private String parseBlock() { + private Element parseBlock() { if( parser.currentChar() != '[' ) return null; - String s; + Element s; s = parseB(); if(s!=null) return s; s = parseI(); if(s!=null) return s; s = parseU(); if(s!=null) return s; @@ -128,61 +135,61 @@ return null; } - private String parseB() { + private Element parseB() { parser.begin(); if( !parser.matchIgnoreCase("[b]") ) return parser.failure(null); - String content = parseWellFormed(); + Object content = parseWellFormed(); if( !parser.matchIgnoreCase("[/b]") ) return parser.failure(null); - String rtn = target==Target.HTML ? "<b>"+content+"</b>" : content; + Element rtn = new Element("b",content); return parser.success(rtn); } - private String parseI() { + private Element parseI() { parser.begin(); if( !parser.matchIgnoreCase("[i]") ) return parser.failure(null); - String content = parseWellFormed(); + Object content = parseWellFormed(); if( !parser.matchIgnoreCase("[/i]") ) return parser.failure(null); - String rtn = target==Target.HTML ? "<i>"+content+"</i>" : content; + Element rtn = new Element("i",content); return parser.success(rtn); } - private String parseU() { + private Element parseU() { parser.begin(); if( !parser.matchIgnoreCase("[u]") ) return parser.failure(null); - String content = parseWellFormed(); + Object content = parseWellFormed(); if( !parser.matchIgnoreCase("[/u]") ) return parser.failure(null); - String rtn = target==Target.HTML ? "<u>"+content+"</u>" : content; + Element rtn = new Element("u",content); return parser.success(rtn); } - private String parseUrl1() { + private Element parseUrl1() { parser.begin(); if( !parser.matchIgnoreCase("[url]") ) return parser.failure(null); String url = parseRealUrl(); if( !parser.matchIgnoreCase("[/url]") ) return parser.failure(null); - String rtn = target==Target.HTML ? "<a href='" + url + "'>" + url + "</a>" : url; + Element rtn = new Element("url",url); return parser.success(rtn); } - private String parseUrl2() { + private Element parseUrl2() { parser.begin(); if( !parser.matchIgnoreCase("[url=") ) return parser.failure(null); String url = parseRealUrl(); if( !parser.match(']') ) return parser.failure(null); - String content = parseWellFormed(); + Object content = parseWellFormed(); if( !parser.matchIgnoreCase("[/url]") ) return parser.failure(null); - String rtn = target==Target.HTML ? "<a href='" + url + "'>" + content + "</a>" : content; + Element rtn = new Element("url",url,content); return parser.success(rtn); } @@ -201,7 +208,7 @@ return parser.success(url); } - private String parseCode() { + private Element parseCode() { parser.begin(); if( !parser.matchIgnoreCase("[code]") ) return parser.failure(null); @@ -212,22 +219,22 @@ } String content = parser.textFrom(start); if( !parser.matchIgnoreCase("[/code]") ) throw new RuntimeException(); - String rtn = target==Target.HTML ? "<code>"+content+"</code>" : content; + Element rtn = new Element("code",content); return parser.success(rtn); } - private String parseImg() { + private Element parseImg() { parser.begin(); if( !parser.matchIgnoreCase("[img]") ) return parser.failure(null); String url = parseRealUrl(); if( !parser.matchIgnoreCase("[/img]") ) return parser.failure(null); - String rtn = target==Target.HTML ? "<img src='" + url + "'>" : ""; + Element rtn = new Element("img",url); return parser.success(rtn); } - private String parseColor() { + private Element parseColor() { parser.begin(); if( !parser.matchIgnoreCase("[color=") ) return parser.failure(null); @@ -240,14 +247,14 @@ String color = parser.textFrom(start); if( !parser.match(']') ) return parser.failure(null); - String content = parseWellFormed(); + Object content = parseWellFormed(); if( !parser.matchIgnoreCase("[/color]") ) return parser.failure(null); - String rtn = target==Target.HTML ? "<span style='color: "+color+"'>"+content+"</span>" : content; + Element rtn = new Element("color",color,content); return parser.success(rtn); } - private String parseSize() { + private Element parseSize() { parser.begin(); if( !parser.matchIgnoreCase("[size=") ) return parser.failure(null); @@ -256,10 +263,10 @@ String size = parser.textFrom(start); if( !parser.match(']') ) return parser.failure(null); - String content = parseWellFormed(); + Object content = parseWellFormed(); if( !parser.matchIgnoreCase("[/size]") ) return parser.failure(null); - String rtn = target==Target.HTML ? "<span style='font-size: "+size+"em'>"+content+"</span>" : content; + Element rtn = new Element("size",size,content); return parser.success(rtn); } @@ -272,55 +279,49 @@ return m.find() ? m : null; } - private String parseVideo() { + private Element parseVideo() { parser.begin(); if( !parser.matchIgnoreCase("[video]") ) return parser.failure(null); String url = parseRealUrl(); if( !parser.matchIgnoreCase("[/video]") ) return parser.failure(null); - if( target==Target.TEXT ) - return parser.success( "" ); + Map<String,String> extra = new LinkedHashMap<String,String>(); + Element rtn = new Element("video",null,url,extra); Matcher m; m = find(youtubePtn1,url); if( m == null ) m = find(youtubePtn2,url); if( m != null ) { - StringBuilder sb = new StringBuilder(); - sb.append( "<iframe width='420' height='315' src='https://www.youtube.com/embed/" ); - sb.append( m.group(1) ); + extra.put( "site", "youtube" ); + extra.put( "id", m.group(1) ); String t = m.group(2); - if( t != null ) { - sb.append( "?start=" ); - sb.append( t ); - } - sb.append( "' frameborder='0' allowfullscreen></iframe>" ); - return parser.success( sb.toString() ); + if( t != null ) + extra.put( "start", t ); + return parser.success(rtn); } m = find(bitchutePtn,url); if( m != null ) { - StringBuilder sb = new StringBuilder(); - sb.append( "<iframe width='420' height='315' scrolling='no' frameborder='0' style='border: none;' src='https://www.bitchute.com/embed/" ); - sb.append( m.group(1) ); - sb.append( "/'></iframe>" ); - return parser.success( sb.toString() ); + extra.put( "site", "bitchute" ); + extra.put( "id", m.group(1) ); + return parser.success(rtn); } - return parser.success( "<a href='" + url + "'>" + url + "</a>" ); + return parser.success(rtn); } - private String parseQuote1() { + private Element parseQuote1() { parser.begin(); if( !parser.matchIgnoreCase("[quote]") ) return parser.failure(null); - String content = parseWellFormed(); + Object content = parseWellFormed(); if( !parser.matchIgnoreCase("[/quote]") ) return parser.failure(null); - String rtn = quoter.quote(target,content,null); + Element rtn = new Element("quote",content); return parser.success(rtn); } - private String parseQuote2() { + private Element parseQuote2() { parser.begin(); if( !parser.matchIgnoreCase("[quote=") ) return parser.failure(null); @@ -330,35 +331,11 @@ String name = parser.textFrom(start).trim(); if( !parser.match(']') ) return parser.failure(null); - String content = parseWellFormed(); + Object content = parseWellFormed(); if( !parser.matchIgnoreCase("[/quote]") ) return parser.failure(null); - String rtn = quoter.quote(target,content,name); + Element rtn = new Element("quote",name,content); return parser.success(rtn); } - public static String htmlEncode(String s) { - final char[] a = s.toCharArray(); - StringBuilder buf = new StringBuilder(); - for( char c : a ) { - switch(c) { - case '&': - buf.append("&"); - break; - case '<': - buf.append("<"); - break; - case '>': - buf.append(">"); - break; - case '"': - buf.append("""); - break; - default: - buf.append(c); - } - } - return buf.toString(); - } - }
--- a/src/luan/modules/Parsers.luan Fri Jul 01 15:53:03 2022 -0600 +++ b/src/luan/modules/Parsers.luan Sun Jul 03 21:59:38 2022 -0600 @@ -9,8 +9,7 @@ local Parsers = {} -Parsers.bbcode_to_html = BBCodeLuan.toHtml -Parsers.bbcode_to_text = BBCodeLuan.toText +Parsers.bbcode_parse = BBCodeLuan.parse Parsers.csv_to_list = Csv.toList Parsers.json_string = BasicLuan.json_string Parsers.theme_to_luan = Theme.toLuan
--- a/src/luan/modules/parsers/BBCodeLuan.java Fri Jul 01 15:53:03 2022 -0600 +++ b/src/luan/modules/parsers/BBCodeLuan.java Sun Jul 03 21:59:38 2022 -0600 @@ -1,54 +1,56 @@ package luan.modules.parsers; import java.util.List; -import java.util.ArrayList; -import luan.Luan; -import luan.LuanFunction; +import java.util.Map; +import luan.LuanTable; import luan.LuanException; -import luan.LuanRuntimeException; import luan.modules.Utils; -import luan.modules.HtmlLuan; import goodjava.bbcode.BBCode; public final class BBCodeLuan { - private static BBCode.Quoter quoter(final Luan luan,final LuanFunction quoterFn) { - return new BBCode.Quoter() { - public String quote(BBCode.Target target,String text,String param) { - try { - Object obj = quoterFn.call(luan,text,param); - if( !(obj instanceof String) ) - throw new LuanException("BBCode quoter function returned "+Luan.type(obj)+" but string required"); - return (String)obj; - } catch(LuanException e) { - throw new LuanRuntimeException(e); - } - } - }; - } - - public static String toHtml(Luan luan,String text,LuanFunction quoterFn) throws LuanException { - return parse(luan,text,quoterFn,BBCode.Target.HTML); - } - - public static String toText(Luan luan,String text,LuanFunction quoterFn) throws LuanException { - return parse(luan,text,quoterFn,BBCode.Target.TEXT); - } - - private static String parse(Luan luan,String text,LuanFunction quoterFn,BBCode.Target target) + public static Object parse(String text) throws LuanException { Utils.checkNotNull(text,1); - BBCode bbcode = new BBCode(text); - bbcode.target = target; - if( quoterFn != null ) - bbcode.quoter = quoter(luan,quoterFn); - try { - return bbcode.parse(); - } catch(LuanRuntimeException e) { - throw (LuanException)e.getCause(); + Object obj = BBCode.parse(text); + return convert(obj); + } + + private static Object convert(Object obj) throws LuanException { + if( obj instanceof String ) + return obj; + if( obj instanceof BBCode.Element ) + return convert((BBCode.Element)obj); + if( obj instanceof List ) + return convert((List)obj); + throw new RuntimeException("invalid obj: "+obj); + } + + private static LuanTable convert(List list) throws LuanException { + LuanTable t = new LuanTable(); + for( Object obj : list ) { + t.rawAdd( convert(obj) ); } + return t; + } + + private static LuanTable convert(BBCode.Element el) throws LuanException { + LuanTable t = new LuanTable(); + t.rawPut( "name", el.name ); + Object param = el.param; + Object contents = el.contents; + Map<String,String> extra = el.extra; + if( param != null ) + t.rawPut( "param", param ); + t.rawPut( "contents", convert(contents) ); + if( extra != null ) { + for( Map.Entry<String,String> entry : extra.entrySet() ) { + t.rawPut( entry.getKey(), entry.getValue() ); + } + } + return t; } }