Skip to content

Commit 0778c63

Browse files
Using CodeFenceLanguageGuesser + TextMate
1 parent cf9d707 commit 0778c63

File tree

19 files changed

+614
-457
lines changed

19 files changed

+614
-457
lines changed

platform/jewel/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/code/MimeType.kt

Lines changed: 0 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -232,44 +232,6 @@ public value class MimeType(private val mimeType: String) {
232232
}
233233
}
234234

235-
private fun normalizeString(): String {
236-
val normalizedBase = getBaseMimeType()
237-
238-
val attributes =
239-
mimeType
240-
.split(';')
241-
.asSequence()
242-
.drop(1)
243-
.sorted()
244-
.mapNotNull {
245-
val index = it.indexOf('=')
246-
if (index != -1) {
247-
it.substring(0, index).trim() to it.substring(index + 1).trim()
248-
} else {
249-
null
250-
}
251-
}
252-
.filter { isRelevantAttribute(it.first) }
253-
.map { "${it.first}=${it.second}" }
254-
.joinToString("; ")
255-
256-
return if (attributes.isNotBlank()) {
257-
"$normalizedBase; $attributes"
258-
} else {
259-
normalizedBase
260-
}
261-
}
262-
263-
/** Returns whether the given attribute should be included in a normalized string */
264-
private fun isRelevantAttribute(attribute: String): Boolean =
265-
when (attribute) {
266-
ATTR_ROLE,
267-
ATTR_ROOT_TAG,
268-
ATTR_FOLDER_TYPE -> true
269-
270-
else -> false
271-
}
272-
273235
/**
274236
* Returns just the language portion of the mime type.
275237
*
@@ -280,8 +242,6 @@ public value class MimeType(private val mimeType: String) {
280242

281243
internal fun getRole(): String? = getAttribute(ATTR_ROLE)
282244

283-
private fun getFolderType(): String? = getAttribute(ATTR_FOLDER_TYPE)
284-
285245
private fun getAttribute(name: String): String? {
286246
val marker = "$name="
287247
var start = mimeType.indexOf(marker)

platform/jewel/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/code/highlighting/CodeHighlighter.kt

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import androidx.compose.ui.text.AnnotatedString
66
import kotlinx.coroutines.flow.Flow
77
import org.jetbrains.annotations.ApiStatus
88
import org.jetbrains.jewel.foundation.ExperimentalJewelApi
9+
import org.jetbrains.jewel.foundation.code.MimeType
910

1011
@ApiStatus.Experimental
1112
@ExperimentalJewelApi
@@ -25,7 +26,40 @@ public interface CodeHighlighter {
2526
*
2627
* @see [NoOpCodeHighlighter]
2728
*/
28-
public fun highlight(code: String, langName: String?): Flow<AnnotatedString>
29+
@ApiStatus.Obsolete
30+
@Deprecated(
31+
message =
32+
"This method is not scalable as it relies on a pre-resolved MimeType object. " +
33+
"This prevents automatic support for languages not explicitly defined in the MimeType system" +
34+
"(e.g., from TextMate bundles). Use the overload that accepts the raw " +
35+
"`languageFileExtension` string instead.",
36+
replaceWith = ReplaceWith("highlight(code, languageFileExtension = \"\")"),
37+
)
38+
public fun highlight(code: String, mimeType: MimeType?): Flow<AnnotatedString>
39+
40+
/**
41+
* Highlights the given `code` string based on the provided `languageFileExtension`.
42+
*
43+
* This function is highly dynamic. It first attempts to find a native IntelliJ Platform plugin that supports the
44+
* given language extension. If no native plugin is found, it gracefully falls back to using any enabled TextMate
45+
* bundles that match the extension. This allows it to automatically support a wide range of languages without prior
46+
* configuration.
47+
*
48+
* The result is returned as a [Flow] to support dynamic updates, such as when the user changes the active IDE color
49+
* scheme. For simple, static highlighting, you can simply collect the first emitted value.
50+
*
51+
* If the `languageFileExtension` is null or does not correspond to any known language or active TextMate bundle,
52+
* the code will be emitted as a plain, un-styled `AnnotatedString`.
53+
*
54+
* @param code The source code to be highlighted.
55+
* @param languageFileExtension The file extension or Markdown info string identifying the programming language
56+
* (e.g., "kt", "py", "js", "bat"). This is case-insensitive. Common aliases (like "js" for "javascript") are
57+
* supported if there is a native IntelliJ Platform plugin installed that supports the language extension.
58+
* @return A [Flow] that emits an `AnnotatedString` with syntax highlighting applied. The flow may emit new values
59+
* if the underlying color scheme changes.
60+
* @see [NoOpCodeHighlighter]
61+
*/
62+
public fun highlight(code: String, languageFileExtension: String = ""): Flow<AnnotatedString>
2963
}
3064

