/*******************************************************************************
* Copyright (c) 2007, 2012 David Green and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* David Green - initial API and implementation
* Jeremie Bresson - Bug 381506
*******************************************************************************/
package org.eclipse.mylyn.wikitext.mediawiki.internal.block;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.mylyn.wikitext.parser.Attributes;
import org.eclipse.mylyn.wikitext.parser.DocumentBuilder.BlockType;
import org.eclipse.mylyn.wikitext.parser.markup.Block;
/**
* @author David Green
*/
public class PreformattedBlock extends Block {
private static final Pattern PRE_OPEN_PATTERN = Pattern.compile(
"(<pre((?:\\s+[a-zA-Z][a-zA-Z0-9_:-]*=\"[^\"]*\")*)\\s*>).*", Pattern.CASE_INSENSITIVE); //$NON-NLS-1$
private static final Pattern PRE_CLOSE_PATTERN = Pattern.compile("(</pre*\\s*>)", Pattern.CASE_INSENSITIVE); //$NON-NLS-1$
private int blockLineCount = 0;
private boolean usesTag = false;
@Override
public boolean canStart(String line, int lineOffset) {
if (lineOffset == 0 && line.length() > 0 && line.charAt(0) == ' ') {
usesTag = false;
return true;
}
final Matcher matcher = PRE_OPEN_PATTERN.matcher(line);
if (lineOffset > 0) {
matcher.region(lineOffset, line.length());
}
if (matcher.matches()) {
usesTag = true;
return true;
}
return false;
}
@Override
public int processLineContent(String line, int offset) {
int lineStart = usesTag ? 0 : 1;
if (blockLineCount++ == 0) {
Attributes attributes = new Attributes();
if (usesTag) {
Matcher matcher = PRE_OPEN_PATTERN.matcher(line);
if (offset > 0) {
matcher.region(offset, line.length());
}
if (matcher.matches()) {
String htmlAttributes = matcher.group(2);
processHtmlAttributes(attributes, htmlAttributes);
lineStart = matcher.end(1);
offset = lineStart;
} else {
throw new IllegalStateException();
}
}
builder.beginBlock(BlockType.PREFORMATTED, attributes);
}
if (usesTag) {
if (blockLineCount > 0) {
Matcher closeMatcher = PRE_CLOSE_PATTERN.matcher(line);
if (offset > 0) {
closeMatcher.region(offset, line.length());
}
if (closeMatcher.find()) {
int contentEnd = closeMatcher.start(1);
int newContentStart = closeMatcher.end(1);
if (contentEnd > 0) {
addContent(line.substring(0, contentEnd), offset);
}
setClosed(true);
if (newContentStart < line.length()) {
return newContentStart;
}
return -1;
}
}
} else {
if (markupLanguage.isEmptyLine(line) || (offset == 0 && line.charAt(0) != ' ')) {
setClosed(true);
return 0;
}
}
if (line.length() >= lineStart) {
addContent(line, lineStart);
}
return -1;
}
private void addContent(String line, int offset) {
if (usesTag) {
builder.characters(line.substring(offset));
} else {
getMarkupLanguage().emitMarkupLine(parser, state, line, offset);
}
builder.characters("\n"); //$NON-NLS-1$
}
private void processHtmlAttributes(Attributes attributes, String htmlAttributes) {
if (htmlAttributes != null) {
Pattern pattern = Pattern.compile("\\s+([a-zA-Z][a-zA-Z0-9_:-]*)=\"([^\"]*)\""); //$NON-NLS-1$
Matcher matcher = pattern.matcher(htmlAttributes);
while (matcher.find()) {
String attrName = matcher.group(1);
String attrValue = matcher.group(2);
if ("id".equals(attrName)) { //$NON-NLS-1$
attributes.setId(attrValue);
} else if ("style".equals(attrName)) { //$NON-NLS-1$
attributes.setCssStyle(attrValue);
} else if ("class".equals(attrName)) { //$NON-NLS-1$
attributes.setCssClass(attrValue);
}
}
}
}
@Override
public void setClosed(boolean closed) {
if (closed && !isClosed()) {
builder.endBlock(); // pre
usesTag = false;
}
super.setClosed(closed);
}
}