Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
- Fixed markdown preview not rendering images (`![alt](path)` syntax)
- Fixed session tab blocking resize below ~600px when docked as a side panel (https://github.com/nbclaudecodegui/NetbeansClaudeCodeGui/issues/19)
- Fixed terminal appearing blank after dismissing the model selection menu
- Fixed MCP connection to localhost being routed through an active HTTP_PROXY/HTTPS_PROXY; NO_PROXY is now automatically extended with localhost and 127.0.0.1 when a proxy is configured
Expand Down
4 changes: 2 additions & 2 deletions docs/to-do.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@

- [x] **Tooltip "Stop session" → "Close session"** — `ClaudeSessionTab.java:229`: переименовать tooltip кнопки `stopButton` с "Stop session" на "Close session" (кнопка закрывает сессию, а не останавливает процесс).
- [x] **IDE restore не сохраняет режим Resume specific** — `ClaudeSessionTab.writeExternal()` сохраняет значение настройки `contextMenuSessionMode` вместо фактического режима/resumeId, с которым была открыта сессия. Если сессия была открыта через "Resume specific", после рестарта IDE она восстановится в режиме Continue last (или New), а не возобновит ту же конкретную сессию.
- [ ] Drag and drop in a text field: вставлять в текущую позицию курсора, а не
- [x] Drag and drop in a text field: вставлять в текущую позицию курсора, а не
сдвигать позицию курсора. Рднако, возможность перемещения позиции курсора кликом должна быть созранена
- [x] Невозможно выйти из /usage по кнопке cancel. Отладить
- [x] Не учитываются цвета Look and Feel для кнопок
- [ ] Previe markdown: не показываются изображения
- [x] Previe markdown: не показываются изображения
- [ ] Previe markdown: не работает навигация по линкам внутри файла

# Features
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<groupId>io.github.nbclaudecodegui</groupId>
<artifactId>netbeans-claude-code-gui</artifactId>
<version>0.21.49-SNAPSHOT</version>
<version>0.21.50-SNAPSHOT</version>
<packaging>nbm</packaging>
<name>Netbeans Claude Code GUI</name>
<description>NetBeans plugin that provides a GUI for Claude Code CLI — run claude code sessions directly inside the IDE.</description>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ public static void openLive(String filePath, String content, FileObject fo) {
tab.fileObject = fo;

String html = MarkdownRenderer.toHtml(content != null ? content : "");
tab.pane = MarkdownRenderer.createOutputPane(html);
tab.pane = MarkdownRenderer.createOutputPane(html, new java.io.File(filePath).getParent());

String name = new java.io.File(filePath).getName();
tab.setDisplayName("Preview: " + name);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ public final class MarkdownRenderer {
+ "|\\*\\*(.+?)\\*\\*" // group 2: bold
+ "|\\*([^*\\n]+)\\*" // group 3: italic
+ "|`([^`]+)`" // group 4: inline code
+ "|\\[([^\\]]+)\\]\\(([^)]+)\\)", // group 5: link text, group 6: link url
+ "|!\\[([^\\]]*)\\]\\(([^)]+)\\)" // group 5: image alt, group 6: image src
+ "|\\[([^\\]]+)\\]\\(([^)]+)\\)", // group 7: link text, group 8: link url
Pattern.DOTALL);

// -------------------------------------------------------------------------
Expand All @@ -64,6 +65,28 @@ public static JEditorPane createOutputPane(String html) {
return pane;
}

/**
* Creates and configures a {@link JEditorPane} with HTML content and a base directory for
* resolving relative image paths.
*
* @param html initial HTML content to display
* @param baseDirPath absolute path of the directory containing the rendered file, or null
* @return a ready-to-use output pane
*/
public static JEditorPane createOutputPane(String html, String baseDirPath) {
JEditorPane pane = createOutputPane();
if (baseDirPath != null) {
try {
((HTMLDocument) pane.getDocument()).setBase(
new java.net.URL("file://" + baseDirPath + "/"));
} catch (java.net.MalformedURLException ignored) {
// fall through — relative images won't resolve but nothing breaks
}
}
pane.setText(html);
return pane;
}

/**
* Creates and configures a {@link JEditorPane} for rendering chat output with no initial content.
*
Expand Down Expand Up @@ -398,8 +421,11 @@ static String inlineToHtml(String text) {
} else if (m.group(4) != null) {
sb.append("<code>").append(esc(m.group(4))).append("</code>");
} else if (m.group(5) != null) {
sb.append("<a href=\"").append(esc(m.group(6))).append("\">")
.append(esc(m.group(5))).append("</a>");
sb.append("<img src=\"").append(esc(m.group(6)))
.append("\" alt=\"").append(esc(m.group(5))).append("\">");
} else if (m.group(7) != null) {
sb.append("<a href=\"").append(esc(m.group(8))).append("\">")
.append(esc(m.group(7))).append("</a>");
}
lastEnd = m.end();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -208,4 +208,33 @@ void testTableFollowedByParagraph() {
assertTrue(html.contains("<table>"), "table present");
assertTrue(html.contains("Some text after"), "paragraph after table");
}

// -------------------------------------------------------------------------
// Bug 2: Images
// -------------------------------------------------------------------------

@Test
void testInlineImage() {
String result = MarkdownRenderer.inlineToHtml("![alt text](image.png)");
assertTrue(result.contains("<img "), "img tag");
assertTrue(result.contains("src=\"image.png\""), "img src");
assertTrue(result.contains("alt=\"alt text\""), "img alt");
assertFalse(result.contains("!["), "raw markdown should not appear");
}

@Test
void testInlineImageInParagraph() {
String html = MarkdownRenderer.toHtml("Here is an image: ![logo](logo.png)");
assertTrue(html.contains("<img "), "img tag in paragraph");
assertTrue(html.contains("src=\"logo.png\""), "img src");
}

@Test
void testInlineImageEmptyAlt() {
String result = MarkdownRenderer.inlineToHtml("![](photo.jpg)");
assertTrue(result.contains("<img "), "img tag");
assertTrue(result.contains("src=\"photo.jpg\""), "img src");
assertTrue(result.contains("alt=\"\""), "empty alt");
}

}
Loading