mirror of
https://codeberg.org/Bazsalanszky/Infinity-For-Lemmy.git
synced 2024-11-10 12:47:26 +01:00
Merge pull request #572 from scria1000/spoiler-optimize
Optimize spoiler parser
This commit is contained in:
commit
57ab519333
@ -3,6 +3,7 @@ package ml.docilealligator.infinityforreddit.markdown;
|
|||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.text.SpannableStringBuilder;
|
import android.text.SpannableStringBuilder;
|
||||||
import android.text.Spanned;
|
import android.text.Spanned;
|
||||||
|
import android.util.Pair;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
@ -13,8 +14,7 @@ import org.commonmark.node.HtmlBlock;
|
|||||||
import org.commonmark.node.HtmlInline;
|
import org.commonmark.node.HtmlInline;
|
||||||
import org.commonmark.parser.Parser;
|
import org.commonmark.parser.Parser;
|
||||||
|
|
||||||
import java.util.LinkedHashMap;
|
import java.util.ArrayList;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.Stack;
|
import java.util.Stack;
|
||||||
|
|
||||||
@ -58,15 +58,15 @@ public class SpoilerParserPlugin extends AbstractMarkwonPlugin {
|
|||||||
|
|
||||||
SpannableStringBuilder markdownStringBuilder = new SpannableStringBuilder(textView.getText());
|
SpannableStringBuilder markdownStringBuilder = new SpannableStringBuilder(textView.getText());
|
||||||
|
|
||||||
LinkedHashMap<Integer, Integer> spoilers = parse(markdownStringBuilder);
|
ArrayList<Pair<Integer, Integer>> spoilers = parse(markdownStringBuilder);
|
||||||
if (spoilers.size() == 0) {
|
if (spoilers.size() == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int offset = 2;
|
|
||||||
|
|
||||||
for (Map.Entry<Integer, Integer> entry : spoilers.entrySet()) {
|
int offset = 2;
|
||||||
int spoilerStart = entry.getKey() - offset;
|
for (Pair<Integer, Integer> spoiler : spoilers) {
|
||||||
int spoilerEnd = entry.getValue() - offset;
|
int spoilerStart = spoiler.first - offset;
|
||||||
|
int spoilerEnd = spoiler.second - offset;
|
||||||
|
|
||||||
// Try not to set a spoiler span if it's inside a CodeSpan
|
// Try not to set a spoiler span if it's inside a CodeSpan
|
||||||
CodeSpan[] codeSpans = markdownStringBuilder.getSpans(spoilerStart, spoilerEnd, CodeSpan.class);
|
CodeSpan[] codeSpans = markdownStringBuilder.getSpans(spoilerStart, spoilerEnd, CodeSpan.class);
|
||||||
@ -78,6 +78,7 @@ public class SpoilerParserPlugin extends AbstractMarkwonPlugin {
|
|||||||
SpoilerSpan spoilerSpan = new SpoilerSpan(textColor, backgroundColor);
|
SpoilerSpan spoilerSpan = new SpoilerSpan(textColor, backgroundColor);
|
||||||
markdownStringBuilder.setSpan(spoilerSpan, spoilerStart, spoilerEnd, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
markdownStringBuilder.setSpan(spoilerSpan, spoilerStart, spoilerEnd, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
offset += 4;
|
offset += 4;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (CodeSpan codeSpan : codeSpans) {
|
for (CodeSpan codeSpan : codeSpans) {
|
||||||
@ -117,86 +118,45 @@ public class SpoilerParserPlugin extends AbstractMarkwonPlugin {
|
|||||||
// Don't allow more than one new line after every non-blank line
|
// Don't allow more than one new line after every non-blank line
|
||||||
// Try not to care about recursing spoilers, we just want the outermost spoiler because
|
// Try not to care about recursing spoilers, we just want the outermost spoiler because
|
||||||
// spoiler revealing-hiding breaks with recursing spoilers
|
// spoiler revealing-hiding breaks with recursing spoilers
|
||||||
private LinkedHashMap<Integer, Integer> parse(SpannableStringBuilder markdown) {
|
private ArrayList<Pair<Integer, Integer>> parse(SpannableStringBuilder markdown) {
|
||||||
final int MAX_NEW_LINE = 1;
|
final int MAX_NEW_LINE = 1;
|
||||||
var openSpoilerStack = new Stack<Integer>();
|
int length = markdown.length();
|
||||||
var closedSpoilerMap = new LinkedHashMap<Integer, Integer>();
|
Stack<Integer> openSpoilerStack = new Stack<>();
|
||||||
int variable_max_depth = calculateBalance(0, markdown) + 1;
|
ArrayList<Pair<Integer, Integer>> closedSpoilers = new ArrayList<>();
|
||||||
int new_lines = 0;
|
int new_lines = 0;
|
||||||
int depth = 0;
|
for (int i = 0; i < length; i++) {
|
||||||
for (int i = 0; i < markdown.length(); i++) {
|
if (markdown.charAt(i) == '\n') {
|
||||||
if (markdown.charAt(i) == '\u2000' || markdown.charAt(i) == '\t') {
|
|
||||||
continue;
|
|
||||||
} else if (markdown.charAt(i) == '>' && (i + 1) < markdown.length() && markdown.charAt(i + 1) == '!') {
|
|
||||||
openSpoilerStack.push(i + 1);
|
|
||||||
depth++;
|
|
||||||
} else if (openSpoilerStack.size() > 0
|
|
||||||
&& markdown.charAt(i) == '!' && (i + 1) < markdown.length()
|
|
||||||
&& markdown.charAt(i + 1) == '<') {
|
|
||||||
var pos = i + 1;
|
|
||||||
for (int j = 0; j < depth; j++) {
|
|
||||||
if (!openSpoilerStack.isEmpty()) pos = openSpoilerStack.peek();
|
|
||||||
if (pos + 1 <= i) {
|
|
||||||
if (!openSpoilerStack.isEmpty()) pos = openSpoilerStack.peek();
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
if (!openSpoilerStack.isEmpty()) pos = openSpoilerStack.pop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (depth <= variable_max_depth && pos + 1 <= i) //Spoiler content cannot be zero or less length
|
|
||||||
{
|
|
||||||
openSpoilerStack.clear();
|
|
||||||
closedSpoilerMap.put(pos + 1, i);
|
|
||||||
}
|
|
||||||
depth--;
|
|
||||||
} else if (markdown.charAt(i) == '\n') {
|
|
||||||
new_lines++;
|
|
||||||
if (openSpoilerStack.size() >= 1 && new_lines > MAX_NEW_LINE) {
|
|
||||||
openSpoilerStack.clear();
|
|
||||||
new_lines = 0;
|
|
||||||
depth = 0;
|
|
||||||
variable_max_depth = calculateBalance(i, markdown) + 1;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
new_lines = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (openSpoilerStack.size() >= 32) // No
|
|
||||||
{
|
|
||||||
openSpoilerStack.clear();
|
|
||||||
closedSpoilerMap.clear();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return closedSpoilerMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
private int calculateBalance(int index, SpannableStringBuilder line) {
|
|
||||||
final int MAX_NEW_LINE = 1;
|
|
||||||
int new_lines = 0;
|
|
||||||
int opening = 0;
|
|
||||||
int closing = 0;
|
|
||||||
for (int i = index; i < line.length(); i++) {
|
|
||||||
if (line.charAt(i) == '\u0020' || line.charAt(i) == '\t') {
|
|
||||||
continue;
|
|
||||||
} else if (line.charAt(i) == '>'
|
|
||||||
&& (i + 1) < line.length()
|
|
||||||
&& line.charAt(i + 1) == '!') {
|
|
||||||
opening++;
|
|
||||||
} else if (line.charAt(i) == '!' && (i + 1) < line.length()
|
|
||||||
&& line.charAt(i + 1) == '<') {
|
|
||||||
closing++;
|
|
||||||
} else if (line.charAt(i) == '\n') {
|
|
||||||
new_lines++;
|
new_lines++;
|
||||||
if (new_lines > MAX_NEW_LINE) {
|
if (new_lines > MAX_NEW_LINE) {
|
||||||
break;
|
openSpoilerStack.clear();
|
||||||
|
new_lines = 0;
|
||||||
|
}
|
||||||
|
} else if ((markdown.charAt(i) != '>')
|
||||||
|
&& (markdown.charAt(i) != '<')
|
||||||
|
&& (markdown.charAt(i) != '!')) {
|
||||||
|
new_lines = 0;
|
||||||
|
} else if ((i + 1 < length)
|
||||||
|
&& markdown.charAt(i) == '>'
|
||||||
|
&& markdown.charAt(i + 1) == '!') {
|
||||||
|
openSpoilerStack.push(i + 2);
|
||||||
|
} else if ((i + 1 < length) && (i - 1 >= 0)
|
||||||
|
&& openSpoilerStack.size() > 0
|
||||||
|
&& markdown.charAt(i - 1) != '>'
|
||||||
|
&& markdown.charAt(i) == '!'
|
||||||
|
&& markdown.charAt(i + 1) == '<') {
|
||||||
|
var pos = openSpoilerStack.pop();
|
||||||
|
if (!closedSpoilers.isEmpty()
|
||||||
|
&& closedSpoilers.get(closedSpoilers.size() - 1).first > pos
|
||||||
|
&& closedSpoilers.get(closedSpoilers.size() - 1).second < i) {
|
||||||
|
closedSpoilers.remove(closedSpoilers.size() - 1);
|
||||||
|
}
|
||||||
|
if (pos != i) {
|
||||||
|
closedSpoilers.add(Pair.create(pos, i));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
new_lines = 0;
|
new_lines = 0;
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Math.abs(opening - closing);
|
return closedSpoilers;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user