254 lines
7.6 KiB
Java
254 lines
7.6 KiB
Java
package md2html;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
import markup.*;
|
|
|
|
public class PrimePartCreator {
|
|
|
|
private final String block;
|
|
private int currentChar;
|
|
|
|
public enum MarkdownToken {
|
|
WORD,
|
|
EMPHASIS_STAR,
|
|
STRONG_STAR,
|
|
EMPHASIS_UNDERLINE,
|
|
STRONG_UNDERLINE,
|
|
STRIKEOUT,
|
|
CODE,
|
|
SCREENING,
|
|
NOTHING,
|
|
}
|
|
|
|
public PrimePartCreator(String block) {
|
|
this.block = block;
|
|
currentChar = 0;
|
|
}
|
|
|
|
public PrimePart createPart() {
|
|
PrimePart result;
|
|
if (isHeader()) {
|
|
int levelOfHeader = 0;
|
|
while (
|
|
levelOfHeader < block.length() &&
|
|
block.charAt(levelOfHeader) == '#'
|
|
) {
|
|
levelOfHeader++;
|
|
}
|
|
currentChar = levelOfHeader + 1;
|
|
result = new Header(buildPart(MarkdownToken.WORD), levelOfHeader);
|
|
} else {
|
|
currentChar = 0;
|
|
result = new Paragraph(buildPart(MarkdownToken.WORD));
|
|
}
|
|
return result;
|
|
}
|
|
|
|
private List<PartOfParagraph> buildPart(MarkdownToken currentToken) {
|
|
List<PartOfParagraph> items = new ArrayList<>();
|
|
MarkdownToken token = nextMarkdownToken();
|
|
StringBuilder sb = new StringBuilder();
|
|
while (token != MarkdownToken.NOTHING) {
|
|
if (
|
|
(token == currentToken && currentToken != MarkdownToken.WORD) ||
|
|
isSuffix(currentToken)
|
|
) {
|
|
addToList(items, sb);
|
|
if (
|
|
!(token == currentToken &&
|
|
currentToken != MarkdownToken.WORD)
|
|
) {
|
|
currentChar++;
|
|
}
|
|
break;
|
|
}
|
|
switch (token) {
|
|
case STRIKEOUT -> {
|
|
addToList(items, sb);
|
|
Strikeout strikeout = new Strikeout(buildPart(token));
|
|
items.add(strikeout);
|
|
}
|
|
case STRONG_STAR, STRONG_UNDERLINE -> {
|
|
addToList(items, sb);
|
|
Strong strong = new Strong(buildPart(token));
|
|
items.add(strong);
|
|
}
|
|
case EMPHASIS_STAR, EMPHASIS_UNDERLINE -> {
|
|
addToList(items, sb);
|
|
Emphasis emphasis = new Emphasis(buildPart(token));
|
|
items.add(emphasis);
|
|
}
|
|
case SCREENING -> {
|
|
addToList(items, sb);
|
|
items.add(
|
|
new Text(String.valueOf(block.charAt(currentChar)))
|
|
);
|
|
currentChar++;
|
|
}
|
|
case CODE -> {
|
|
addToList(items, sb);
|
|
Code code = new Code(buildPart(token));
|
|
items.add(code);
|
|
}
|
|
default -> {
|
|
if (currentChar < block.length()) {
|
|
if (block.charAt(currentChar) == '<') {
|
|
sb.append("<");
|
|
} else if (block.charAt(currentChar) == '>') {
|
|
sb.append(">");
|
|
} else if (block.charAt(currentChar) == '&') {
|
|
sb.append("&");
|
|
} else {
|
|
sb.append(block.charAt(currentChar));
|
|
}
|
|
currentChar++;
|
|
}
|
|
}
|
|
}
|
|
token = nextMarkdownToken();
|
|
}
|
|
if (token == MarkdownToken.NOTHING) {
|
|
addToList(items, sb);
|
|
}
|
|
return items;
|
|
}
|
|
|
|
private MarkdownToken nextMarkdownToken() {
|
|
if (currentChar == block.length()) {
|
|
return MarkdownToken.NOTHING;
|
|
}
|
|
switch (block.charAt(currentChar)) {
|
|
case '*' -> {
|
|
if (isPrefix("**")) {
|
|
currentChar += 2;
|
|
return MarkdownToken.STRONG_STAR;
|
|
} else if (isPrefix("*")) {
|
|
currentChar += 1;
|
|
return MarkdownToken.EMPHASIS_STAR;
|
|
}
|
|
}
|
|
case '_' -> {
|
|
if (isPrefix("__")) {
|
|
currentChar += 2;
|
|
return MarkdownToken.STRONG_UNDERLINE;
|
|
} else if (isPrefix("_")) {
|
|
currentChar += 1;
|
|
return MarkdownToken.EMPHASIS_UNDERLINE;
|
|
}
|
|
}
|
|
case '-' -> {
|
|
if (isPrefix("--")) {
|
|
currentChar += 2;
|
|
return MarkdownToken.STRIKEOUT;
|
|
}
|
|
}
|
|
case '`' -> {
|
|
if (isPrefix("`")) {
|
|
currentChar += 1;
|
|
return MarkdownToken.CODE;
|
|
}
|
|
}
|
|
case '\\' -> {
|
|
if (isScreening(block.charAt(currentChar + 1))) {
|
|
currentChar++;
|
|
return MarkdownToken.SCREENING;
|
|
}
|
|
}
|
|
default -> {
|
|
return MarkdownToken.WORD;
|
|
}
|
|
}
|
|
return MarkdownToken.WORD;
|
|
}
|
|
|
|
private static boolean isScreening(char ch) {
|
|
return ch == '*' || ch == '_';
|
|
}
|
|
|
|
private boolean isSuffix(MarkdownToken token) {
|
|
if (token == MarkdownToken.WORD) {
|
|
return false;
|
|
}
|
|
String suffix = getHighlight(token);
|
|
if (isWordInBlock(suffix, currentChar, currentChar + suffix.length())) {
|
|
currentChar += suffix.length() - 1;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private boolean isPrefix(String prefix) {
|
|
int i = currentChar + prefix.length();
|
|
return (
|
|
isValidIndexInBlock(i + prefix.length()) &&
|
|
!isWordInBlock(prefix, i, i + prefix.length()) &&
|
|
isWordInBlock(prefix, i - prefix.length(), i) &&
|
|
!Character.isWhitespace(block.charAt(i))
|
|
);
|
|
}
|
|
|
|
private boolean isWordInBlock(String word, int start, int end) {
|
|
return word.equals(block.substring(start, end));
|
|
}
|
|
|
|
private boolean isValidIndexInBlock(int index) {
|
|
return index < block.length();
|
|
}
|
|
|
|
private boolean isHeader() {
|
|
int levelOfHeader = 0;
|
|
if (block.charAt(levelOfHeader) != '#') {
|
|
return false;
|
|
}
|
|
while (
|
|
levelOfHeader < block.length() && block.charAt(levelOfHeader) == '#'
|
|
) {
|
|
levelOfHeader++;
|
|
}
|
|
return (
|
|
levelOfHeader < block.length() &&
|
|
Character.isWhitespace(block.charAt(levelOfHeader))
|
|
);
|
|
}
|
|
|
|
private static String getHighlight(MarkdownToken token) {
|
|
switch (token) {
|
|
case STRONG_STAR -> {
|
|
return "**";
|
|
}
|
|
case STRONG_UNDERLINE -> {
|
|
return "__";
|
|
}
|
|
case EMPHASIS_STAR -> {
|
|
return "*";
|
|
}
|
|
case EMPHASIS_UNDERLINE -> {
|
|
return "_";
|
|
}
|
|
case CODE -> {
|
|
return "`";
|
|
}
|
|
case STRIKEOUT -> {
|
|
return "--";
|
|
}
|
|
case SCREENING -> {
|
|
return "\\";
|
|
}
|
|
default -> {
|
|
return "";
|
|
}
|
|
}
|
|
}
|
|
|
|
private static void addToList(
|
|
List<PartOfParagraph> items,
|
|
StringBuilder sb
|
|
) {
|
|
if (!sb.isEmpty()) {
|
|
items.add(new Text(sb.toString()));
|
|
sb.setLength(0);
|
|
}
|
|
}
|
|
}
|