feat(jbm/code): show language

Signed-off-by: Infi <infi@infi.sh>
This commit is contained in:
Infi 2024-09-17 23:27:14 +02:00
parent df234f7902
commit f4085c1c93
2 changed files with 70 additions and 11 deletions

View File

@ -37,6 +37,7 @@ import androidx.compose.ui.graphics.drawscope.Stroke
import androidx.compose.ui.input.pointer.pointerInput import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.AnnotatedString import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.Placeholder import androidx.compose.ui.text.Placeholder
import androidx.compose.ui.text.PlaceholderVerticalAlign import androidx.compose.ui.text.PlaceholderVerticalAlign
@ -49,6 +50,7 @@ import androidx.compose.ui.text.style.TextDecoration
import androidx.compose.ui.text.withStyle import androidx.compose.ui.text.withStyle
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import chat.revolt.R
import chat.revolt.api.settings.GlobalState import chat.revolt.api.settings.GlobalState
import chat.revolt.components.markdown.Annotations import chat.revolt.components.markdown.Annotations
import chat.revolt.components.utils.detectTapGesturesConditionalConsume import chat.revolt.components.utils.detectTapGesturesConditionalConsume
@ -383,9 +385,41 @@ private fun annotateHighlights(
return AnnotatedString(source, spanStyles = highlightStyles) return AnnotatedString(source, spanStyles = highlightStyles)
} }
// ======== TODO ======== val languageAliases = mapOf(
// - Add aliases for languages. For example, "js" should be an alias for "javascript" and "ts" should be an alias for "typescript", etc. "js" to SyntaxLanguage.JAVASCRIPT,
// - Better looking language name display. Ideally a dictionary of language names to display names with proper brand casing. "ts" to SyntaxLanguage.TYPESCRIPT,
"rs" to SyntaxLanguage.RUST,
"cs" to SyntaxLanguage.CSHARP,
"py" to SyntaxLanguage.PYTHON,
"pl" to SyntaxLanguage.PERL,
"bash" to SyntaxLanguage.SHELL,
"sh" to SyntaxLanguage.SHELL,
"py" to SyntaxLanguage.PYTHON,
"coffee" to SyntaxLanguage.COFFEESCRIPT,
"bad" to SyntaxLanguage.PHP // had to
)
val languageDisplayNamedResource = mapOf(
SyntaxLanguage.DEFAULT to R.string.programming_language_default,
SyntaxLanguage.C to R.string.programming_language_c,
SyntaxLanguage.CPP to R.string.programming_language_cpp,
SyntaxLanguage.DART to R.string.programming_language_dart,
SyntaxLanguage.JAVA to R.string.programming_language_java,
SyntaxLanguage.KOTLIN to R.string.programming_language_kotlin,
SyntaxLanguage.RUST to R.string.programming_language_rust,
SyntaxLanguage.CSHARP to R.string.programming_language_csharp,
SyntaxLanguage.COFFEESCRIPT to R.string.programming_language_coffeescript,
SyntaxLanguage.JAVASCRIPT to R.string.programming_language_javascript,
SyntaxLanguage.PERL to R.string.programming_language_perl,
SyntaxLanguage.PYTHON to R.string.programming_language_python,
SyntaxLanguage.RUBY to R.string.programming_language_ruby,
SyntaxLanguage.SHELL to R.string.programming_language_shell,
SyntaxLanguage.SWIFT to R.string.programming_language_swift,
SyntaxLanguage.TYPESCRIPT to R.string.programming_language_typescript,
SyntaxLanguage.GO to R.string.programming_language_go,
SyntaxLanguage.PHP to R.string.programming_language_php,
)
@Composable @Composable
private fun JBMCodeBlockContent(node: ASTNode, modifier: Modifier) { private fun JBMCodeBlockContent(node: ASTNode, modifier: Modifier) {
val state = LocalJBMarkdownTreeState.current val state = LocalJBMarkdownTreeState.current
@ -409,7 +443,9 @@ private fun JBMCodeBlockContent(node: ASTNode, modifier: Modifier) {
} }
val annotatedContent = remember(codeFenceLanguage, codeFenceContent) { val annotatedContent = remember(codeFenceLanguage, codeFenceContent) {
val canAnnotate = codeFenceLanguage != null val canAnnotate = codeFenceLanguage != null
val language = codeFenceLanguage?.let { SyntaxLanguage.getByName(it) } val language = codeFenceLanguage?.let {
languageAliases[it] ?: SyntaxLanguage.getByName(it)
}
val shouldAnnotate = language != null val shouldAnnotate = language != null
if (canAnnotate && shouldAnnotate) { if (canAnnotate && shouldAnnotate) {
@ -435,13 +471,16 @@ private fun JBMCodeBlockContent(node: ASTNode, modifier: Modifier) {
.background(MaterialTheme.colorScheme.surfaceContainer) .background(MaterialTheme.colorScheme.surfaceContainer)
.padding(8.dp) .padding(8.dp)
) { ) {
if (codeFenceLanguage != null) { Text(
Text( text = languageDisplayNamedResource[
text = codeFenceLanguage, languageAliases[codeFenceLanguage]
fontWeight = FontWeight.Bold, ?: SyntaxLanguage.getByName(codeFenceLanguage ?: "")
modifier = Modifier.padding(vertical = 4.dp) ]?.let {
) stringResource(it)
} } ?: stringResource(R.string.programming_language_default),
fontWeight = FontWeight.Bold,
modifier = Modifier.padding(vertical = 4.dp)
)
Box( Box(
modifier = Modifier.horizontalScroll(rememberScrollState()) modifier = Modifier.horizontalScroll(rememberScrollState())
) { ) {

View File

@ -251,6 +251,26 @@
<string name="copy">Copy</string> <string name="copy">Copy</string>
<string name="copied">Copied to clipboard</string> <string name="copied">Copied to clipboard</string>
<!-- See dev.snipme.highlights.model.SyntaxLanguage -->
<string name="programming_language_default">Plain Text</string>
<string name="programming_language_c" translatable="false">C</string>
<string name="programming_language_cpp" translatable="false">C++</string>
<string name="programming_language_dart" translatable="false">Dart</string>
<string name="programming_language_java" translatable="false">Java</string>
<string name="programming_language_kotlin" translatable="false">Kotlin</string>
<string name="programming_language_rust" translatable="false">Rust</string>
<string name="programming_language_csharp" translatable="false">C#</string>
<string name="programming_language_coffeescript" translatable="false">CoffeeScript</string>
<string name="programming_language_javascript" translatable="false">ECMAScript / JS</string>
<string name="programming_language_perl" translatable="false">Perl</string>
<string name="programming_language_python" translatable="false">Python</string>
<string name="programming_language_ruby" translatable="false">Ruby</string>
<string name="programming_language_shell" translatable="false">Shell</string>
<string name="programming_language_swift" translatable="false">Swift</string>
<string name="programming_language_typescript" translatable="false">TypeScript</string>
<string name="programming_language_go" translatable="false">Go</string>
<string name="programming_language_php" translatable="false">PHP</string>
<string name="server_flag_official">Official Server</string> <string name="server_flag_official">Official Server</string>
<string name="server_flag_verified">Verified Server</string> <string name="server_flag_verified">Verified Server</string>