Skip to content

Commit

Permalink
[23] JEP 467: Render markdown doc comments
Browse files Browse the repository at this point in the history
fixes #1472
  • Loading branch information
stephan-herrmann authored and jjohnstn committed Aug 13, 2024
1 parent 961b17a commit e51121d
Show file tree
Hide file tree
Showing 3 changed files with 622 additions and 10 deletions.
3 changes: 2 additions & 1 deletion org.eclipse.jdt.core.manipulation/META-INF/MANIFEST.MF
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.31.0,4.0.0)",
org.eclipse.core.filesystem;bundle-version="1.10.0",
org.eclipse.core.filebuffers;bundle-version="3.8.0",
org.eclipse.search.core;bundle-version="3.16.0",
org.commonmark;bundle-version="0.22.0"
org.commonmark;bundle-version="0.22.0",
org.commonmark-gfm-tables;bundle-version="0.22.0"
Bundle-ActivationPolicy: lazy
Export-Package: org.eclipse.jdt.core.manipulation,
org.eclipse.jdt.core.refactoring,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,42 +13,108 @@
*******************************************************************************/
package org.eclipse.jdt.core.manipulation.internal.javadoc;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.commonmark.Extension;
import org.commonmark.ext.gfm.tables.TablesExtension;
import org.commonmark.node.Document;
import org.commonmark.node.Node;
import org.commonmark.node.Paragraph;
import org.commonmark.parser.Parser;
import org.commonmark.renderer.html.HtmlRenderer;

import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.Javadoc;
import org.eclipse.jdt.core.dom.TagElement;
import org.eclipse.jdt.core.dom.TextElement;

public class CoreMarkdownAccessImpl extends CoreJavadocAccessImpl {

private Parser fParser;
private HtmlRenderer fRenderer;
private int fBlockDepth= 0;

public CoreMarkdownAccessImpl(IJavaElement element, Javadoc javadoc, String source) {
super(element, javadoc, source);
init();
}

public CoreMarkdownAccessImpl(IJavaElement element, Javadoc javadoc, String source, JavadocLookup lookup) {
super(element, javadoc, source, lookup);
init();
}

private void init() {
List<Extension> extensions= List.of(TablesExtension.create());
fParser= Parser.builder().extensions(extensions).build();
fRenderer= HtmlRenderer.builder().extensions(extensions).build();
}

@Override
protected String removeDocLineIntros(String textWithStars) {
protected String removeDocLineIntros(String textWithSlashes) {
String lineBreakGroup= "(\\r\\n?|\\n)"; //$NON-NLS-1$
String noBreakSpace= "[^\r\n&&\\s]"; //$NON-NLS-1$
return textWithStars.replaceAll(lineBreakGroup + noBreakSpace + "///" /*+ noBreakSpace + '?'*/, "$1"); //$NON-NLS-1$ //$NON-NLS-2$
return textWithSlashes.replaceAll(lineBreakGroup + noBreakSpace + "*///" /*+ noBreakSpace + '?'*/, "$1"); //$NON-NLS-1$ //$NON-NLS-2$
}

@Override
protected void handleLink(List<? extends ASTNode> fragments) {
if (fragments.size() == 2 && fragments.get(0) instanceof TextElement) {
// super method expects the reference as first fragment, optional label as second fragment
fragments= Arrays.asList(fragments.get(1), fragments.get(0));
}
super.handleLink(fragments);
}

@Override
protected String getBlockTagStart() {
this.fBlockDepth++;
return "\n"+super.getBlockTagStart(); //$NON-NLS-1$
}

@Override
public String toHTML() {
String content = super.toHTML();
Parser parser = Parser.builder().build();
Node document = parser.parse(content);
HtmlRenderer renderer = HtmlRenderer.builder().build();
return renderer.render(document);
protected String getBlockTagEnd() {
if (this.fBlockDepth > 0)
this.fBlockDepth--;
return super.getBlockTagEnd();
}

@Override
protected void handleContentElements(List<? extends ASTNode> nodes, boolean skipLeadingWhitespace, TagElement tagElement) {
int start= fBuf.length();
super.handleContentElements(nodes, skipLeadingWhitespace, tagElement);
if (this.fBlockDepth > 0) {
// inside an HTML block the markdown content must be rendered now
String generated= fBuf.substring(start); // extract new part of fBuf
Node node= fParser.parse(generated);
if (node.getFirstChild() instanceof Paragraph para && para.getNext() == null) {
// inside block replace single paragraph with its children
node= eliminateContainerNode(para);
}
String rendered= fRenderer.render(node);
fBuf.replace(start, fBuf.length(), rendered); // replace new part with its rendered version
}
}

/** Return a new Document containing all children of the given container node. */
protected Node eliminateContainerNode(Node container) {
List<Node> children= new ArrayList<>();
for (Node child= container.getFirstChild(); child != null; child= child.getNext()) {
children.add(child);
}
Document doc= new Document();
for (Node child2 : children) {
doc.appendChild(child2);
}
return doc;
}

@Override
public String toHTML() {
String content= super.toHTML();
Node document= fParser.parse(content);
return fRenderer.render(document);
}
}
Loading

0 comments on commit e51121d

Please sign in to comment.