-
Notifications
You must be signed in to change notification settings - Fork 38
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Feature] Consider using Prism.js for code rendering #241
Comments
Applying Prism.js for markdown rendering in the DevoxxGenie plugin would be a great way to enhance code highlighting and improve the overall user experience. Let's go through the steps to integrate Prism.js into the DevoxxGenie plugin.
// Add these files to your resources folder
/resources/assets/prism.js
/resources/assets/prism-hooks.js
package com.devoxx.genie.ui.util;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.util.Computable;
import org.jetbrains.annotations.NotNull;
import javax.script.*;
import java.io.InputStreamReader;
import java.util.List;
public class HtmlUtil {
private static final ScriptEngine engine;
static {
engine = new ScriptEngineManager().getEngineByName("graal.js");
try {
engine.eval(new InputStreamReader(HtmlUtil.class.getResourceAsStream("/assets/prism.js")));
engine.eval(new InputStreamReader(HtmlUtil.class.getResourceAsStream("/assets/prism-hooks.js")));
engine.eval("function highlight(code, language) { return Prism.highlight(code, Prism.languages[language], language); }");
} catch (ScriptException e) {
throw new RuntimeException("Failed to initialize Prism.js", e);
}
}
public static String highlightCode(String code, String language) {
return ApplicationManager.getApplication().runReadAction((Computable<String>) () -> {
try {
return (String) ((Invocable) engine).invokeFunction("highlight", code, language);
} catch (ScriptException | NoSuchMethodException e) {
throw new RuntimeException("Failed to highlight code", e);
}
});
}
// Add other HTML utility methods as needed
}
package com.devoxx.genie.ui.panel;
import com.devoxx.genie.ui.util.HtmlUtil;
import org.commonmark.node.*;
import org.commonmark.parser.Parser;
import org.commonmark.renderer.html.HtmlRenderer;
// ... other imports
public class ChatResponsePanel extends BackgroundPanel {
// ... other fields and methods
private void renderMarkdown(String markdown) {
Parser parser = Parser.builder().build();
Node document = parser.parse(markdown);
HtmlRenderer htmlRenderer = HtmlRenderer.builder()
.nodeRendererFactory(context -> new CodeBlockNodeRenderer(context))
.build();
String html = htmlRenderer.render(document);
// Apply the rendered HTML to your panel
// You might need to use a JEditorPane or similar component to display HTML
}
private class CodeBlockNodeRenderer implements NodeRenderer {
private final HtmlRenderer.HtmlNodeRendererContext context;
CodeBlockNodeRenderer(HtmlRenderer.HtmlNodeRendererContext context) {
this.context = context;
}
@Override
public Set<Class<? extends Node>> getNodeTypes() {
return new HashSet<>(Arrays.asList(FencedCodeBlock.class, IndentedCodeBlock.class));
}
@Override
public void render(Node node) {
if (node instanceof FencedCodeBlock) {
FencedCodeBlock codeBlock = (FencedCodeBlock) node;
String language = codeBlock.getInfo();
String code = codeBlock.getLiteral();
String highlightedCode = HtmlUtil.highlightCode(code, language);
context.getWriter().raw("<pre><code class=\"language-" + language + "\">" + highlightedCode + "</code></pre>");
} else if (node instanceof IndentedCodeBlock) {
// Handle indented code blocks similarly
}
}
}
}
package com.devoxx.genie.ui.util;
public class PrismCssUtil {
public static String getPrismCss() {
return """
code[class*="language-"],
pre[class*="language-"] {
color: #f8f8f2;
background: none;
text-shadow: 0 1px rgba(0, 0, 0, 0.3);
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
font-size: 1em;
text-align: left;
white-space: pre;
word-spacing: normal;
word-break: normal;
word-wrap: normal;
line-height: 1.5;
-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;
-webkit-hyphens: none;
-moz-hyphens: none;
-ms-hyphens: none;
hyphens: none;
}
/* Add more Prism.js CSS rules here */
""";
}
}
private String wrapHtmlContent(String htmlContent) {
return String.format("""
<!DOCTYPE html>
<html>
<head>
<style>
%s
</style>
</head>
<body>
%s
</body>
</html>
""", PrismCssUtil.getPrismCss(), htmlContent);
}
package com.devoxx.genie.ui.panel;
import com.devoxx.genie.ui.util.HtmlUtil;
import org.commonmark.node.*;
import org.commonmark.parser.Parser;
// ... other imports
public class ChatStreamingResponsePanel extends BackgroundPanel {
private final StringBuilder markdownContent = new StringBuilder();
private final JEditorPane editorPane;
// ... constructor and other methods
public void insertToken(String token) {
SwingUtilities.invokeLater(() -> {
markdownContent.append(token);
String html = renderMarkdown(markdownContent.toString());
editorPane.setText(html);
});
}
private String renderMarkdown(String markdown) {
Parser parser = Parser.builder().build();
Node document = parser.parse(markdown);
String html = renderNode(document);
return wrapHtmlContent(html);
}
private String renderNode(Node node) {
if (node instanceof FencedCodeBlock) {
FencedCodeBlock codeBlock = (FencedCodeBlock) node;
String language = codeBlock.getInfo();
String code = codeBlock.getLiteral();
return "<pre><code class=\"language-" + language + "\">" + HtmlUtil.highlightCode(code, language) + "</code></pre>";
}
// Handle other node types...
return "";
}
} By implementing these changes, you'll be able to use Prism.js for syntax highlighting in your DevoxxGenie plugin. This will provide a more visually appealing and readable output for code snippets in your chat responses. Remember to test thoroughly, as integrating JavaScript engines and modifying the rendering process can sometimes lead to unexpected behaviors or performance issues. You may need to fine-tune the implementation based on your specific requirements and the structure of your plugin. |
IDEA Darcula theme |
Light theme @ https://github.com/joseluisgp/Prism-IntelliJ-Light |
"Prism is a lightweight, extensible syntax highlighter, built with modern web standards in mind. It’s used in millions of websites, including some of those you visit daily."
https://prismjs.com/
The text was updated successfully, but these errors were encountered: