Update sample (toc plugin)
This commit is contained in:
		
							parent
							
								
									3ee62a724c
								
							
						
					
					
						commit
						3ef41b1b81
					
				| @ -89,7 +89,7 @@ public class AnchorHeadingPlugin extends AbstractMarkwonPlugin { | ||||
|     } | ||||
| 
 | ||||
|     @NonNull | ||||
|     private static String createAnchor(@NonNull CharSequence content) { | ||||
|     public static String createAnchor(@NonNull CharSequence content) { | ||||
|         return String.valueOf(content) | ||||
|                 .replaceAll("[^\\w]", "") | ||||
|                 .toLowerCase(); | ||||
|  | ||||
| @ -58,7 +58,8 @@ public class BasicPluginsActivity extends ActivityWithMenuOptions { | ||||
|                 .add("headingNoSpaceBlockHandler", this::headingNoSpaceBlockHandler) | ||||
|                 .add("allBlocksNoForcedLine", this::allBlocksNoForcedLine) | ||||
|                 .add("anchor", this::anchor) | ||||
|                 .add("letterOrderedList", this::letterOrderedList); | ||||
|                 .add("letterOrderedList", this::letterOrderedList) | ||||
|                 .add("tableOfContents", this::tableOfContents); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
| @ -411,4 +412,26 @@ public class BasicPluginsActivity extends ActivityWithMenuOptions { | ||||
| 
 | ||||
|         markwon.setMarkdown(textView, md); | ||||
|     } | ||||
| 
 | ||||
|     private void tableOfContents() { | ||||
|         final String lorem = getString(R.string.lorem); | ||||
|         final String md = "" + | ||||
|                 "# First\n" + | ||||
|                 "" + lorem + "\n\n" + | ||||
|                 "# Second\n" + | ||||
|                 "" + lorem + "\n\n" + | ||||
|                 "## Second level\n\n" + | ||||
|                 "" + lorem + "\n\n" + | ||||
|                 "### Level 3\n\n" + | ||||
|                 "" + lorem + "\n\n" + | ||||
|                 "# First again\n" + | ||||
|                 "" + lorem + "\n\n"; | ||||
| 
 | ||||
|         final Markwon markwon = Markwon.builder(this) | ||||
|                 .usePlugin(new TableOfContentsPlugin()) | ||||
|                 .usePlugin(new AnchorHeadingPlugin((view, top) -> scrollView.smoothScrollTo(0, top))) | ||||
|                 .build(); | ||||
| 
 | ||||
|         markwon.setMarkdown(textView, md); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -0,0 +1,115 @@ | ||||
| package io.noties.markwon.sample.basicplugins; | ||||
| 
 | ||||
| import androidx.annotation.NonNull; | ||||
| 
 | ||||
| import org.commonmark.node.AbstractVisitor; | ||||
| import org.commonmark.node.BulletList; | ||||
| import org.commonmark.node.CustomBlock; | ||||
| import org.commonmark.node.Heading; | ||||
| import org.commonmark.node.Link; | ||||
| import org.commonmark.node.ListItem; | ||||
| import org.commonmark.node.Node; | ||||
| import org.commonmark.node.Text; | ||||
| 
 | ||||
| import io.noties.markwon.AbstractMarkwonPlugin; | ||||
| import io.noties.markwon.MarkwonVisitor; | ||||
| import io.noties.markwon.core.SimpleBlockNodeVisitor; | ||||
| 
 | ||||
| public class TableOfContentsPlugin extends AbstractMarkwonPlugin { | ||||
|     @Override | ||||
|     public void configure(@NonNull Registry registry) { | ||||
|         // just to make it explicit | ||||
|         registry.require(AnchorHeadingPlugin.class); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void configureVisitor(@NonNull MarkwonVisitor.Builder builder) { | ||||
|         builder.on(TableOfContentsBlock.class, new SimpleBlockNodeVisitor()); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void beforeRender(@NonNull Node node) { | ||||
| 
 | ||||
|         // custom block to hold TOC | ||||
|         final TableOfContentsBlock block = new TableOfContentsBlock(); | ||||
| 
 | ||||
|         // create TOC title | ||||
|         { | ||||
|             final Text text = new Text("Table of contents"); | ||||
|             final Heading heading = new Heading(); | ||||
|             // important one - set TOC heading level | ||||
|             heading.setLevel(1); | ||||
|             heading.appendChild(text); | ||||
|             block.appendChild(heading); | ||||
|         } | ||||
| 
 | ||||
|         final HeadingVisitor visitor = new HeadingVisitor(block); | ||||
|         node.accept(visitor); | ||||
| 
 | ||||
|         // make it the very first node in rendered markdown | ||||
|         node.prependChild(block); | ||||
|     } | ||||
| 
 | ||||
|     private static class HeadingVisitor extends AbstractVisitor { | ||||
| 
 | ||||
|         private final BulletList bulletList = new BulletList(); | ||||
|         private final StringBuilder builder = new StringBuilder(); | ||||
|         private boolean isInsideHeading; | ||||
| 
 | ||||
|         HeadingVisitor(@NonNull Node node) { | ||||
|             node.appendChild(bulletList); | ||||
|         } | ||||
| 
 | ||||
|         @Override | ||||
|         public void visit(Heading heading) { | ||||
|             this.isInsideHeading = true; | ||||
|             try { | ||||
|                 // reset build from previous content | ||||
|                 builder.setLength(0); | ||||
| 
 | ||||
|                 // obtain level (can additionally filter by level, to skip lower ones) | ||||
|                 final int level = heading.getLevel(); | ||||
| 
 | ||||
|                 // build heading title | ||||
|                 visitChildren(heading); | ||||
| 
 | ||||
|                 // initial list item | ||||
|                 final ListItem listItem = new ListItem(); | ||||
| 
 | ||||
|                 Node parent = listItem; | ||||
|                 Node node = listItem; | ||||
| 
 | ||||
|                 for (int i = 1; i < level; i++) { | ||||
|                     final ListItem li = new ListItem(); | ||||
|                     final BulletList bulletList = new BulletList(); | ||||
|                     bulletList.appendChild(li); | ||||
|                     parent.appendChild(bulletList); | ||||
|                     parent = li; | ||||
|                     node = li; | ||||
|                 } | ||||
| 
 | ||||
|                 final String content = builder.toString(); | ||||
|                 final Link link = new Link("#" + AnchorHeadingPlugin.createAnchor(content), null); | ||||
|                 final Text text = new Text(content); | ||||
|                 link.appendChild(text); | ||||
|                 node.appendChild(link); | ||||
|                 bulletList.appendChild(listItem); | ||||
| 
 | ||||
| 
 | ||||
|             } finally { | ||||
|                 isInsideHeading = false; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         @Override | ||||
|         public void visit(Text text) { | ||||
|             // can additionally check if we are building heading (to skip all other texts) | ||||
|             if (isInsideHeading) { | ||||
|                 builder.append(text.getLiteral()); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private static class TableOfContentsBlock extends CustomBlock { | ||||
|     } | ||||
| } | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Dimitry Ivanov
						Dimitry Ivanov