Skip to content

Commit 1137bd6

Browse files
Add syntax highlighting to Clojure documentation codeblocks (#52)
* Add syntax highlighting to clojure documentation * Enhance code with suggestions * Add CHANGELOG.md
1 parent a93096e commit 1137bd6

File tree

4 files changed

+67
-5
lines changed

4 files changed

+67
-5
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
## [Unreleased]
44

5+
- Add syntax highlighting to Clojure documentation codeblocks
6+
57
## 2.4.5
68

79
- Only log server communication when trace-level matches.

build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ dependencies {
3636
exclude("org.clojure", "core.async")
3737
}
3838
implementation ("com.rpl:proxy-plus:0.0.9")
39-
implementation ("markdown-clj:markdown-clj:1.11.4")
39+
implementation ("markdown-clj:markdown-clj:1.12.1")
4040
}
4141

4242
sourceSets {

deps.edn

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
seesaw/seesaw {:mvn/version "1.5.0"}
77
camel-snake-kebab/camel-snake-kebab {:mvn/version "0.4.3"}
88
com.github.clojure-lsp/clojure-lsp {:mvn/version "2024.03.01-11.37.51"}
9-
markdown-clj/markdown-clj {:mvn/version "1.11.4"}
9+
markdown-clj/markdown-clj {:mvn/version "1.12.1"}
1010
com.rpl/proxy-plus {:mvn/version "0.0.9"}}
1111
:aliases {:dev {:deps {nrepl/nrepl {:mvn/version "1.0.0"}
1212
com.jetbrains.intellij.platform/ide-impl {:mvn/version "213.7172.48"

src/main/clojure/com/github/clojure_lsp/intellij/extension/documentation.clj

Lines changed: 63 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,65 @@
99
(:import
1010
[com.intellij.openapi.util.text StringUtil]
1111
[com.intellij.openapi.util.text HtmlBuilder]
12-
[com.intellij.psi PsiDocumentManager PsiElement PsiFile]))
12+
[com.intellij.psi PsiDocumentManager PsiElement PsiFile]
13+
[com.intellij.openapi.fileTypes SyntaxHighlighterFactory]
14+
[com.intellij.openapi.editor.colors EditorColorsManager]
15+
[com.github.clojure_lsp.intellij ClojureLanguage]
16+
[java.awt Color]))
1317

1418
(set! *warn-on-reflection* true)
1519

20+
(defn ^:private rgb-html-style [^Color color]
21+
(str "rgb(" (.getRed color) ", " (.getGreen color) ", " (.getBlue color) ")"))
22+
23+
(defn ^:private html-style [prop value]
24+
(if (some? value)
25+
(str prop ":" value ";")
26+
""))
27+
28+
(defn ^:private highlight-html-text
29+
[^String text {:keys [foreground-color background-color font-type]}]
30+
(let [color-style (html-style "color" (when foreground-color
31+
(rgb-html-style foreground-color)))
32+
background-style (html-style "background-color" (when background-color
33+
(rgb-html-style foreground-color)))
34+
font-weight-style (html-style "font-weight" (case font-type
35+
:bold "bold"
36+
:bold-italic "bold"
37+
"normal"))
38+
font-style (html-style "font-style" (case font-type
39+
:italic "italic"
40+
:bold-italic "italic"
41+
"normal"))]
42+
(str "<span style=\"" color-style background-style font-weight-style font-style "\">" text "</span>")))
43+
44+
(defn ^:private highlight-html-code [^String code]
45+
(let [highlighter (SyntaxHighlighterFactory/getSyntaxHighlighter (ClojureLanguage/INSTANCE) nil nil)
46+
lexer (.getHighlightingLexer highlighter)
47+
color-scheme (.getGlobalScheme (EditorColorsManager/getInstance))]
48+
(loop [highlighted-code ""]
49+
(if (empty? highlighted-code)
50+
(.start lexer code)
51+
(.advance lexer))
52+
(let [lexer-not-finished? (.getTokenType lexer)]
53+
(if lexer-not-finished?
54+
(let [text (.getTokenText lexer)
55+
highlight (first (.getTokenHighlights highlighter (.getTokenType lexer)))
56+
highlight-attrs (.getAttributes color-scheme highlight)
57+
foreground-color (some-> highlight-attrs .getForegroundColor)
58+
background-color (some-> highlight-attrs .getBackgroundColor)
59+
font-type (some-> highlight-attrs .getFontType (#(case (int %)
60+
1 :bold
61+
2 :italic
62+
3 :bold-italic
63+
nil)))]
64+
(if (some some? [foreground-color background-color font-type])
65+
(recur (str highlighted-code (highlight-html-text text {:foreground-color foreground-color
66+
:background-color background-color
67+
:font-type font-type})))
68+
(recur (str highlighted-code text))))
69+
highlighted-code)))))
70+
1671
(defn ^:private build-doc [^PsiElement element]
1772
(when-let [client (db/get-in (.getProject element) [:client])]
1873
(when-let [psi-file ^PsiFile (.getContainingFile element)]
@@ -25,9 +80,14 @@
2580
:position {:line (.line line-col)
2681
:character (.column line-col)}}])]
2782

28-
(when-let [raw-html (markdown/md-to-html-string (:value contents))]
83+
(when-let [html (markdown/md-to-html-string (:value contents)
84+
:codeblock-no-escape? true
85+
:codeblock-callback (fn [code language]
86+
(if (= language "clojure")
87+
(highlight-html-code code)
88+
code)))]
2989
(-> (HtmlBuilder.)
30-
(.appendRaw raw-html)
90+
(.appendRaw html)
3191
(.toString)))))))
3292

3393
(defn -getCustomDocumentationElement

0 commit comments

Comments
 (0)