Parse multiline list headings
[sixth.git] / src / main / java / eu / svjatoslav / sixth / core / document / Heading.java
index f9c3e6d..0ae9ad5 100644 (file)
 package eu.svjatoslav.sixth.core.document;
 
+import eu.svjatoslav.commons.string.tokenizer.Tokenizer;
+import eu.svjatoslav.commons.string.tokenizer.TokenizerMatch;
+import eu.svjatoslav.sixth.core.document.content.ListElement;
+import eu.svjatoslav.sixth.core.document.text.FormattedText;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static eu.svjatoslav.sixth.core.document.Helper.TG_LIST;
+
 public class Heading {
-    public final String name;
+    public final FormattedText name;
     public final int level;
     public final Heading parent;
+    private final List<Heading> children = new ArrayList<>();
 
-    public Heading(String name, int level, Heading parent){
+    public final ListElement rootListElement = new ListElement(null, -1, null, "");
+    private ListElement currentListElement = rootListElement;
+
+    public Heading(FormattedText name, int level, Heading parent){
         this.level = level;
         this.name = name;
         this.parent = parent;
     }
 
+    public void addChild(Heading heading){
+        children.add(heading);
+    }
+
+    public List<Heading> getChildren(){
+        return children;
+    }
+
+    public String toMD () {
+        StringBuilder sb = new StringBuilder();
+
+        if (level > 0) sb.append(enlistTitleInMD());
+
+        rootListElement.toMD(sb, -2);
+
+        children.stream().map(Heading::toMD).forEach(sb::append);
+
+        return sb.toString();
+    }
+
+    private String enlistTitleInMD() {
+        StringBuilder sb = new StringBuilder();
+        for (int i = 0; i < level; i++)
+            sb.append("#");
+
+        sb.append(" ").append(name.toMD()).append("\n");
+        return sb.toString();
+    }
+
+    public ListElement getCurrentHeading(){
+        return currentListElement;
+    }
+
+    public void parse(TokenizerMatch tm){
+
+        if (tm.isGroup(TG_LIST)){
+            parseList(tm);
+            return;
+        }
+
+        currentListElement.parse(tm);
+    }
+
+    private void parseList(TokenizerMatch tm) {
+        String[] listSections = tm.getRegExpGroups();
+        int indent = listSections[0].length();
+        String type = listSections[1];
+
+        FormattedText title = FormattedText.fromOrg(parseFullListTitle(listSections.length > 2 ? listSections[2] : "", tm.getTokenizer(), indent));
+
+//        System.out.println("  indent: " + indent);
+//        System.out.println("  type: " + type);
+//        System.out.println("  title: " + title);
+
+        ListElement parent = null;
+
+        if (indent > currentListElement.indent){
+            ListElement newElement = new ListElement(title, indent, parent, type);
+            currentListElement.addContent(newElement);
+            currentListElement = newElement;
+        }
+
+    }
+
+
+    private String parseFullListTitle(String partialTitle, Tokenizer tokenizer, int listIndent){
+        StringBuilder sb = new StringBuilder();
+        sb.append(partialTitle);
+
+        while (tokenizer.hasMoreContent()){
+            final TokenizerMatch tm = tokenizer.getNextToken();
+
+            if (isContentContinuation(tm, listIndent, null)){
+                String titleContinuation = tm.token.substring(listIndent).trim();
+                sb.append("\n").append(titleContinuation);
+                continue;
+            }
+
+            tokenizer.unreadToken();
+            break;
+        }
+
+        return sb.toString();
+    }
+
+    public static boolean isContentContinuation(TokenizerMatch tm, int requiredIndent, String requiredGroup) {
+        if (tm.token.length() <= requiredIndent) return false;
+
+        return tm.isGroup(requiredGroup) && tm.token.substring(0, requiredIndent +1).trim().length() == 0;
+    }
+
 }