diff --git a/Makefile b/Makefile index 20873c6..ea4badf 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ BUILD_ENV := CGO_ENABLED=0 APP=wechatmp2markdown -VERSION=v1.1.2 +VERSION=v1.1.3 # linux or mac 环境编译 # make [cmd] diff --git a/README.md b/README.md index d6fddc9..a70eb69 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,19 @@ wechatmp2makrdown_win64.exe https://mp.weixin.qq.com/s/a=1&b=2 D:\wechatmp_bak - markdown和图片文件将保存在 `D:\wechatmp_bak\2022年度总结\` 下 +> 在Windows环境下,文件或路径名不能包含以下任何字符:“(双引号)、*(星号)、<(小于)、>(大于)、?(问号)、\(反斜杠)、/(正斜杠)、|(竖线)、:(冒号)。当标题包含以上字符时,本程序将用相似的Unicode字符进行替换,具体替换规则为: +> ``` +> "<" -> "≺" +> ">" -> "≻" +> ":" -> ":" +> """ -> "“" +> "/" -> "∕" +> "\" -> "∖" +> "|" -> "∣" +> "?" -> "?" +> "*" -> "⁎" +> ``` + ### web server 模式 通过web服务使用 @@ -73,5 +86,8 @@ mingw32-make win-build-win32 编译好的文件在`./build`目录下 +## TODO +- [ ] 支持解析表格元素(table tag) + ## 最后 抓紧时间窗口。努力记录。黑暗中记得光的模样。 \ No newline at end of file diff --git a/format/format.go b/format/format.go index f1a307c..56ad708 100644 --- a/format/format.go +++ b/format/format.go @@ -3,10 +3,10 @@ package format import ( "bytes" "encoding/binary" - "io/ioutil" "log" "os" "path/filepath" + "regexp" "runtime" "strconv" "strings" @@ -30,6 +30,33 @@ func Format(article parse.Article) (string, map[string][]byte) { return result, saveImageBytes } +// windows下, 文件名包含非法字符时, 用相似的Unicode字符进行替换; 长度超过255个字符时,保留前255个字符 +func legalizationFilenameForWindows(name string) string { + // Windows文件名不能包含这些字符 + invalidChars := regexp.MustCompile(`[\\/:*?\"<>|]`) + + // 如果包含非法字符,则替换 + if invalidChars.MatchString(name) { + name = strings.ReplaceAll(name, "<", "≺") + name = strings.ReplaceAll(name, ">", "≻") + name = strings.ReplaceAll(name, ":", ":") + name = strings.ReplaceAll(name, "\"", "“") + name = strings.ReplaceAll(name, "/", "∕") + name = strings.ReplaceAll(name, "\\", "∖") + name = strings.ReplaceAll(name, "|", "∣") + name = strings.ReplaceAll(name, "?", "?") + name = strings.ReplaceAll(name, "*", "⁎") + } + + // 文件名最大长度255字符 + if len(name) > 255 { + // 超出就截断文件名 + name = name[:255] + } + + return name +} + // FormatAndSave fomat article and save to local file func FormatAndSave(article parse.Article, filePath string) error { // basrPath := filepath.Join(filePath, ) @@ -55,6 +82,9 @@ func FormatAndSave(article parse.Article, filePath string) error { fileName = filePath } else { title := strings.TrimSpace(article.Title.Val.(string)) + if isWin { + title = legalizationFilenameForWindows(title) + } // title := "thisistitle" basePath = filepath.Join(filePath, title) fileName = filepath.Join(basePath, title+".md") @@ -89,7 +119,7 @@ func FormatAndSave(article parse.Article, filePath string) error { f.Write(buf.Bytes()) } } - return ioutil.WriteFile(fileName, []byte(result), 0644) + return os.WriteFile(fileName, []byte(result), 0644) } func formatTitle(piece parse.Piece) string {