r9969 - helma/helma/trunk/src/helma/util
[email protected] Mon, 28 Sep 2009 14:21:17 +0200 (CEST)
| Newsgroups | gmane.comp.java.helma.cvs |
|---|---|
| Message-ID | <20090928122117.170313D0E2@mia> |
Author: hannes
Date: 2009-09-28 14:21:16 +0200 (Mon, 28 Sep 2009)
New Revision: 9969
Modified:
helma/helma/trunk/src/helma/util/MarkdownProcessor.java
Log:
Fix some markdown bugs.
Details at http://dev.helma.org/trac/helma/changeset/9969
Modified: helma/helma/trunk/src/helma/util/MarkdownProcessor.java
===================================================================
--- helma/helma/trunk/src/helma/util/MarkdownProcessor.java 2009-09-27 18:59:38 UTC (rev 9968)
+++ helma/helma/trunk/src/helma/util/MarkdownProcessor.java 2009-09-28 12:21:16 UTC (rev 9969)
@@ -60,27 +60,30 @@
public MarkdownProcessor() {}
public MarkdownProcessor(String text) {
- length = text.length();
- chars = new char[length + 2];
- text.getChars(0, length, chars, 0);
- chars[length] = chars[length + 1] = '\n';
+ init(text);
}
public MarkdownProcessor(File file) throws IOException {
length = (int) file.length();
chars = new char[length + 2];
FileReader reader = new FileReader(file);
- if (reader.read(chars) != length) {
- throw new IOException("Couldn't read file");
+ int read = 0;
+ try {
+ while (read < length) {
+ int r = reader.read(chars, read, length - read);
+ if (r == -1)
+ break;
+ read += r;
+ }
+ } finally {
+ reader.close();
}
+ length = read;
chars[length] = chars[length + 1] = '\n';
}
public synchronized String process(String text) {
- length = text.length();
- chars = new char[length + 2];
- text.getChars(0, length, chars, 0);
- chars[length] = chars[length + 1] = '\n';
+ init(text);
return process();
}
@@ -95,6 +98,18 @@
return result;
}
+ public synchronized String processLinkText(String text) {
+ init(text);
+ return processLinkText();
+ }
+
+ private void init(String text) {
+ length = text.length();
+ chars = new char[length + 2];
+ text.getChars(0, length, chars, 0);
+ chars[length] = chars[length + 1] = '\n';
+ }
+
/**
* Retrieve a link defined in the source text. If the link is not found, we call
* lookupLink(String) to retrieve it from an external source.
@@ -232,7 +247,7 @@
// no valid link title - escape
state = NONE;
}
- } else {
+ } else if (!isSpace(c) || buffer.length() > 0) {
buffer.append(c);
}
}
@@ -436,7 +451,7 @@
char lastChar = 0;
int count = 0;
boolean escape = false;
- for (int k = j; k < length; k++) {
+ for (int k = j; k <= length; k++) {
if (chars[k] == '\n' && lastChar == '\n') {
break;
}
@@ -449,6 +464,8 @@
escape = true;
} else if (chars[k] == '`') {
k = skipCodeSpan(k);
+ } else if (chars[k] == '[') {
+ k = skipLink(k);
} else if (chars[k] == c) {
count += 1;
} else {
@@ -575,6 +592,83 @@
return j;
}
+ private int skipLink(int start) {
+ boolean escape = false;
+ int nesting = 0;
+ int j = start + 1;
+ char c;
+ while (j < length && (escape || chars[j] != ']' || nesting != 0)) {
+ c = chars[j];
+ if (c == '\n' && chars[j - 1] == '\n') {
+ return start;
+ }
+
+ if (escape) {
+ escape = false;
+ } else {
+ escape = c == '\\';
+ if (!escape) {
+ if (c == '[') {
+ nesting += 1;
+ } else if (c == ']') {
+ nesting -= 1;
+ }
+ }
+ }
+ j += 1;
+ }
+ int k = j;
+ j += 1;
+ boolean extraSpace = false;
+ if (j < length && Character.isWhitespace(chars[j])) {
+ j += 1;
+ extraSpace = true;
+ }
+ c = chars[j++];
+ if (c == '[') {
+ while (j < length && chars[j] != ']') {
+ if (chars[j] == '\n') {
+ return start;
+ }
+ j += 1;
+ }
+ } else if (c == '(' && !extraSpace) {
+ while (j < length && chars[j] != ')' && !isSpace(chars[j])) {
+ if (chars[j] == '\n') {
+ return start;
+ }
+ j += 1;
+ }
+ if (j < length && chars[j] != ')') {
+ while (j < length && chars[j] != ')' && Character.isWhitespace(chars[j])) {
+ j += 1;
+ }
+ if (chars[j] == '"') {
+ int quoteStart = j = j + 1;
+ int len = -1;
+ while (j < length && chars[j] != '\n') {
+ if (chars[j] == '"') {
+ len = j - quoteStart;
+ } else if (len > -1) {
+ if (chars[j] == ')') {
+ break;
+ } else if (!isSpace(chars[j])) {
+ len = -1;
+ }
+ }
+ j += 1;
+ }
+ }
+ if (chars[j] != ')') {
+ return start;
+ }
+ }
+ } else {
+ j = k;
+ }
+ return j;
+ }
+
private boolean checkLink(char c) {
return checkLinkInternal(c, i + 1, false);
}
@@ -609,7 +703,7 @@
} else if (c == ']') {
nesting -= 1;
}
- if (c == '*' || c == '_' || c == '`') {
+ if (c == '*' || c == '_' || c == '`' || c == '[') {
needsEncoding = true;
}
boolean s = Character.isWhitespace(chars[j]);
@@ -627,10 +721,10 @@
String linkId;
int k = j;
j += 1;
- // this is weird, bug we follow the official markup implementation here:
+ // this is weird, but we follow the official markup implementation here:
// only accept space between link text and link target for [][], not for []()
boolean extraSpace = false;
- if (j < length && isSpace(chars[j])) {
+ if (j < length && Character.isWhitespace(chars[j])) {
j += 1;
extraSpace = true;
}
@@ -715,19 +809,13 @@
}
buffer.append(">");
if (needsEncoding) {
- b.append(escapeHtml(text)).append("</a>");
+ MarkdownProcessor wrapped = new MarkdownProcessor();
+ buffer.append(wrapped.processLinkText(text)).append("</a>");
} else {
buffer.append(escapeHtml(text)).append("</a>");
}
}
- if (b.length() > 0) {
- System.arraycopy(chars, j + 1, chars, i + b.length(), length - j - 1);
- b.getChars(0, b.length(), chars, i);
- length = i + (length - j - 1) + b.length();
- } else {
- System.arraycopy(chars, j + 1, chars, i, length - j - 1);
- length -= 1 + j - i;
- }
+ i = j + 1;
return true;
}
@@ -1021,6 +1109,51 @@
return b.toString();
}
+ private synchronized String processLinkText() {
+ buffer = new StringBuilder((int) (length * 1.2));
+ line = 1;
+ boolean escape = false;
+
+ for (i = 0; i < length; ) {
+ char c = chars[i];
+
+ if (escape) {
+ buffer.append(c);
+ escape = false;
+ i += 1;
+ continue;
+ } else if (c == '\\') {
+ escape = true;
+ i += 1;
+ continue;
+ }
+ switch (c) {
+ case '*':
+ case '_':
+ if (checkEmphasis(c)) {
+ continue;
+ }
+ break;
+
+ case '`':
+ if (checkCodeSpan(c)) {
+ continue;
+ }
+ break;
+
+ case '!':
+ if (checkImage()) {
+ continue;
+ }
+ break;
+ }
+
+ buffer.append(c);
+ i += 1;
+ }
+ return buffer.toString().trim();
+ }
+
boolean isLinkQuote(char c) {
return c == '"' || c == '\'' || c == '(';
}