Skip to content

Commit

Permalink
Merge branch 'main' into 98-pastedocument
Browse files Browse the repository at this point in the history
  • Loading branch information
jperedadnr committed May 14, 2024
2 parents 413c1bc + dcc8e77 commit b199647
Show file tree
Hide file tree
Showing 6 changed files with 171 additions and 7 deletions.
13 changes: 11 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ on:

jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
os: [ macos-latest, ubuntu-latest, windows-latest ]
runs-on: ${{ matrix.os }}
steps:
- name: Checkout
uses: actions/checkout@v3
Expand All @@ -23,13 +26,19 @@ jobs:
server-password: MAVEN_CENTRAL_TOKEN

- name: Build project
if: runner.os != 'Linux'
run: |
mvn -B -ntp verify -f rta
- name: Build project (Linux)
if: runner.os == 'Linux'
run: |
export DISPLAY=:90
Xvfb -ac :90 -screen 0 1280x1024x24 > /dev/null 2>&1 &
mvn -B -ntp verify -f rta
- name: Publish Snapshots
if: github.ref == 'refs/heads/main'
if: github.ref == 'refs/heads/main' && runner.os == 'Linux'
run: |
ver=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout -f rta)
if [[ $ver == *"SNAPSHOT"* ]]; then
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ To use the RichTextArea control in your project add the following dependency:
<dependency>
<groupId>com.gluonhq</groupId>
<artifactId>rich-text-area</artifactId>
<version>1.1.2</version>
<version>1.1.3</version>
</dependency>
```

Expand Down
2 changes: 1 addition & 1 deletion rta/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.gluonhq</groupId>
<artifactId>rich-text-area</artifactId>
<version>1.1.3-SNAPSHOT</version>
<version>1.1.4-SNAPSHOT</version>
<packaging>jar</packaging>

<name>Rich Text Area</name>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ public void apply(RichTextAreaViewModel viewModel) {
viewModel.getCommandManager().undo();

// Update selection accordingly, removing from the original selection the length of the
// removed last unit (based on the length of the text)
newSelection = new Selection(selection.getStart(), Math.min(selection.getEnd(), viewModel.getTextLength()));
// removed last unit
newSelection = new Selection(selection.getStart(), selection.getEnd() - 1);
}
viewModel.getCommandManager().execute(new SelectAndReplaceCmd(
viewModel.getTextBuffer().getInternalSelection(newSelection), content));
Expand Down
155 changes: 155 additions & 0 deletions rta/src/test/java/com/gluonhq/richtextarea/ui/RTATest.java
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,16 @@

import java.nio.CharBuffer;
import java.util.List;
import java.util.Locale;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.BiConsumer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import static com.gluonhq.emoji.EmojiData.getEmojiCollection;
import static com.gluonhq.richtextarea.RichTextArea.RTA_DATA_FORMAT;
import static javafx.scene.input.KeyCode.A;
import static javafx.scene.input.KeyCode.END;
Expand Down Expand Up @@ -96,6 +101,14 @@ public class RTATest {
private BorderPane root;
private RichTextArea richTextArea;

private static final Pattern codenamePattern = Pattern.compile(":([a-zA-Z0-9_-]*):");
private static final Pattern asciiPattern = Pattern.compile("D:|C:|c:|:D|:-D|>:\\(|>:-\\(|=\\)|=-\\)|<3|</3|;p|;-p|;b|;-b|;P|;-P|" +
";\\)|;-\\)|:\\||:-\\||:p|:-p|:P|:-P|:b|:-b|:o|:-o|:O|:-O|:\\\\|:-\\\\|:/|:-/|:>|:->|" +
":\\*|:-\\*|:\\)|\\(:|:-\\)|:'\\(|8\\)|\\):|:\\(|:-\\("); // "D:|:D|:-D" don't work, ":o)" is superseded by ":o"
private static final List<Emoji> asciiEmojiList = getEmojiCollection().stream()
.filter(e -> e.getTextList() != null)
.collect(Collectors.toList());

@BeforeEach
public void setup() {
if (!fxStarted) {
Expand Down Expand Up @@ -551,6 +564,148 @@ public void copyPasteTest(FxRobot robot) {
assertEquals(NORMAL, ((TextDecoration) dm1.getDecoration()).getFontWeight());
}

@Test
public void findASCIIEmojiTest(FxRobot robot) {
run(() -> {
richTextArea.documentProperty().subscribe(d -> {
String nv = d.getText();
if (nv != null) {
String substring = nv.substring(0, Math.min(richTextArea.getCaretPosition(), nv.length())).toLowerCase(Locale.ROOT);
findEmoji(substring,
(emoji, start) -> richTextArea.getActionFactory().selectAndInsertEmoji(
new Selection(start, richTextArea.getCaretPosition()), emoji, true).execute(new ActionEvent()));
}
});
richTextArea.getActionFactory().newDocument().execute(new ActionEvent());
richTextArea.setAutoSave(true);
});
waitForFxEvents();

RichTextArea rta = robot.lookup(".rich-text-area").query();

robot.write("<3");
assertEquals(1, rta.getTextLength());
assertEquals(2, rta.getDocument().getText().length());
String text = "\u2764\ufe0f";
assertEquals(text, rta.getDocument().getText());
assertEquals(1, robot.lookup(node -> node instanceof ImageView).queryAll().size());

run(() -> richTextArea.getActionFactory().undo().execute(new ActionEvent()));
waitForFxEvents();

assertEquals(0, robot.lookup(node -> node instanceof ImageView).queryAll().size());
assertEquals("<", rta.getDocument().getText());

run(() -> richTextArea.getActionFactory().redo().execute(new ActionEvent()));
waitForFxEvents();

assertEquals(1, robot.lookup(node -> node instanceof ImageView).queryAll().size());
assertEquals(text, rta.getDocument().getText());

robot.push(new KeyCodeCombination(A, SHORTCUT_DOWN));
robot.write("<3 <3 <3 <3 <3 <3 <3 <3");
assertEquals(15, rta.getTextLength());
assertEquals(23, rta.getDocument().getText().length());
text = "\u2764\ufe0f \u2764\ufe0f \u2764\ufe0f \u2764\ufe0f \u2764\ufe0f \u2764\ufe0f \u2764\ufe0f \u2764\ufe0f";
assertEquals(text, rta.getDocument().getText());
assertEquals(8, robot.lookup(node -> node instanceof ImageView).queryAll().size());

robot.push(new KeyCodeCombination(A, SHORTCUT_DOWN));
robot.write("C: c: >:( >:-( =) =-) <3 </3 ;p ;-p ;b ;-b ;P ;-P " +
";) ;-) :| :-| :p :-p :P :-P :b :-b :o :-o :O :-O :\\ :-\\ :/ :-/ :> :-> " +
":* :-* :) (: :-) :'( 8) ): :( :-(");

assertEquals(87, rta.getTextLength());
assertEquals(131, rta.getDocument().getText().length());
text = "\ud83d\ude04 \ud83d\ude04 \ud83d\ude20 \ud83d\ude20 \ud83d\ude03 \ud83d\ude03 \u2764\ufe0f \ud83d\udc94 \ud83d\ude1c \ud83d\ude1c \ud83d\ude1c \ud83d\ude1c \ud83d\ude1c \ud83d\ude1c \ud83d\ude09 \ud83d\ude09 \ud83d\ude10 \ud83d\ude10 \ud83d\ude1b \ud83d\ude1b \ud83d\ude1b \ud83d\ude1b \ud83d\ude1b \ud83d\ude1b \ud83d\ude2e \ud83d\ude2e \ud83d\ude2e \ud83d\ude2e \ud83d\ude15 \ud83d\ude15 \ud83d\ude15 \ud83d\ude15 \ud83d\ude06 \ud83d\ude06 \ud83d\ude18 \ud83d\ude18 \ud83d\ude42 \ud83d\ude42 \ud83d\ude42 \ud83d\ude22 \ud83d\ude0e \ud83d\ude1e \ud83d\ude1e \ud83d\ude1e";
assertEquals(text, rta.getDocument().getText());
assertEquals(44, robot.lookup(node -> node instanceof ImageView).queryAll().size());

robot.push(new KeyCodeCombination(A, SHORTCUT_DOWN));
robot.write("https://www.wikipedia.org");
assertEquals(0, robot.lookup(node -> node instanceof ImageView).queryAll().size());
assertEquals("https://www.wikipedia.org", rta.getDocument().getText());
}

@Test
public void findCodeNameEmojiTest(FxRobot robot) {
run(() -> {
richTextArea.documentProperty().subscribe(d -> {
String nv = d.getText();
if (nv != null) {
String substring = nv.substring(0, Math.min(richTextArea.getCaretPosition(), nv.length())).toLowerCase(Locale.ROOT);
findEmoji(substring,
(emoji, start) -> richTextArea.getActionFactory().selectAndInsertEmoji(
new Selection(start, richTextArea.getCaretPosition()), emoji, true).execute(new ActionEvent()));
}
});
richTextArea.getActionFactory().newDocument().execute(new ActionEvent());
richTextArea.setAutoSave(true);
});
waitForFxEvents();

RichTextArea rta = robot.lookup(".rich-text-area").query();

robot.write(":wink:");
assertEquals(1, rta.getTextLength());
assertEquals(2, rta.getDocument().getText().length());
String text = "\ud83d\ude09";
assertEquals(text, rta.getDocument().getText());
assertEquals(1, robot.lookup(node -> node instanceof ImageView).queryAll().size());

run(() -> richTextArea.getActionFactory().undo().execute(new ActionEvent()));
waitForFxEvents();

assertEquals(0, robot.lookup(node -> node instanceof ImageView).queryAll().size());
assertEquals(":wink", rta.getDocument().getText());

run(() -> richTextArea.getActionFactory().redo().execute(new ActionEvent()));
waitForFxEvents();

assertEquals(1, robot.lookup(node -> node instanceof ImageView).queryAll().size());
assertEquals(text, rta.getDocument().getText());

robot.push(new KeyCodeCombination(A, SHORTCUT_DOWN));
robot.write(":flag-wales:");
assertEquals(1, rta.getTextLength());
assertEquals(14, rta.getDocument().getText().length());
text = "\ud83c\udff4\udb40\udc67\udb40\udc62\udb40\udc77\udb40\udc6c\udb40\udc73\udb40\udc7f";
assertEquals(text, rta.getDocument().getText());
assertEquals(1, robot.lookup(node -> node instanceof ImageView).queryAll().size());

robot.push(new KeyCodeCombination(A, SHORTCUT_DOWN));
robot.write("this is a:wink:");
assertEquals(0, robot.lookup(node -> node instanceof ImageView).queryAll().size());
assertEquals("this is a:wink:", rta.getDocument().getText());
}

private static void findEmoji(String text, BiConsumer<Emoji, Integer> onCodeNameFound) {
if (text.endsWith(" ")) {
return;
}
int wordBeginIndex = Math.max(text.lastIndexOf(" ") + 1, text.lastIndexOf("\n") + 1);
String word = text.substring(wordBeginIndex);
Matcher asciiMatcher = asciiPattern.matcher(word);
if (asciiMatcher.find() && asciiMatcher.start() == 0) {
// check if word is an ascii emoji and replace
asciiEmojiList.stream()
.filter(e -> e.getTextList().contains(asciiMatcher.group()))
.findFirst()
.ifPresent(emoji -> onCodeNameFound.accept(emoji, wordBeginIndex));
return;
}
if (word.startsWith(":") && word.length() > 2) {
// check if word contains an emoji codename :name:
if (word.substring(1).contains(":")) {
Matcher matcher = codenamePattern.matcher(word);
if (matcher.find()) {
EmojiData.emojiFromShortName(matcher.group(1))
.ifPresent(emoji -> onCodeNameFound.accept(emoji, wordBeginIndex));
}
}
}
}

private void run(Runnable runnable) {
CountDownLatch countDownLatch = new CountDownLatch(1);
Platform.runLater(() -> {
Expand Down
2 changes: 1 addition & 1 deletion samples/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
<javafx.plugin.version>0.0.8</javafx.plugin.version>
<main.class>com.gluonhq.richtextarea.samples.FullFeaturedDemo</main.class>
<jpro.version>2022.1.0</jpro.version>
<rta.version>1.1.3-SNAPSHOT</rta.version>
<rta.version>1.1.4-SNAPSHOT</rta.version>
</properties>

<dependencies>
Expand Down

0 comments on commit b199647

Please sign in to comment.