Sanitize emphasis
This commit is contained in:
parent
fc689d9a12
commit
219a5df9ff
1 changed files with 90 additions and 61 deletions
|
@ -18,7 +18,7 @@ public class MarkdownProcessor {
|
||||||
private boolean listParagraphs = false;
|
private boolean listParagraphs = false;
|
||||||
private int codeEndMarker = 0;
|
private int codeEndMarker = 0;
|
||||||
private ElementStack stack = new ElementStack();
|
private ElementStack stack = new ElementStack();
|
||||||
private HashMap spanTags;
|
private Emphasis[] emph = new Emphasis[2];
|
||||||
|
|
||||||
private String result = null;
|
private String result = null;
|
||||||
|
|
||||||
|
@ -249,7 +249,6 @@ public class MarkdownProcessor {
|
||||||
private synchronized void secondPass() {
|
private synchronized void secondPass() {
|
||||||
state = NEWLINE;
|
state = NEWLINE;
|
||||||
stack.add(new BaseElement());
|
stack.add(new BaseElement());
|
||||||
spanTags = new HashMap();
|
|
||||||
buffer = new StringBuilder((int) (length * 1.2));
|
buffer = new StringBuilder((int) (length * 1.2));
|
||||||
line = 1;
|
line = 1;
|
||||||
boolean escape = false;
|
boolean escape = false;
|
||||||
|
@ -320,9 +319,9 @@ public class MarkdownProcessor {
|
||||||
|
|
||||||
if (state == HEADER) {
|
if (state == HEADER) {
|
||||||
if (c == '#') {
|
if (c == '#') {
|
||||||
((Element) stack.peek()).m ++;
|
((Element) stack.peek()).mod++;
|
||||||
} else {
|
} else {
|
||||||
((Element) stack.peek()).m = 0;
|
((Element) stack.peek()).mod = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -346,8 +345,8 @@ public class MarkdownProcessor {
|
||||||
}
|
}
|
||||||
if (state == HEADER) {
|
if (state == HEADER) {
|
||||||
Element header = (Element) stack.pop();
|
Element header = (Element) stack.pop();
|
||||||
if (header.m > 0) {
|
if (header.mod > 0) {
|
||||||
buffer.setLength(buffer.length() - header.m);
|
buffer.setLength(buffer.length() - header.mod);
|
||||||
}
|
}
|
||||||
header.close();
|
header.close();
|
||||||
}
|
}
|
||||||
|
@ -415,6 +414,14 @@ public class MarkdownProcessor {
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean checkEmphasis(char c) {
|
private boolean checkEmphasis(char c) {
|
||||||
|
for (int l = 1; l >= 0; l--) {
|
||||||
|
if (emph[l] != null && emph[l].end == i) {
|
||||||
|
emph[l].close();
|
||||||
|
i += emph[l].mod;
|
||||||
|
emph[l] = null;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (c == '*' || c == '_') {
|
if (c == '*' || c == '_') {
|
||||||
int n = 1;
|
int n = 1;
|
||||||
int j = i + 1;
|
int j = i + 1;
|
||||||
|
@ -424,68 +431,50 @@ public class MarkdownProcessor {
|
||||||
}
|
}
|
||||||
int found = n;
|
int found = n;
|
||||||
boolean isStartTag = j < length - 1 && !Character.isWhitespace(chars[j]);
|
boolean isStartTag = j < length - 1 && !Character.isWhitespace(chars[j]);
|
||||||
boolean isEndTag = i > 0 && !Character.isWhitespace(chars[i - 1]);
|
if (isStartTag && (emph[0] == null || emph[1] == null)) {
|
||||||
boolean hasStrong = spanTags.get(Integer.valueOf(2)) != null;
|
List possibleEndTags = new ArrayList();
|
||||||
boolean hasEmphasis = spanTags.get(Integer.valueOf(1)) != null;
|
|
||||||
if (isStartTag && (!hasStrong || !hasEmphasis)) {
|
|
||||||
List matchingEndTags = new ArrayList();
|
|
||||||
char lastChar = 0;
|
char lastChar = 0;
|
||||||
int count = 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') {
|
if (chars[k] == '\n' && lastChar == '\n') {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (chars[k] == c) {
|
|
||||||
count += 1;
|
|
||||||
} else {
|
|
||||||
if (count > 0 && !Character.isWhitespace(chars[k - count - 1])) {
|
|
||||||
matchingEndTags.add(Integer.valueOf(count));
|
|
||||||
}
|
|
||||||
count = 0;
|
|
||||||
}
|
|
||||||
lastChar = chars[k];
|
lastChar = chars[k];
|
||||||
}
|
System.err.println(k + ": " + chars[k]);
|
||||||
|
|
||||||
String[] tryElements = {
|
if (escape) {
|
||||||
hasEmphasis ? null : "em",
|
escape = false;
|
||||||
hasStrong || n < 2 ? null : "strong"
|
} else {
|
||||||
};
|
if (chars[k] == '\\') {
|
||||||
Stack matchedElements = new Stack();
|
escape = true;
|
||||||
for (int l = tryElements.length - 1; l >= 0; l--) {
|
} else if (chars[k] == '`') {
|
||||||
for (int k = 0; k < matchingEndTags.size(); k++) {
|
k = skipCodeSpan(k);
|
||||||
// FIXME bogus check
|
} else if (chars[k] == c) {
|
||||||
if (matchedElements.size() == tryElements.length) {
|
count += 1;
|
||||||
break;
|
} else {
|
||||||
}
|
if (count > 0 && !Character.isWhitespace(chars[k - count - 1])) {
|
||||||
if (n > l && tryElements[l] != null && ((Integer) matchingEndTags.get(k)).intValue() > l) {
|
// add an int array to possible end tags: [position, nuberOfTokens]
|
||||||
matchedElements.add(tryElements[l]);
|
possibleEndTags.add(new int[] {k - count, count});
|
||||||
n -= l + 1;
|
}
|
||||||
matchingEndTags.set(k, Integer.valueOf(((Integer) matchingEndTags.get(k)).intValue() - l + 1));
|
count = 0;
|
||||||
tryElements[l] = null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while (matchedElements.size() > 0) {
|
for (int l = 1; l >= 0; l--) {
|
||||||
String ctor = (String) matchedElements.pop();
|
if (emph[l] == null && n > l) {
|
||||||
Element elem = "em".equals(ctor) ? (Element) new Emphasis() : new Strong();
|
emph[l] = checkEmphasisInternal(l + 1, possibleEndTags);
|
||||||
elem.open();
|
if (emph[l] != null) {
|
||||||
spanTags.put(Integer.valueOf("strong".equals(ctor) ? 2 : 1), elem);
|
n -= l + 1;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (isEndTag) {
|
|
||||||
for (int z = 2; z > 0; z--) {
|
|
||||||
Element elem = (Element) spanTags.get(Integer.valueOf(z));
|
|
||||||
if (elem != null && elem.m <= n) {
|
|
||||||
spanTags.remove(Integer.valueOf(z));
|
|
||||||
elem.close();
|
|
||||||
n -= elem.m;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (n == found) {
|
if (n == found) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
// write out remaining token chars
|
||||||
for (int m = 0; m < n; m++) {
|
for (int m = 0; m < n; m++) {
|
||||||
buffer.append(c);
|
buffer.append(c);
|
||||||
}
|
}
|
||||||
|
@ -495,6 +484,20 @@ public class MarkdownProcessor {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Emphasis checkEmphasisInternal(int length, List possibleEndTags) {
|
||||||
|
for (int k = 0; k < possibleEndTags.size(); k++) {
|
||||||
|
int[] possibleEndTag = (int[]) possibleEndTags.get(k);
|
||||||
|
if (possibleEndTag[1] >= length) {
|
||||||
|
Emphasis elem = new Emphasis(length, possibleEndTag[0]);
|
||||||
|
elem.open();
|
||||||
|
possibleEndTag[0] += length;
|
||||||
|
possibleEndTag[1] -= length;
|
||||||
|
return elem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
private boolean checkCodeSpan(char c) {
|
private boolean checkCodeSpan(char c) {
|
||||||
if (c != '`') {
|
if (c != '`') {
|
||||||
return false;
|
return false;
|
||||||
|
@ -542,6 +545,37 @@ public class MarkdownProcessor {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// find the end of a code span starting at start
|
||||||
|
private int skipCodeSpan(int start) {
|
||||||
|
int n = 0; // additional backticks to match
|
||||||
|
int j = start + 1;
|
||||||
|
while(j < length && chars[j] == '`') {
|
||||||
|
n += 1;
|
||||||
|
j += 1;
|
||||||
|
}
|
||||||
|
outer: while(j < length) {
|
||||||
|
if (chars[j] == '`') {
|
||||||
|
if (n == 0) {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
if (j + n >= length) {
|
||||||
|
return start + 1;
|
||||||
|
}
|
||||||
|
for (int k = j + 1; k <= j + n; k++) {
|
||||||
|
if (chars[k] != '`') {
|
||||||
|
break;
|
||||||
|
} else if (k == j + n) {
|
||||||
|
j = k;
|
||||||
|
break outer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
j += 1;
|
||||||
|
}
|
||||||
|
return j;
|
||||||
|
}
|
||||||
|
|
||||||
private boolean checkLink(char c) {
|
private boolean checkLink(char c) {
|
||||||
return checkLinkInternal(c, i + 1, false);
|
return checkLinkInternal(c, i + 1, false);
|
||||||
}
|
}
|
||||||
|
@ -1089,7 +1123,7 @@ public class MarkdownProcessor {
|
||||||
|
|
||||||
class Element {
|
class Element {
|
||||||
String tag;
|
String tag;
|
||||||
int nesting, m;
|
int nesting, mod;
|
||||||
|
|
||||||
void open() {
|
void open() {
|
||||||
openTag(tag, buffer);
|
openTag(tag, buffer);
|
||||||
|
@ -1145,16 +1179,11 @@ public class MarkdownProcessor {
|
||||||
}
|
}
|
||||||
|
|
||||||
class Emphasis extends Element {
|
class Emphasis extends Element {
|
||||||
Emphasis() {
|
int end;
|
||||||
this.tag = "em";
|
Emphasis(int mod, int end) {
|
||||||
this.m = 1;
|
this.mod = mod;
|
||||||
}
|
this.end = end;
|
||||||
}
|
this.tag = mod == 1 ? "em" : "strong";
|
||||||
|
|
||||||
class Strong extends Element {
|
|
||||||
Strong() {
|
|
||||||
this.tag = "strong";
|
|
||||||
this.m = 2;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue