diff src/goodjava/bbcode/BBCode.java @ 1705:a6e27c8e7ef4

bbcode now returns data
author Franklin Schmidt <fschmidt@gmail.com>
date Sun, 03 Jul 2022 21:59:38 -0600
parents 3a61451f8130
children 05d14db623b6
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("&amp;");
-				break;
-			case '<':
-				buf.append("&lt;");
-				break;
-			case '>':
-				buf.append("&gt;");
-				break;
-			case '"':
-				buf.append("&quot;");
-				break;
-			default:
-				buf.append(c);
-			}
-		}
-		return buf.toString();
-	}
-
 }