BufferedReader reader = new BufferedReader(new StringReader(textile));
String textileLine;
int lineNumber = 0;
BlockType extendedBlockType = null;
int extendedBlockNewlines = 0;
boolean extendedTagRequired = false;
while ((textileLine = reader.readLine()) != null) {
++lineNumber;
builder.textileLine(lineNumber,textileLine);
if (textileLine.length() == 0) {
if (extendedBlockType == null) {
endBlock(state.elements);
} else if (extendedBlockType.isPreformatted()) {
++extendedBlockNewlines;
} else {
if (!extendedTagRequired) {
extendedTagRequired = true;
pop(state.elements,1);
}
}
continue;
}
boolean startedNewBlock = false;
boolean table = inTable(state.elements);
if (!table && BLOCK_START_TABLE_ROW.matcher(textileLine).matches()) {
endBlock(state.elements);
state.elements.push(new BlockState(builder,BlockType.TABLE,new Attributes()));
table = true;
}
if (table) {
state.elements.push(new BlockState(builder,BlockType.TABLE_ROW,new Attributes()));
Matcher rowMatcher = TABLE_ROW_PATTERN.matcher(textileLine);
while (rowMatcher.find()) {
int start = rowMatcher.start();
if (start == textileLine.length()-1) {
break;
}
String alignment = rowMatcher.group(1);
String headerIndicator = rowMatcher.group(6);
String text = rowMatcher.group(7);
boolean header = headerIndicator != null && ("_".equals(headerIndicator) || "|".equals(headerIndicator));
String textAlign = null;
if (alignment != null) {
if (alignment.equals("<>")) {
textAlign = "text-align: center;";
} else if (alignment.equals(">")) {
textAlign = "text-align: right;";
} else if (alignment.equals("<")) {
textAlign = "text-align: left;";
} else if (alignment.equals("^")) {
textAlign = "text-align: top;";
}
}
state.elements.push(new BlockState(builder,header?BlockType.TABLE_CELL_HEADER:BlockType.TABLE_CELL_NORMAL,createAttributes(rowMatcher, 2,null,null,textAlign)));
emitTextileLine(text);
pop(state.elements,1);
}
pop(state.elements,1);
} else {
Matcher listBlockMatcher = LIST_BLOCK_MODIFIERS.matcher(textileLine);
boolean lineContentProcessed = false;
if (listBlockMatcher.matches()) {
extendedBlockType = null;
extendedTagRequired = false;
String listType = listBlockMatcher.group(1);
textileLine = listBlockMatcher.group(6);
int level = listType.length();
boolean numeric = listType.charAt(level-1) == '#';
adjustList(state.elements,numeric,level,listBlockMatcher,2);
startedNewBlock = true;
} else {
Matcher blockModifierMatcher = BLOCK_MODIFIERS.matcher(textileLine);
if (blockModifierMatcher.matches()) {
// end any previous block
extendedBlockType = null;
extendedTagRequired = false;
endBlock(state.elements);
startedNewBlock = true;
String modifierType = blockModifierMatcher.group(1);
String extended = blockModifierMatcher.group(6);
textileLine = blockModifierMatcher.group(7);
//
// System.out.println("groups: "+blockModifierMatcher.groupCount());
// for (int x = 1;x<=blockModifierMatcher.groupCount();++x) {
// System.out.println("\t"+x+": "+blockModifierMatcher.group(x));
// }
if (modifierType.startsWith("h")) {
int level = Integer.parseInt(modifierType.substring(1));
state.elements.push(new HeadingState(builder,level,createAttributes(blockModifierMatcher,2),textileLine));
} else if (modifierType.equals("p")) {
state.elements.push(new BlockState(builder,BlockType.PARAGRAPH,createAttributes(blockModifierMatcher,2)));
} else if (modifierType.equals("pre")) {
state.elements.push(new BlockState(builder,BlockType.PREFORMATTED,createAttributes(blockModifierMatcher,2)));
} else if (modifierType.equals("bq")) {
state.elements.push(new BlockState(builder,BlockType.QUOTE,createAttributes(blockModifierMatcher,2)));
state.elements.push(new BlockState(builder,BlockType.PARAGRAPH,new Attributes()));
if (extended != null) {
extendedBlockType = BlockType.PARAGRAPH;
}
} else if (modifierType.equals("bc")) {
state.elements.push(new BlockState(builder,BlockType.PREFORMATTED,createAttributes(blockModifierMatcher,2)));
state.elements.push(new BlockState(builder,BlockType.CODE,new Attributes()));
if (extended != null) {
extendedBlockType = BlockType.CODE;
}
} else if (modifierType.startsWith("fn")) {
String fnId = modifierType.substring(2);
String elementId = getFootnoteId(state.footnoteIdToHtmlId, fnId);
state.elements.push(new BlockState(builder,BlockType.PARAGRAPH,createAttributes(blockModifierMatcher,2,elementId,"footnote",null)));
builder.beginSpan(SpanType.SUPERSCRIPT, new Attributes());
emitText(fnId);
builder.endSpan();
} else if (modifierType.equals("table")) {
state.elements.push(new BlockState(builder,BlockType.TABLE,createAttributes(blockModifierMatcher,2)));
} else {
throw new IllegalStateException(String.format("Unexpected '%s' at line %s",modifierType,lineNumber));
}
} else {
BlockTagProcessor blockProcessor;
if (dialect != null && ((blockProcessor = dialect.startBlock(textileLine,0)) != null)) {
blockProcessor.setParser(this);
blockProcessor.setParserServices(services);
blockProcessor.setBuilder(builder);
blockProcessor.setTextile(textile);
// end any previous block
extendedBlockType = null;
extendedTagRequired = false;
endBlock(state.elements);
startedNewBlock = true;
int lineOffset = blockProcessor.getLineOffset();
if (lineOffset < textileLine.length()) {
String textileLineEnd = textileLine.substring(lineOffset);
if (textileLineEnd.trim().length() > 0) {
blockProcessor.process(textileLine,lineOffset);
}
}
while (!blockProcessor.isBlockClosed()) {
if ((textileLine = reader.readLine()) != null) {
++lineNumber;
builder.textileLine(lineNumber,textileLine);
blockProcessor.process(textileLine, 0);
} else {
break;
}
}
blockProcessor.closeBlock();
lineContentProcessed = true;
if (textileLine == null) {
break;
}
if (blockProcessor.getLineOffset() < textileLine.length()) {
String textileLineEnd = textileLine.substring(lineOffset);
if (textileLineEnd.trim().length() > 0) {
textileLine = textileLineEnd;
lineContentProcessed = false;
state.elements.push(new BlockState(builder,BlockType.PARAGRAPH,createAttributes(blockModifierMatcher,2)));
startedNewBlock = true;
}
}
} else {
Matcher generativeEmitterMatcher = GENERATIVE_EMITTER_PATTERN.matcher(textileLine);
if (generativeEmitterMatcher.matches()) {
// end any previous block
extendedBlockType = null;
extendedTagRequired = false;
endBlock(state.elements);
startedNewBlock = true;
lineContentProcessed = true;
emitText(textileLine.trim());
}
}
}
}
if (startedNewBlock) {
extendedBlockNewlines = 0;
}
if (textileLine != null && !lineContentProcessed) {
lineContentProcessed = true;
if (!startedNewBlock) {
if (extendedBlockType != null && extendedBlockType.isPreformatted()) {
for (int x = 0;x<extendedBlockNewlines;++x) {
builder.characters("\n");
}
}
extendedBlockNewlines = 0;