comparison src/luan/modules/HtmlLuan.java @ 775:1a68fc55a80c

simplify dir structure
author Franklin Schmidt <fschmidt@gmail.com>
date Fri, 26 Aug 2016 14:36:40 -0600
parents core/src/luan/modules/HtmlLuan.java@cdc70de628b5
children 25746915a241
comparison
equal deleted inserted replaced
774:3e30cf310e56 775:1a68fc55a80c
1 package luan.modules;
2
3 import java.util.List;
4 import java.util.ArrayList;
5 import java.util.Arrays;
6 import java.util.Set;
7 import java.util.HashSet;
8 import java.util.Map;
9 import luan.Luan;
10 import luan.LuanState;
11 import luan.LuanTable;
12 import luan.LuanException;
13
14
15 public final class HtmlLuan {
16
17 public static String encode(String s) throws LuanException {
18 Utils.checkNotNull(s);
19 char[] a = s.toCharArray();
20 StringBuilder buf = new StringBuilder();
21 for( int i=0; i<a.length; i++ ) {
22 char c = a[i];
23 switch(c) {
24 case '&':
25 buf.append("&amp;");
26 break;
27 case '<':
28 buf.append("&lt;");
29 break;
30 case '>':
31 buf.append("&gt;");
32 break;
33 case '"':
34 buf.append("&quot;");
35 break;
36 default:
37 buf.append(c);
38 }
39 }
40 return buf.toString();
41 }
42
43 /*
44 // public static final String TEXTAREA = "textarea";
45 public static final String SCRIPT = "script";
46 public static final String STYLE = "style";
47
48 public static Set<String> containerTags = new HashSet<String>(Arrays.asList(SCRIPT,STYLE));
49 */
50 /*
51 public static LuanTable parse(LuanState luan,String text,LuanTable containerTagsTbl)
52 throws LuanException
53 {
54 Utils.checkNotNull(luan,text);
55 Utils.checkNotNull(luan,containerTagsTbl);
56 Set<String> containerTags = new HashSet<String>();
57 for( Object v : containerTagsTbl.asList() ) {
58 containerTags.add((String)v);
59 }
60 List<Object> html = new ArrayList<Object>();
61 int len = text.length();
62 int i = 0;
63 outer:
64 while( i < len ) {
65 int i2 = text.indexOf('<',i);
66 while( i2 != -1 && i2+1 < len ) {
67 char c = text.charAt(i2+1);
68 if( Character.isLetter(c) || c=='/' || c=='!' )
69 break;
70 i2 = text.indexOf('<',i2+1);
71 }
72 if( i2 == -1 ) {
73 html.add( text.substring(i) );
74 break;
75 }
76 if( i < i2 )
77 html.add( text.substring(i,i2) );
78 if( text.startsWith("<!--",i2) ) {
79 i = text.indexOf("-->",i2+4);
80 if( i == -1 ) {
81 html.add( text.substring(i2) );
82 break;
83 }
84 html.add( comment( text.substring(i2+4,i) ) );
85 i += 3;
86 } else if( text.startsWith("<![CDATA[",i2) ) {
87 i = text.indexOf("]]>",i2+9);
88 if( i == -1 ) {
89 html.add( text.substring(i2) );
90 break;
91 }
92 html.add( cdata( text.substring(i2+9,i) ) );
93 i += 3;
94 } else {
95 i = text.indexOf('>',i2);
96 if( i == -1 ) {
97 html.add( text.substring(i2) );
98 break;
99 }
100 String tagText = text.substring(i2+1,i);
101 try {
102 LuanTable tag = parseTag(tagText);
103 String tagName = (String)tag.rawGet("name");
104 if( containerTags.contains(tagName) ) {
105 i2 = i;
106 String endTagName = '/' + tagName;
107 while(true) {
108 i2 = text.indexOf('<',i2+1);
109 if( i2 == -1 )
110 break;
111 int i3 = text.indexOf('>',i2);
112 if( i3 == -1 )
113 break;
114 int j = i2+1;
115 while( j<i3 && !Character.isWhitespace(text.charAt(j)) ) j++;
116 String s = text.substring(i2+1,j);
117 if( s.equalsIgnoreCase(endTagName) ) {
118 String text2 = text.substring(i+1,i2);
119 LuanTable textContainer = textContainer(tag,text2);
120 html.add( textContainer );
121 i = i3 + 1;
122 continue outer;
123 }
124 }
125 // logger.warn("unclosed "+tagName);
126 }
127 i += 1;
128 html.add( tag );
129 } catch(BadTag e) {
130 // logger.debug("bad tag",e);
131 i += 1;
132 // if( !removeBadTags ) {
133 html.add( "&lt;" );
134 html.add( encode(luan,tagText) );
135 html.add( "&gt;" );
136 // }
137 }
138 }
139 }
140 return new LuanTable(html);
141 }
142
143 static LuanTable comment(String text) {
144 LuanTable tbl = new LuanTable();
145 tbl.rawPut("type","comment");
146 tbl.rawPut("text",text);
147 return tbl;
148 }
149
150 static LuanTable cdata(String text) {
151 LuanTable tbl = new LuanTable();
152 tbl.rawPut("type","cdata");
153 tbl.rawPut("text",text);
154 return tbl;
155 }
156
157 static LuanTable textContainer(LuanTable tag,String text) {
158 LuanTable tbl = new LuanTable();
159 tbl.rawPut("type","container");
160 tbl.rawPut("tag",tag);
161 tbl.rawPut("text",text);
162 return tbl;
163 }
164
165
166
167 static final class BadTag extends RuntimeException {
168 private BadTag(String msg) {
169 super(msg);
170 }
171 }
172
173 static LuanTable parseTag(String text) {
174 LuanTable tbl = new LuanTable();
175 tbl.rawPut("type","tag");
176 if( text.endsWith("/") ) {
177 text = text.substring(0,text.length()-1);
178 tbl.rawPut("is_empty",true);
179 } else {
180 tbl.rawPut("is_empty",false);
181 }
182 int len = text.length();
183 int i = 0;
184 int i2 = i;
185 if( i2<len && text.charAt(i2)=='/' )
186 i2++;
187 while( i2<len ) {
188 char c = text.charAt(i2);
189 if( Character.isWhitespace(c) )
190 break;
191 if( !( Character.isLetterOrDigit(c) || c=='_' || c=='.' || c=='-' || c==':' ) )
192 throw new BadTag("invalid tag name for <"+text+">");
193 i2++;
194 }
195 String name = text.substring(i,i2).toLowerCase();
196 tbl.rawPut("name",name);
197 LuanTable attributes = new LuanTable();
198 tbl.rawPut("attributes",attributes);
199 i = i2;
200 while( i<len && Character.isWhitespace(text.charAt(i)) ) i++;
201 while( i<len ) {
202 i2 = toEndName(text,i,len);
203 String attrName = unquote(text.substring(i,i2).toLowerCase());
204 if( attributes.rawGet(attrName) != null )
205 throw new BadTag("duplicate attribute: "+attrName);
206 i = i2;
207 while( i<len && Character.isWhitespace(text.charAt(i)) ) i++;
208 if( i<len && text.charAt(i) == '=' ) {
209 i++;
210 i2 = i;
211 while( i<len && Character.isWhitespace(text.charAt(i)) ) i++;
212 i2 = toEndValue(text,i,len);
213 String attrValue = text.substring(i,i2);
214 if( attrValue.indexOf('<') != -1 || attrValue.indexOf('>') != -1 )
215 throw new BadTag("invalid attribute value: "+attrValue);
216 attrValue = unquote(attrValue);
217 attributes.rawPut(attrName,attrValue);
218 i = i2;
219 while( i<len && Character.isWhitespace(text.charAt(i)) ) i++;
220 } else {
221 attributes.rawPut(attrName,true);
222 }
223 }
224 return tbl;
225 }
226
227 private static int toEndName(String text,int i,int len) {
228 if( i==len )
229 return i;
230 char c = text.charAt(i);
231 switch(c) {
232 case '"':
233 case '\'':
234 i = text.indexOf(c,i+1);
235 return i==-1 ? len : i+1;
236 default:
237 if( Character.isWhitespace(c) ) {
238 throw new RuntimeException("text="+text+" i="+i);
239 }
240 do {
241 i++;
242 } while( i<len && (c=text.charAt(i))!='=' && !Character.isWhitespace(c) );
243 return i;
244 }
245 }
246
247 private static int toEndValue(String text,int i,int len) {
248 if( i==len )
249 return i;
250 char c = text.charAt(i);
251 switch(c) {
252 case '"':
253 case '\'':
254 i = text.indexOf(c,i+1);
255 return i==-1 ? len : i+1;
256 default:
257 if( Character.isWhitespace(c) ) {
258 throw new RuntimeException("text="+text+" i="+i);
259 }
260 do {
261 i++;
262 } while( i<len && !Character.isWhitespace(text.charAt(i)) );
263 return i;
264 }
265 }
266
267 public static String unquote(String s) {
268 if( s==null || s.length()<=1 )
269 return s;
270 char c = s.charAt(0);
271 return (c=='"' || c=='\'') && s.charAt(s.length()-1)==c
272 ? s.substring(1,s.length()-1) : s;
273 }
274 */
275
276
277 /*
278 public static String to_string(LuanState luan,LuanTable tbl) throws LuanException {
279 List<Object> html = tbl.asList();
280 StringBuilder buf = new StringBuilder();
281 for( Object o : html ) {
282 if( o instanceof String ) {
283 buf.append( o );
284 } else if( o instanceof LuanTable ) {
285 LuanTable t = (LuanTable)o;
286 String type = (String)t.get(luan,"type");
287 if( type==null )
288 throw new LuanException(luan, "no type in element of table for 'Html.to_string'" );
289 if( type.equals("comment") ) {
290 buf.append( "<!--" ).append( t.get(luan,"text") ).append( "-->" );
291 } else if( type.equals("cdata") ) {
292 buf.append( "<![CDATA[" ).append( t.get(luan,"text") ).append( "]]" );
293 } else if( type.equals("tag") ) {
294 buf.append( tagToString(luan,t) );
295 } else if( type.equals("container") ) {
296 LuanTable tag = (LuanTable)t.get(luan,"tag");
297 buf.append( tagToString(luan,tag) );
298 buf.append( t.get(luan,"text") );
299 buf.append( "</" ).append( tag.get(luan,"name") ).append( ">" );
300 } else {
301 throw new LuanException(luan, "invalid element type for 'Html.to_string'" );
302 }
303 } else
304 throw new LuanException(luan, "invalid value ("+Luan.type(o)+") in table for 'Html.to_string'" );
305 }
306 return buf.toString();
307 }
308
309 private static String tagToString(LuanState luan,LuanTable tbl) throws LuanException {
310 StringBuilder buf = new StringBuilder();
311 buf.append('<');
312 buf.append(tbl.get(luan,"name"));
313 LuanTable attributes = (LuanTable)tbl.get(luan,"attributes");
314 for( Map.Entry<Object,Object> attr : attributes.iterable(luan) ) {
315 buf.append( ' ' );
316 buf.append( attr.getKey() );
317 Object val = attr.getValue();
318 if( !val.equals(Boolean.TRUE) ) {
319 buf.append( '=' );
320 buf.append( quote((String)val) );
321 }
322 }
323 if( tbl.get(luan,"is_empty").equals(Boolean.TRUE) )
324 buf.append('/');
325 buf.append('>');
326 return buf.toString();
327 }
328 */
329 public static String quote(String s) {
330 StringBuilder buf = new StringBuilder();
331 buf.append('"');
332 int i = 0;
333 while(true) {
334 int i2 = s.indexOf('"',i);
335 if( i2 == -1 ) {
336 buf.append(s.substring(i));
337 break;
338 } else {
339 buf.append(s.substring(i,i2));
340 buf.append("&quot;");
341 i = i2 + 1;
342 }
343 }
344 buf.append('"');
345 return buf.toString();
346 }
347
348 }