3165
public val LocalCodeHighlighter: ProvidableCompositionLocal<CodeHighlighter> = staticCompositionLocalOf {

platform/jewel/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/code/highlighting/NoOpCodeHighlighter.kt

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,19 @@ package org.jetbrains.jewel.foundation.code.highlighting
33
import androidx.compose.ui.text.AnnotatedString
44
import kotlinx.coroutines.flow.Flow
55
import kotlinx.coroutines.flow.flowOf
6+
import org.jetbrains.jewel.foundation.code.MimeType
67

78
public object NoOpCodeHighlighter : CodeHighlighter {
8-
override fun highlight(code: String, langName: String?): Flow<AnnotatedString> = flowOf(AnnotatedString(code))
9+
@Deprecated(
10+
message =
11+
"This method is not scalable as it relies on a pre-resolved MimeType object. " +
12+
"This prevents automatic support for languages not explicitly defined in the MimeType system" +
13+
"(e.g., from TextMate bundles). Use the overload that accepts the raw " +
14+
"`languageFileExtension` string instead.",
15+
replaceWith = ReplaceWith("highlight(code, languageFileExtension = \"\")"),
16+
)
17+
override fun highlight(code: String, mimeType: MimeType?): Flow<AnnotatedString> = flowOf(AnnotatedString(code))
18+
19+
override fun highlight(code: String, languageFileExtension: String): Flow<AnnotatedString> =
20+
flowOf(AnnotatedString(code))
921
}

platform/jewel/foundation/src/test/kotlin/org/jetbrains/jewel/foundation/code/MimeTypeTest.kt

Lines changed: 0 additions & 237 deletions
This file was deleted.

platform/jewel/ide-laf-bridge/intellij.platform.jewel.ideLafBridge.iml

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,7 @@
1414
</stringArguments>
1515
<arrayArguments>
1616
<arrayArg name="pluginClasspaths">
17-
<args>
18-
<arg>$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-compose-compiler-plugin/2.2.0/kotlin-compose-compiler-plugin-2.2.0.jar</arg>
19-
</args>
17+
<args>$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-compose-compiler-plugin/2.2.0/kotlin-compose-compiler-plugin-2.2.0.jar</args>
2018
</arrayArg>
2119
</arrayArguments>
2220
</compilerArguments>
@@ -29,6 +27,7 @@
2927
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
3028
<sourceFolder url="file://$MODULE_DIR$/src/main/kotlin" isTestSource="false" />
3129
<sourceFolder url="file://$MODULE_DIR$/ide-laf-bridge-tests/src/test/kotlin" isTestSource="true" />
30+
<sourceFolder url="file://$MODULE_DIR$/src/test/kotlin" isTestSource="true" />
3231
</content>
3332
<orderEntry type="inheritedJdk" />
3433
<orderEntry type="library" name="kotlin-stdlib" level="project" />
@@ -49,5 +48,10 @@
4948
<orderEntry type="module" module-name="intellij.libraries.compose.foundation.desktop" />
5049
<orderEntry type="module" module-name="intellij.platform.editor.ex" />
5150
<orderEntry type="module" module-name="intellij.libraries.compose.foundation.desktop.junit" scope="TEST" />
51+
<orderEntry type="module" module-name="intellij.markdown" />
52+
<orderEntry type="module" module-name="intellij.platform.testFramework" scope="TEST" />
53+
<orderEntry type="module" module-name="intellij.java.testFramework" scope="TEST" />
54+
<orderEntry type="module" module-name="intellij.textmate" scope="TEST" />
55+
<orderEntry type="library" scope="TEST" name="io.mockk.jvm" level="project" />
5256
</component>
5357
</module>

0 commit comments

Comments
 (0)