001/* 002 * Shredzone Commons 003 * 004 * Copyright (C) 2012 Richard "Shred" Körber 005 * http://commons.shredzone.org 006 * 007 * This program is free software: you can redistribute it and/or modify 008 * it under the terms of the GNU Library General Public License as 009 * published by the Free Software Foundation, either version 3 of the 010 * License, or (at your option) any later version. 011 * 012 * This program is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 015 * GNU General Public License for more details. 016 * 017 * You should have received a copy of the GNU Library General Public License 018 * along with this program. If not, see <http://www.gnu.org/licenses/>. 019 */ 020package org.shredzone.commons.text.filter; 021 022import org.shredzone.commons.text.TextFilter; 023 024/** 025 * A filter that detects paragraphs and surrounds them with a HTML {@code <p>} 026 * container. Paragraphs are separated by empty lines. Additionally, single EOLs can be 027 * replaced with {@code <br />} tags. 028 * <p> 029 * This filter expects a normalized text (only LF is accepted as EOL marker, see 030 * {@link NormalizeFilter}). 031 * 032 * @author Richard "Shred" Körber 033 */ 034public class ParagraphFilter implements TextFilter { 035 036 private boolean foldLines = true; 037 038 /** 039 * Also fold single EOL marker. 040 * 041 * @param foldLines 042 * {@code true} to create {@code <br />} tags for single EOL markers, 043 * {@code false} to keep the EOL marker. Defaults to {@code true}. 044 */ 045 public void setFoldLines(boolean foldLines) { 046 this.foldLines = foldLines; 047 } 048 049 @Override 050 public CharSequence apply(CharSequence text) { 051 StringBuilder sb = toStringBuilder(text); 052 053 sb.insert(0, "<p>").append("</p>"); 054 055 int max = sb.length() - 3 - 4; 056 int ix = 3; 057 058 while (ix < max) { 059 if (sb.charAt(ix) == '\n') { 060 int lineEnd = ix + 1; 061 while (lineEnd < max && sb.charAt(lineEnd) == '\n') { 062 lineEnd++; 063 } 064 065 if (lineEnd > ix + 1) { 066 sb.replace(ix, lineEnd, "</p><p>"); 067 max += 7 - (lineEnd - ix); 068 ix += 7; 069 } else if (foldLines) { 070 sb.replace(ix, lineEnd, "<br />"); 071 max += 6 - (lineEnd - ix); 072 ix += 6; 073 } else { 074 ix++; 075 } 076 } else { 077 ix++; 078 } 079 } 080 081 return sb; 082 } 083 084}