Skip to content

Commit

Permalink
Attempt superscript
Browse files Browse the repository at this point in the history
  • Loading branch information
MV-GH committed Feb 27, 2024
1 parent 5b482d1 commit 537081a
Show file tree
Hide file tree
Showing 11 changed files with 550 additions and 1 deletion.
1 change: 1 addition & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ dependencies {
implementation("io.noties.markwon:core:4.6.2")
implementation("io.noties.markwon:ext-strikethrough:4.6.2")
implementation("io.noties.markwon:ext-tables:4.6.2")
implementation("io.noties.markwon:inline-parser:4.6.2")
implementation("io.noties.markwon:html:4.6.2")
implementation("io.noties.markwon:image-coil:4.6.2")
implementation("io.noties.markwon:linkify:4.6.2")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import com.jerboa.util.markwon.BetterLinkMovementMethod
import com.jerboa.util.markwon.ForceHttpsPlugin
import com.jerboa.util.markwon.MarkwonLemmyLinkPlugin
import com.jerboa.util.markwon.MarkwonSpoilerPlugin
import com.jerboa.util.markwon.script.SuperscriptPlugin
import io.noties.markwon.AbstractMarkwonPlugin
import io.noties.markwon.Markwon
import io.noties.markwon.MarkwonConfiguration
Expand All @@ -42,6 +43,8 @@ import io.noties.markwon.html.HtmlPlugin
import io.noties.markwon.html.TagHandlerNoOp
import io.noties.markwon.image.AsyncDrawableSpan
import io.noties.markwon.image.coil.ClickableCoilImagesPlugin
import io.noties.markwon.inlineparser.HtmlInlineProcessor
import io.noties.markwon.inlineparser.MarkwonInlineParserPlugin
import io.noties.markwon.linkify.LinkifyPlugin
import io.noties.markwon.movement.MovementMethodPlugin
import java.util.regex.Pattern
Expand Down Expand Up @@ -92,6 +95,10 @@ object MarkdownHelper {
.usePlugin(ForceHttpsPlugin())
// email urls interfere with lemmy links
.usePlugin(LinkifyPlugin.create(Linkify.WEB_URLS))
.usePlugin(MarkwonInlineParserPlugin.create { plugin ->
plugin.excludeInlineProcessor(HtmlInlineProcessor::class.java)
})
.usePlugin(SuperscriptPlugin.create())
.usePlugin(MarkwonLemmyLinkPlugin())
.usePlugin(MarkwonSpoilerPlugin(true))
.usePlugin(StrikethroughPlugin.create())
Expand Down Expand Up @@ -126,6 +133,10 @@ object MarkdownHelper {
Markwon.builder(context)
// email urls interfere with lemmy links
.usePlugin(LinkifyPlugin.create(Linkify.WEB_URLS))
.usePlugin(MarkwonInlineParserPlugin.create { plugin ->
plugin.excludeInlineProcessor(HtmlInlineProcessor::class.java)
})
.usePlugin(SuperscriptPlugin.create())
.usePlugin(MarkwonLemmyLinkPlugin())
.usePlugin(StrikethroughPlugin.create())
.usePlugin(TablePlugin.create(context))
Expand Down
22 changes: 22 additions & 0 deletions app/src/main/java/com/jerboa/util/markwon/script/Superscript.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.jerboa.util.markwon.script;

import org.commonmark.node.CustomNode;
import org.commonmark.node.Visitor;

// Source : https://codeberg.org/Bazsalanszky/Eternity/src/commit/3c871e26781d26df7b7f92b8633580b6087a8223/app/src/main/java/eu/toldi/infinityforlemmy/markdown/Superscript.java
public class Superscript extends CustomNode {
private boolean isBracketed;

@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}

public boolean isBracketed() {
return isBracketed;
}

public void setBracketed(boolean bracketed) {
isBracketed = bracketed;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package com.jerboa.util.markwon.script;

import static io.noties.markwon.inlineparser.InlineParserUtils.mergeChildTextNodes;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import org.commonmark.node.Node;

import io.noties.markwon.inlineparser.InlineProcessor;

public class SuperscriptClosingInlineProcessor extends InlineProcessor {
@NonNull
private final SuperscriptOpeningStorage superscriptOpeningStorage;

public SuperscriptClosingInlineProcessor(@NonNull SuperscriptOpeningStorage superscriptOpeningStorage) {
this.superscriptOpeningStorage = superscriptOpeningStorage;
}

@Override
public char specialCharacter() {
return ')';
}

@Nullable
@Override
protected Node parse() {
SuperscriptOpeningBracket superscriptOpening = superscriptOpeningStorage.pop(block);
if (superscriptOpening == null) {
return null;
}
index++;

Superscript superscript = new Superscript();
superscript.setBracketed(true);
Node node = superscriptOpening.node.getNext();
while (node != null) {
Node next = node.getNext();
superscript.appendChild(node);
node = next;
}

// Process delimiters such as emphasis inside spoiler
processDelimiters(superscriptOpening.previousDelimiter);
mergeChildTextNodes(superscript);
// We don't need the corresponding text node anymore, we turned it into a spoiler node
superscriptOpening.node.unlink();

return superscript;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.jerboa.util.markwon.script;

import org.commonmark.node.Node;

public class SuperscriptOpening {
/**
* Node that contains non-bracketed superscript opening markdown ({@code ^}).
*/
public final Node node;

public final Integer start;

public SuperscriptOpening(Node node, int start) {
this.node = node;
this.start = start;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.jerboa.util.markwon.script;

import org.commonmark.internal.Delimiter;
import org.commonmark.node.Node;

public class SuperscriptOpeningBracket {
/**
* Node that contains superscript opening bracket markdown ({@code ^(}).
*/
public final Node node;

/**
* Previous superscript opening bracket.
*/
public final SuperscriptOpeningBracket previous;

/**
* Previous delimiter (emphasis, etc) before this bracket.
*/
public final Delimiter previousDelimiter;

public final Integer start;

public SuperscriptOpeningBracket(Node node, SuperscriptOpeningBracket previous, Delimiter previousDelimiter) {
this.node = node;
this.previous = previous;
this.previousDelimiter = previousDelimiter;
this.start = null;
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package com.jerboa.util.markwon.script;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import org.commonmark.node.Node;
import org.commonmark.node.Text;

import io.noties.markwon.inlineparser.InlineProcessor;

public class SuperscriptOpeningInlineProcessor extends InlineProcessor {
@NonNull
private final SuperscriptOpeningStorage superscriptOpeningStorage;

public SuperscriptOpeningInlineProcessor(@NonNull SuperscriptOpeningStorage superscriptOpeningStorage) {
this.superscriptOpeningStorage = superscriptOpeningStorage;
}

@Override
public char specialCharacter() {
return '^';
}

@Nullable
@Override
protected Node parse() {
index++;
char c = peek();
if (c != '\0' && !Character.isWhitespace(c)) {
if (c == '(') {
index++;
Text node = text("^(");
superscriptOpeningStorage.add(block, node, lastDelimiter());
return node;
}

if (lastDelimiter() != null && lastDelimiter().canOpen && block.getLastChild() != null) {
if (lastDelimiter().node == this.block.getLastChild()) {
if (lastDelimiter().delimiterChar == peek()) {
index--;
return null;
}
}
}

return new Superscript();
}
return null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.jerboa.util.markwon.script;

import androidx.annotation.Nullable;

import org.commonmark.internal.Delimiter;
import org.commonmark.node.Node;

public class SuperscriptOpeningStorage {
@Nullable
private SuperscriptOpeningBracket lastBracket;
private Node currentBlock;

public void clear() {
lastBracket = null;
}

public void add(Node block, Node node, Delimiter lastDelimiter) {
updateBlock(block);
lastBracket = new SuperscriptOpeningBracket(node, lastBracket, lastDelimiter);
}

@Nullable
public SuperscriptOpeningBracket pop(Node block) {
updateBlock(block);
SuperscriptOpeningBracket opening = lastBracket;
if (opening != null) {
lastBracket = opening.previous;
}
return opening;
}

private void updateBlock(Node block) {
if (block != currentBlock) {
clear();
}
currentBlock = block;
}
}
Loading

0 comments on commit 537081a

Please sign in to comment.