/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.karaf.shell.impl.console.commands.help.wikidoc; import java.io.BufferedReader; import java.io.IOException; import java.io.Reader; import org.apache.karaf.util.StringEscapeUtils; /** * Parses wiki syntax from a reader and calls a Wikivisitor with the * tokens it finds */ public class WikiParser { WikiVisitor visitor; public WikiParser(WikiVisitor visitor) { this.visitor = visitor; } public void parse(Reader reader) throws IOException { BufferedReader br = new BufferedReader(reader); String line; while ((line = br.readLine()) != null) { if (!line.startsWith("#")) { parse(line); } } } public void parse(String line) { String unescaped = StringEscapeUtils.unescapeJava(line); Tokenizer tokenizer = new Tokenizer(unescaped); String token; boolean bold = false; boolean first = true; while ((token = tokenizer.nextToken("\u001B[h*")) != null) { if (first) { first = false; int tabs = 0; for (int i = 0; i < token.length() && token.charAt(i) == '\t'; i++) { tabs++; } token = token.substring(tabs); for (int i = 0; i < tabs; i++) { token = " " + token; } int i = 0; while (i < token.length() && token.charAt(i) == ' ') { i++; } visitor.startPara(i); token = token.substring(i); } if ("\u001B".equals(token)) { parseEsc(tokenizer, token); } else if ("[".equals(token)) { parseLink(tokenizer); } else if ("h".equals(token)) { parseHeading(tokenizer); } else if ("*".equals(token)) { parseEnumeration(tokenizer); } else if ("**".equals(token)) { bold = !bold; visitor.bold(bold); } else { visitor.text(token); } } if (first) { visitor.startPara(0); } visitor.endPara(); } private void parseEsc(Tokenizer tokenizer, String token) { visitor.text(token + tokenizer.nextToken("\u001B[h*") + tokenizer.nextToken("\u001B[]")); } private void parseEnumeration(Tokenizer tokenizer) { String text = tokenizer.nextToken("-\n"); visitor.enumeration(text.trim()); } private void parseHeading(Tokenizer tokenizer) { String level = tokenizer.nextToken("123456789"); if (!level.matches("[123456789]")) { visitor.text("h" + level); return; } String dot = tokenizer.nextToken(".\n"); if (!".".equals(dot)) { visitor.text("h" + level + dot); return; } String heading = tokenizer.nextToken("\n"); if (heading == null) { heading = ""; } visitor.heading(Integer.parseInt(level), heading.trim()); } private void parseLink(Tokenizer tokenizer) { String token = tokenizer.nextToken("]"); visitor.link(token, ""); tokenizer.nextToken("]"); } public static class Tokenizer { final String str; int pos; public Tokenizer(String str) { this.str = str; } public String nextToken(String delim) { StringBuilder sb = new StringBuilder(); boolean escape = false; boolean del = false; while (pos < str.length()) { char c = str.charAt(pos++); if (escape) { escape = false; sb.append(c); } else if (c == '\\') { if (del) { pos--; break; } else { escape = true; } } else if (delim.indexOf(c) >= 0) { if (sb.length() == 0 || del) { sb.append(c); del = true; } else { pos--; break; } } else { if (del) { pos--; break; } sb.append(c); } } return sb.length() > 0 ? sb.toString() : null; } } }