mirror of
https://github.com/chenhg5/cc-connect.git
synced 2026-10-25 17:36:43 +08:00
StripMarkdown is used to flatten Markdown to plain text for platforms without Markdown support (LINE, WeCom) and for TTS synthesis. It already covered `**bold**` / `*italic*` / `~~strike~~` / `[text](url)` / headings / fenced code, plus the underscore variants `__bold__` and `_italic_`. The two underscore patterns are dangerous: reBoldUnd: `__(.+?)__` reItalicUnd: `_(.+?)_` Both happily match identifier fragments. With these enabled, StripMarkdown silently rewrites: call my_func_name() to start -> call myfuncname() to start use module_name_var here -> use modulenamevar here Python's __init__ method -> Python's init method the __version__ string -> the version string i.e. exactly the things an agent writes whenever it discusses code. The corrupted text then ships out to LINE / WeCom messages and TTS audio, where the underscores are gone and the user can no longer copy-paste or pronounce the identifier correctly. Go's regexp engine has no lookbehind, so the underscore form can't be narrowed to "not adjacent to a word char" with a one-line regex change. The dunder case (`__init__` surrounded by spaces) is also shape-identical to `__bold__` and can't be distinguished structurally. Real-world agent output overwhelmingly uses `**bold**` / `*italic*`, so the underscore forms are mostly a hazard with little upside. Drop them. Inputs containing literal `_italic_` now keep the underscores — a small cosmetic loss compared to losing identifier integrity in TTS or plain-text channels. Add core/markdown_test.go (no test file existed) covering both the preserved asterisk paths and the regression cases above so we don't re-introduce the corruption.
47 lines
1.8 KiB
Go
47 lines
1.8 KiB
Go
package core
|
|
|
|
import "testing"
|
|
|
|
func TestStripMarkdown(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
in string
|
|
want string
|
|
}{
|
|
// Asterisk forms keep working — these are what agents typically emit.
|
|
{"bold asterisk", "this is **bold** text", "this is bold text"},
|
|
{"italic asterisk", "this is *italic* text", "this is italic text"},
|
|
{"bold italic combined", "**bold** and *italic*", "bold and italic"},
|
|
|
|
// Strikethrough, links, headings, code — unchanged behavior.
|
|
{"strikethrough", "~~struck~~", "struck"},
|
|
{"link", "[GitHub](https://github.com)", "GitHub (https://github.com)"},
|
|
{"heading", "# Title\nbody", "Title\nbody"},
|
|
{"inline code", "use `os.path.join`", "use os.path.join"},
|
|
{"fenced code block", "```go\nfmt.Println(\"hi\")\n```", "fmt.Println(\"hi\")"},
|
|
|
|
// Regression: underscore forms must NOT be stripped, since the same
|
|
// patterns appear in legitimate identifiers. Stripping them used to
|
|
// produce e.g. "mysnakecase_var" and "init", corrupting code
|
|
// references in TTS / LINE / WeChat output.
|
|
{"snake_case identifier", "call my_func_name() to start", "call my_func_name() to start"},
|
|
{"two-underscore snake_case", "use module_name_var here", "use module_name_var here"},
|
|
{"python dunder", "Python's __init__ method", "Python's __init__ method"},
|
|
{"version dunder", "the __version__ string", "the __version__ string"},
|
|
{"single underscore identifier", "function_name", "function_name"},
|
|
|
|
// Underscore-form bold/italic is now kept literal (rare in practice).
|
|
{"underscore italic kept literal", "_italic_ text", "_italic_ text"},
|
|
{"underscore bold kept literal", "__bold__ text", "__bold__ text"},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got := StripMarkdown(tt.in)
|
|
if got != tt.want {
|
|
t.Errorf("StripMarkdown(%q) = %q, want %q", tt.in, got, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|