Skip to content

Commit

Permalink
Merge pull request #452 from devoxx/issue-168
Browse files Browse the repository at this point in the history
🥳
<img width="1001" alt="Screenshot 2025-01-28 at 09 58 48" src="https://github.com/user-attachments/assets/a81b778b-6013-43f6-ba65-6cc0fc53f900" />
  • Loading branch information
stephanj authored Jan 28, 2025
2 parents 57d81ef + ab00cf6 commit 010282e
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 51 deletions.
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ plugins {
}

group = "com.devoxx.genie"
version = "0.4.10"
version = "0.4.11"

repositories {
mavenCentral()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,6 @@
import com.intellij.lang.Language;
import com.intellij.lang.documentation.DocumentationSettings;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.editor.HighlighterColors;
import com.intellij.openapi.editor.colors.EditorColorsManager;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.editor.richcopy.HtmlSyntaxInfoUtil;
import com.intellij.openapi.fileTypes.PlainTextLanguage;
import com.intellij.openapi.project.Project;
Expand All @@ -20,7 +17,8 @@
import org.commonmark.renderer.html.HtmlWriter;
import org.jetbrains.annotations.NotNull;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
Expand All @@ -38,17 +36,14 @@ public class CodeBlockNodeRenderer implements NodeRenderer {
private final Project project;
private final HtmlWriter htmlOutputWriter;

public CodeBlockNodeRenderer(Project project, @NotNull
HtmlNodeRendererContext context) {
public CodeBlockNodeRenderer(Project project, @NotNull HtmlNodeRendererContext context) {
this.project = project;
this.htmlOutputWriter = context.getWriter();
}

@Override
public Set<Class<? extends Node>> getNodeTypes() {
return Set.of(
IndentedCodeBlock.class, FencedCodeBlock.class, Code.class
);
return Set.of(IndentedCodeBlock.class, FencedCodeBlock.class, Code.class);
}

@Override
Expand All @@ -59,30 +54,56 @@ public void render(Node node) {
renderNode(fencedCodeBlock.getLiteral(), fencedCodeBlock.getInfo(), true);
} else if (node instanceof Code code) {
renderNode(code.getLiteral(), false);
} else {
System.err.println("Unknown node type: " + node);
}
}

private void renderNode(String codeSnippet, String info, boolean block) {
htmlOutputWriter.line();

if (block) {
htmlOutputWriter.tag("pre");
// Style to ensure proper whitespace handling
Map<String, String> preStyle = new HashMap<>();
preStyle.put("style", "-webkit-user-select: text; user-select: text; white-space: pre !important;");
htmlOutputWriter.tag("pre", preStyle);
}

htmlOutputWriter.tag("code", Collections.singletonMap("style", "font-size:14pt"));
// Critical: we need to handle newlines properly in the code tag
Map<String, String> codeStyle = new HashMap<>();
codeStyle.put("style", "font-size:14pt; white-space: pre !important; -webkit-user-select: text; user-select: text;");
htmlOutputWriter.tag("code", codeStyle);

HighlightingMode highlightingMode = determineHighlightingMode(block);
Language language = LanguageGuesser.guessLanguage(info);
if (language == null) {
language = PlainTextLanguage.INSTANCE;
}

// Get highlighted code
StringBuilder highlightedCode = new StringBuilder();
Language finalLanguage = language;
ApplicationManager.getApplication().runReadAction(() -> {
if (highlightingMode == HighlightingMode.SEMANTIC_HIGHLIGHTING) {
HtmlSyntaxInfoUtil.appendHighlightedByLexerAndEncodedAsHtmlCodeSnippet(
highlightedCode,
project,
finalLanguage,
codeSnippet,
false,
DocumentationSettings.getHighlightingSaturation(true)
);
} else {
highlightedCode.append(StringUtil.escapeXmlEntities(codeSnippet));
}
});

// Process the code to ensure proper line breaks
String processedCode = highlightedCode.toString()
.replace("&#32;", " ") // Convert space entities to spaces
.replaceAll("</span><span[^>]*><br></span>", "\n") // Convert br tags to newlines
.replaceAll("<br>\\s*", "\n") // Handle any remaining br tags
.replaceAll("\\n", "</span>\n<span>"); // Ensure spans wrap around newlines

htmlOutputWriter.raw(
appendHighlightedByLexerAndEncodedAsHtmlCodeSnippet(
highlightingMode,
project,
LanguageGuesser.guessLanguage(info) != null ? LanguageGuesser.guessLanguage(info) : PlainTextLanguage.INSTANCE,
codeSnippet
)
);
htmlOutputWriter.raw(processedCode);

htmlOutputWriter.tag("/code");

Expand Down Expand Up @@ -110,31 +131,4 @@ private HighlightingMode determineHighlightingMode(boolean block) {
return HighlightingMode.INLINE_HIGHLIGHTING;
}
}

private @NotNull String appendHighlightedByLexerAndEncodedAsHtmlCodeSnippet(
HighlightingMode highlightingMode, Project project, Language language, String codeSnippet) {
StringBuilder highlightedAndEncodedAsHtmlCodeSnippet = new StringBuilder();
ApplicationManager.getApplication().runReadAction(() -> {
if (highlightingMode == HighlightingMode.SEMANTIC_HIGHLIGHTING) {
HtmlSyntaxInfoUtil.appendHighlightedByLexerAndEncodedAsHtmlCodeSnippet(
highlightedAndEncodedAsHtmlCodeSnippet,
project,
language,
codeSnippet,
false,
DocumentationSettings.getHighlightingSaturation(true)
);
} else {
highlightedAndEncodedAsHtmlCodeSnippet.append(StringUtil.escapeXmlEntities(codeSnippet));
}
});

if (highlightingMode != HighlightingMode.NO_HIGHLIGHTING) {
TextAttributes codeAttributes =
EditorColorsManager.getInstance().getGlobalScheme().getAttributes(HighlighterColors.TEXT).clone();
codeAttributes.setBackgroundColor(null);
}

return highlightedAndEncodedAsHtmlCodeSnippet.toString();
}
}
}
6 changes: 5 additions & 1 deletion src/main/resources/META-INF/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,13 @@
]]></description>

<change-notes><![CDATA[
<h2>V0.4.11</h2>
<UL>
<LI>Fix #168 : Preserve new line when copying code from response by @stephanj</LI>
</UL>
<h2>V0.4.10</h2>
<UL>
<LI>Fix #440 : Fix for the custom OpenAI chat memory issue</LI>
<LI>Fix #440 : Fix for the custom OpenAI chat memory issue by @stephanj</LI>
<LI>Feat #443 : Add initial support for AWS Bedrock by @pavel-rodionov</LI>
<LI>Fix #447 : Broken UI elements on Windows/Linux fixed</LI>
</UL>
Expand Down

0 comments on commit 010282e

Please sign in to comment.