Dave Jarvis' Repositories

git clone https://repo.autonoma.ca/repo/keenwrite.git

Add Unicode support (emojis), TODOs, and speech bubbles

AuthorDaveJarvis <email>
Date2022-04-02 12:47:28 GMT-0700
Commit28a03c6f7e8ff8783b2675e2d589a2198195bcf3
Parenta0702c3
src/main/java/com/keenwrite/dom/DocumentParser.java
import static com.keenwrite.events.StatusEvent.clue;
+import static java.nio.charset.StandardCharsets.UTF_16;
import static java.nio.charset.StandardCharsets.UTF_8;
import static javax.xml.transform.OutputKeys.*;
sTransformer = TransformerFactory.newInstance().newTransformer();
+ // Ensure Unicode characters (emojis) are encoded correctly.
+ sTransformer.setOutputProperty( ENCODING, UTF_16.toString() );
sTransformer.setOutputProperty( OMIT_XML_DECLARATION, "yes" );
sTransformer.setOutputProperty( METHOD, "xml" );
- sTransformer.setOutputProperty( ENCODING, UTF_8.toString() );
sTransformer.setOutputProperty( INDENT, "yes" );
sTransformer.setOutputProperty( INDENT_AMOUNT, "2" );
src/main/resources/com/keenwrite/preview/webview.css
}
+/* SPEECH BUBBLE ***/
+div.bubblerx, div.bubbletx {
+ display: table;
+ padding: .5em;
+ padding-top: .25em;
+ padding-bottom: .25em;
+ margin: 1em;
+ position: relative;
+ border-radius: .25em;
+ background-color: #ccc;
+
+ font-family: 'OpenSansEmoji', sans-serif;
+ font-size: 95%;
+}
+
+/* Transmit bubble on the right. */
+div.bubbletx {
+ margin-left: auto;
+}
+
+div.bubblerx:after, div.bubbletx:after {
+ content: "";
+ position: absolute;
+ width: 0;
+ height: 0;
+ top: .5em;
+ border-top: 1em solid transparent;
+ border-bottom: 1em solid transparent;
+}
+
+div.bubblerx::after {
+ left: -1em;
+ right: auto;
+ border-right: 1em solid #ccc;
+ border-left: none;
+}
+
+div.bubbletx:after {
+ right: -1em;
+ border-left: 1em solid #ccc;
+}
+
src/main/resources/fonts/emoji/OpenSansEmoji-Regular.otf
Binary files differ
src/test/java/com/keenwrite/flexmark/ParserTest.java
}
+ private List<Extension> createExtensions() {
+ final var extensions = new ArrayList<Extension>();
+
+ extensions.add( DefinitionExtension.create() );
+ extensions.add( StrikethroughSubscriptExtension.create() );
+ extensions.add( SuperscriptExtension.create() );
+ extensions.add( TablesExtension.create() );
+ extensions.add( FencedDivExtension.create() );
+
+ return extensions;
+ }
+
private static Stream<Arguments> markdownParameters() {
return Stream.of(
)
);
- }
-
- private List<Extension> createExtensions() {
- final var extensions = new ArrayList<Extension>();
-
- extensions.add( DefinitionExtension.create() );
- extensions.add( StrikethroughSubscriptExtension.create() );
- extensions.add( SuperscriptExtension.create() );
- extensions.add( TablesExtension.create() );
- extensions.add( FencedDivExtension.create() );
-
- return extensions;
}
}
src/test/java/com/keenwrite/processors/html/XhtmlProcessorTest.java
+package com.keenwrite.processors.html;
+
+import com.keenwrite.ExportFormat;
+import com.keenwrite.editors.common.Caret;
+import com.keenwrite.processors.ProcessorContext;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import java.io.File;
+import java.nio.file.Path;
+import java.util.HashMap;
+import java.util.stream.Stream;
+
+import static com.keenwrite.ExportFormat.HTML_TEX_DELIMITED;
+import static com.keenwrite.ExportFormat.XHTML_TEX;
+import static com.keenwrite.processors.ProcessorContext.builder;
+import static com.keenwrite.processors.ProcessorFactory.createProcessors;
+import static java.util.Locale.ENGLISH;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class XhtmlProcessorTest {
+
+ /**
+ * Contains the thumbs up emoji.
+ */
+ private static final String EMOJI_MARKDOWN = "the \uD83D\uDC4D emoji";
+
+ @ParameterizedTest
+ @MethodSource( "formatParameters" )
+ void test_Conversion_EmojiInput_EncodedEmoji(
+ final ExportFormat format, final String expected ) {
+ final var context = createProcessorContext( format );
+ final var processor = createProcessors( context );
+ final var actual = processor.apply( EMOJI_MARKDOWN );
+
+ assertEquals( expected, actual );
+ }
+
+ private static ProcessorContext createProcessorContext(
+ final ExportFormat format ) {
+ final var caret = Caret.builder().build();
+ return builder()
+ .with( ProcessorContext.Mutator::setExportFormat, format )
+ .with( ProcessorContext.Mutator::setInputPath, Path.of( "f.md" ) )
+ .with( ProcessorContext.Mutator::setDefinitions, HashMap::new )
+ .with( ProcessorContext.Mutator::setLocale, () -> ENGLISH )
+ .with( ProcessorContext.Mutator::setMetadata, HashMap::new )
+ .with( ProcessorContext.Mutator::setThemePath, () -> Path.of( "b" ) )
+ .with( ProcessorContext.Mutator::setCaret, () -> caret )
+ .with( ProcessorContext.Mutator::setImageDir, () -> new File( "i" ) )
+ .with( ProcessorContext.Mutator::setImageOrder, () -> "" )
+ .with( ProcessorContext.Mutator::setImageServer, () -> "" )
+ .with( ProcessorContext.Mutator::setSigilBegan, () -> "" )
+ .with( ProcessorContext.Mutator::setSigilEnded, () -> "" )
+ .with( ProcessorContext.Mutator::setRScript, () -> "" )
+ .with( ProcessorContext.Mutator::setRWorkingDir, () -> Path.of( "r" ) )
+ .with( ProcessorContext.Mutator::setCurlQuotes, () -> true )
+ .with( ProcessorContext.Mutator::setAutoClean, () -> true )
+ .build();
+ }
+
+ private static Stream<Arguments> formatParameters() {
+ return Stream.of(
+ Arguments.of(
+ HTML_TEX_DELIMITED,
+ "<p id=\"caret\">the \uD83D\uDC4D emoji</p>\n"
+ ),
+ Arguments.of(
+ XHTML_TEX,
+ """
+ <html>
+ <head>
+ <title> </title>
+ <meta charset="utf8"/>
+ <meta content="2" name="count"/>
+ </head>
+ <body>
+ <p id="caret">the 👍 emoji</p>
+ </body>
+ </html>
+ """
+ )
+ );
+ }
+}
Delta143 lines added, 13 lines removed, 130-line increase