Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prevent italic or strikethrough emojis on Android #534

Open
wants to merge 13 commits into
base: main
Choose a base branch
from
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.expensify.livemarkdown;

public class MarkdownRange {
public String type;
public int start;
public int end;
public int length;
public int depth;
Skalakid marked this conversation as resolved.
Show resolved Hide resolved

public MarkdownRange(String type, int start, int end, int depth) {
this.type = type;
this.start = start;
this.end = end;
this.length = end - start + 1;
this.depth = depth;
Skalakid marked this conversation as resolved.
Show resolved Hide resolved

Skalakid marked this conversation as resolved.
Show resolved Hide resolved
}
}
78 changes: 63 additions & 15 deletions android/src/main/java/com/expensify/livemarkdown/MarkdownUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

public class MarkdownUtils {
Expand Down Expand Up @@ -66,6 +68,62 @@ public void setMarkdownStyle(@NonNull MarkdownStyle markdownStyle) {
mMarkdownStyle = markdownStyle;
}

private List<MarkdownRange> splitRangesOnEmojis(List<MarkdownRange> markdownRanges) {
List<MarkdownRange> emojiRanges = new ArrayList<>();
for (MarkdownRange range : markdownRanges) {
if (range.type.equals("emoji")) {
emojiRanges.add(range);
}
}

for (int i = 0; i < markdownRanges.size(); i++) {
MarkdownRange range = markdownRanges.get(i);
if (!range.type.equals("italic") && !range.type.equals("strikethrough")) {
continue;
}

for (int j = 0; j < emojiRanges.size(); j++) {
Skalakid marked this conversation as resolved.
Show resolved Hide resolved
Skalakid marked this conversation as resolved.
Show resolved Hide resolved
MarkdownRange emojiRange = emojiRanges.get(j);
if (emojiRange.start >= range.start && emojiRange.end <= range.end) {
// Split range
MarkdownRange startRange = new MarkdownRange(range.type, range.start, emojiRange.start, range.depth);
MarkdownRange endRange = new MarkdownRange(range.type, emojiRange.end, range.end, range.depth);
Skalakid marked this conversation as resolved.
Show resolved Hide resolved
markdownRanges.add(i + 1, endRange);
markdownRanges.add(i + 1, startRange);
Skalakid marked this conversation as resolved.
Show resolved Hide resolved
markdownRanges.remove(i);
i += 1;
Skalakid marked this conversation as resolved.
Show resolved Hide resolved
range = endRange;
} else {
break;
}
}
}
return markdownRanges;
}


private MarkdownRange[] parseRanges(String rangesJSON) {
try {
List<MarkdownRange> markdownRanges = new ArrayList<>();
JSONArray ranges = new JSONArray(rangesJSON);
for (int i = 0; i < ranges.length(); i++) {
JSONObject range = ranges.getJSONObject(i);
String type = range.getString("type");
int start = range.getInt("start");
int length = range.getInt("length");
int depth = range.optInt("depth", 1);
int end = start + length;
Skalakid marked this conversation as resolved.
Show resolved Hide resolved
markdownRanges.add(new MarkdownRange(type, start, end, depth));
}
List<MarkdownRange> splittedRanges = splitRangesOnEmojis(markdownRanges);
Skalakid marked this conversation as resolved.
Show resolved Hide resolved
return splittedRanges.toArray(new MarkdownRange[0]);
Skalakid marked this conversation as resolved.
Show resolved Hide resolved
} catch (JSONException e) {
return new MarkdownRange[0];
}
}



public void applyMarkdownFormatting(SpannableStringBuilder ssb) {
Objects.requireNonNull(mMarkdownStyle, "mMarkdownStyle is null");

Expand All @@ -81,22 +139,12 @@ public void applyMarkdownFormatting(SpannableStringBuilder ssb) {
mPrevOutput = output;
}

try {
JSONArray ranges = new JSONArray(output);
for (int i = 0; i < ranges.length(); i++) {
JSONObject range = ranges.getJSONObject(i);
String type = range.getString("type");
int start = range.getInt("start");
int length = range.getInt("length");
int depth = range.optInt("depth", 1);
int end = start + length;
if (length == 0 || end > input.length()) {
continue;
}
applyRange(ssb, type, start, end, depth);
MarkdownRange[] ranges = parseRanges(output);
for (MarkdownRange range: ranges) {
Skalakid marked this conversation as resolved.
Show resolved Hide resolved
if (range.length == 0 || range.end > input.length()) {
continue;
}
Skalakid marked this conversation as resolved.
Show resolved Hide resolved
} catch (JSONException e) {
// Do nothing
applyRange(ssb, range.type, range.start, range.end, range.depth);
}
}

Expand Down
2 changes: 2 additions & 0 deletions parser/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,8 @@ function getTagPriority(tag: string) {
return 2;
case 'h1':
return 1;
case 'emoji':
return -1;
default:
return 0;
}
Expand Down
2 changes: 1 addition & 1 deletion parser/react-native-live-markdown-parser.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 7 additions & 2 deletions src/web/utils/blockUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,13 @@ function addStyleToBlock(targetElement: HTMLElement, type: NodeType, markdownSty
node.style.textDecoration = 'line-through';
break;
case 'emoji':
Object.assign(node.style, {...markdownStyle.emoji, verticalAlign: 'middle'});
Object.assign(node.style, {
...markdownStyle.emoji,
verticalAlign: 'middle',
fontStyle: 'normal',
textDecoration: 'none',
display: 'inline-block',
});
break;
case 'mention-here':
Object.assign(node.style, markdownStyle.mentionHere);
Expand All @@ -49,7 +55,6 @@ function addStyleToBlock(targetElement: HTMLElement, type: NodeType, markdownSty
case 'pre':
Object.assign(node.style, markdownStyle.pre);
break;

case 'blockquote':
Object.assign(node.style, {
...markdownStyle.blockquote,
Expand Down
Loading