blob: 072ee33798128d60eb94f560a3b2f0719e2cd570 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2007, 2015 David Green and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* David Green - initial API and implementation
*******************************************************************************/
package org.eclipse.mylyn.wikitext.textile.internal.block;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.mylyn.wikitext.parser.DocumentBuilder.BlockType;
import org.eclipse.mylyn.wikitext.parser.TableAttributes;
import org.eclipse.mylyn.wikitext.parser.TableCellAttributes;
import org.eclipse.mylyn.wikitext.parser.TableRowAttributes;
import org.eclipse.mylyn.wikitext.parser.markup.Block;
import org.eclipse.mylyn.wikitext.textile.internal.Textile;
import com.google.common.base.CharMatcher;
/**
* Table block, matches blocks that start with <code>table. </code> or those that start with a table row.
*
* @author David Green
*/
public class TableBlock extends Block {
// NOTE: no need for whitespace after the dot on 'table.'
static final Pattern startPattern = Pattern.compile("(table" + Textile.REGEX_BLOCK_ATTRIBUTES //$NON-NLS-1$
+ "\\.\\s*)|(\\|(.*)?(\\|\\s*$))"); //$NON-NLS-1$
static final Pattern rowAttributesPattern = Pattern.compile(Textile.REGEX_BLOCK_ATTRIBUTES + "\\.\\s*.*"); //$NON-NLS-1$
static final Pattern TABLE_ROW_PATTERN = Pattern.compile("\\|(?:\\\\(\\d+))?(?:/(\\d+))?((?:\\<\\>)|\\<|\\>|\\^)?" //$NON-NLS-1$
+ Textile.REGEX_ATTRIBUTES + "(_|\\|)?\\.?\\s?([^\\|]*)(\\|\\|?\\s*$)?"); //$NON-NLS-1$
private int blockLineCount = 0;
private Matcher matcher;
public TableBlock() {
}
@Override
public int processLineContent(String line, int offset) {
if (blockLineCount == 0) {
TableAttributes attributes = new TableAttributes();
if (matcher.group(1) != null) {
// 0-offset matches may start with the "table. " prefix.
Textile.configureAttributes(attributes, matcher, 2, true);
offset = line.length();
}
builder.beginBlock(BlockType.TABLE, attributes);
} else if (markupLanguage.isEmptyLine(line)) {
setClosed(true);
return 0;
}
++blockLineCount;
if (offset == line.length()) {
return -1;
}
String textileLine = offset == 0 ? line : line.substring(offset);
Matcher rowMatcher = TABLE_ROW_PATTERN.matcher(textileLine);
if (!rowMatcher.find()) {
setClosed(true);
return 0;
}
{
TableRowAttributes rowAttributes = new TableRowAttributes();
int rowStart = rowMatcher.start();
if (rowStart > 0) {
// if the row content starts somewhere in the line then it's likely
// that we have some row-level attributes
Matcher rowAttributesMatcher = rowAttributesPattern.matcher(textileLine);
if (rowAttributesMatcher.matches()) {
Textile.configureAttributes(rowAttributes, rowAttributesMatcher, 1, true);
}
}
builder.beginBlock(BlockType.TABLE_ROW, rowAttributes);
}
do {
int start = rowMatcher.start();
if (start == textileLine.length() - 1) {
break;
}
String colSpan = rowMatcher.group(1);
String rowSpan = rowMatcher.group(2);
String alignment = rowMatcher.group(3);
String headerIndicator = rowMatcher.group(8);
String text = rowMatcher.group(9);
int textLineOffset = rowMatcher.start(9);
boolean header = headerIndicator != null && ("_".equals(headerIndicator) || "|".equals(headerIndicator)); //$NON-NLS-1$ //$NON-NLS-2$
String textAlign = null;
if (alignment != null) {
if (alignment.equals("<>")) { //$NON-NLS-1$
textAlign = "text-align: center;"; //$NON-NLS-1$
} else if (alignment.equals(">")) { //$NON-NLS-1$
textAlign = "text-align: right;"; //$NON-NLS-1$
} else if (alignment.equals("<")) { //$NON-NLS-1$
textAlign = "text-align: left;"; //$NON-NLS-1$
} else if (alignment.equals("^")) { //$NON-NLS-1$
textAlign = "vertical-align: top;"; //$NON-NLS-1$
}
}
TableCellAttributes attributes = new TableCellAttributes();
attributes.setCssStyle(textAlign);
attributes.setRowspan(rowSpan);
attributes.setColspan(colSpan);
Textile.configureAttributes(attributes, rowMatcher, 4, false);
state.setLineCharacterOffset(start);
builder.beginBlock(header ? BlockType.TABLE_CELL_HEADER : BlockType.TABLE_CELL_NORMAL, attributes);
markupLanguage.emitMarkupLine(getParser(), state, textLineOffset,
CharMatcher.WHITESPACE.trimTrailingFrom(text), 0);
builder.endBlock(); // table cell
} while (rowMatcher.find());
builder.endBlock(); // table row
return -1;
}
@Override
public boolean canStart(String line, int lineOffset) {
blockLineCount = 0;
if (lineOffset == 0) {
matcher = startPattern.matcher(line);
return matcher.matches();
} else {
matcher = null;
return false;
}
}
@Override
public void setClosed(boolean closed) {
if (closed && !isClosed()) {
builder.endBlock();
}
super.setClosed(closed);
}
}