/******************************************************************************* * This file is part of RedReader. * * RedReader is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * RedReader is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with RedReader. If not, see <http://www.gnu.org/licenses/>. ******************************************************************************/ package org.quantumbadger.redreader.reddit.prepared.markdown; import java.util.ArrayList; public final class MarkdownParser { public enum MarkdownParagraphType { TEXT, CODE, BULLET, NUMBERED, QUOTE, HEADER, HLINE, EMPTY } public static MarkdownParagraphGroup parse(final char[] raw) { final CharArrSubstring[] rawLines = CharArrSubstring.generateFromLines(raw); final MarkdownLine[] lines = new MarkdownLine[rawLines.length]; for(int i = 0; i < rawLines.length; i++) { lines[i] = MarkdownLine.generate(rawLines[i]); } final ArrayList<MarkdownLine> mergedLines = new ArrayList<>(rawLines.length); MarkdownLine currentLine = null; for(int i = 0; i < lines.length; i++) { if(currentLine != null) { switch(lines[i].type) { case BULLET: case NUMBERED: case HEADER: case CODE: case HLINE: case QUOTE: mergedLines.add(currentLine); currentLine = lines[i]; break; case EMPTY: mergedLines.add(currentLine); currentLine = null; break; case TEXT: if(i < 1) { throw new RuntimeException("Internal error: invalid paragrapher state"); } switch(lines[i - 1].type) { case QUOTE: case BULLET: case NUMBERED: case TEXT: if(lines[i - 1].spacesAtEnd >= 2) { mergedLines.add(currentLine); currentLine = lines[i]; } else { currentLine = currentLine.rejoin(lines[i]); } break; case CODE: case HEADER: case HLINE: mergedLines.add(currentLine); currentLine = lines[i]; break; } break; } } else if(lines[i].type != MarkdownParagraphType.EMPTY) { currentLine = lines[i]; } } if(currentLine != null) { mergedLines.add(currentLine); } final ArrayList<MarkdownParagraph> outputParagraphs = new ArrayList<>(mergedLines.size()); for(final MarkdownLine line : mergedLines) { final MarkdownParagraph lastParagraph = outputParagraphs.isEmpty() ? null : outputParagraphs.get(outputParagraphs.size() - 1); final MarkdownParagraph paragraph = line.tokenize(lastParagraph); if(!paragraph.isEmpty()) outputParagraphs.add(paragraph); } return new MarkdownParagraphGroup(outputParagraphs.toArray(new MarkdownParagraph[outputParagraphs.size()])); } }