@@ -22,6 +22,7 @@ import androidx.compose.ui.unit.Dp
2222import androidx.compose.ui.unit.dp
2323import androidx.compose.ui.unit.times
2424import cc.unitmesh.devins.ui.compose.icons.AutoDevComposeIcons
25+ import cc.unitmesh.devins.ui.platform.FileChooser
2526import com.mikepenz.markdown.annotator.AnnotatorSettings
2627import com.mikepenz.markdown.annotator.annotatorSettings
2728import com.mikepenz.markdown.annotator.buildMarkdownAnnotatedString
@@ -158,7 +159,10 @@ fun MarkdownTableHeader(
158159 modifier = Modifier .widthIn(tableWidth).height(IntrinsicSize .Max )
159160 ) {
160161 header.children.filter { it.type == CELL }.forEachIndexed { idx, cell ->
161- val weight = if (weights.size == header.children.count { it.type == CELL }) weights[idx] else 1f / (header.children.count { it.type == CELL }).coerceAtLeast(1 )
162+ val weight =
163+ if (weights.size == header.children.count { it.type == CELL }) weights[idx] else 1f / (header.children.count { it.type == CELL }).coerceAtLeast(
164+ 1
165+ )
162166 Column (
163167 modifier = Modifier .padding(tableCellPadding).weight(weight),
164168 ) {
@@ -221,6 +225,19 @@ fun MarkdownTableRow(
221225 val filePath = extractBacktickedPath(raw)
222226 if (filePath != null ) {
223227 Row (verticalAlignment = Alignment .CenterVertically ) {
228+ IconButton (
229+ modifier = Modifier .size(16 .dp),
230+ onClick = {
231+ val root = WorkspaceManager .getCurrentOrEmpty().rootPath
232+ val abs = if (root != null ) root + " /" + filePath else filePath
233+ onOpenFile(abs)
234+ }) {
235+ Icon (
236+ modifier = Modifier .size(16 .dp),
237+ imageVector = AutoDevComposeIcons .Visibility , contentDescription = " View File"
238+ )
239+ }
240+ Spacer (modifier = Modifier .width(4 .dp))
224241 MarkdownTableBasicText (
225242 content = content,
226243 cell = cell,
@@ -229,14 +246,6 @@ fun MarkdownTableRow(
229246 overflow = overflow,
230247 annotatorSettings = annotatorSettings
231248 )
232- Spacer (modifier = Modifier .width(4 .dp))
233- IconButton (onClick = {
234- val root = WorkspaceManager .getCurrentOrEmpty().rootPath
235- val abs = if (root != null ) root + " /" + filePath else filePath
236- onOpenFile(abs)
237- }) {
238- Icon (imageVector = AutoDevComposeIcons .Visibility , contentDescription = " View File" )
239- }
240249 }
241250 } else {
242251 MarkdownTableBasicText (
@@ -277,9 +286,23 @@ fun MarkdownTableBasicText(
277286
278287/* *
279288 * Extract backticked file path from markdown cell content
289+ * Supports paths like:
290+ * - `mpp-core/.../CodeReviewArtifact.kt`
291+ * - `src/main/kotlin/MyFile.kt`
292+ * - `path/to/file-name_v2.kt`
280293 */
281294private fun extractBacktickedPath (raw : String ): String? {
282- val pathRegex = Regex (" `([\\ w\\ -./]+)`" )
295+ // Match backticked content that looks like a file path
296+ // Supports: alphanumeric, dots, slashes, hyphens, underscores, ellipsis (...), brackets, parentheses
297+ val pathRegex = Regex (" `([\\ w\\ -_./@()\\ [\\ ]]+(?:\\ .{3})?[\\ w\\ -_./@()\\ [\\ ]]*)`" )
283298 val match = pathRegex.find(raw)
284- return match?.groupValues?.getOrNull(1 )
299+ val candidate = match?.groupValues?.getOrNull(1 )
300+
301+ // Filter: must contain at least one slash or a file extension
302+ return if (candidate != null && (candidate.contains(' /' ) || candidate.contains(' .' ))) {
303+ // Expand ellipsis if present (e.g., mpp-core/.../File.kt -> mpp-core/src/.../File.kt)
304+ candidate
305+ } else {
306+ null
307+ }
285308}
0 commit comments