@@ -14,8 +14,11 @@ import (
1414 "github.com/yuin/goldmark/text"
1515)
1616
17- // sentenceBoundaryRegex matches sentence boundaries (. ! ?) followed by space or end of string
18- var sentenceBoundaryRegex = regexp .MustCompile (`([.!?])(\s+)` )
17+ // Common abbreviations that should not be treated as sentence boundaries
18+ var commonAbbreviations = []string {"e.g." , "i.e." , "etc." , "vs." , "cf." , "ex." , "viz." , "approx." , "ca." }
19+
20+ // sentenceBoundaryRegex matches sentence boundaries (. ! ?) followed by space and uppercase letter
21+ var sentenceBoundaryRegex = regexp .MustCompile (`([.!?])(\s+)([A-Z])` )
1922
2023// formatMarkdown formats markdown content with one sentence per line
2124func formatMarkdown (input []byte ) ([]byte , error ) {
@@ -294,16 +297,29 @@ func collectInlineText(node ast.Node, source []byte, buf *bytes.Buffer) error {
294297
295298// splitIntoSentences splits text into sentences
296299func splitIntoSentences (text string ) []string {
300+ // Protect common abbreviations by replacing them temporarily
301+ protected := text
302+ replacements := make (map [string ]string )
303+ for i , abbr := range commonAbbreviations {
304+ placeholder := fmt .Sprintf ("\x00 ABBR%d\x00 " , i )
305+ replacements [placeholder ] = abbr
306+ protected = strings .ReplaceAll (protected , abbr , placeholder )
307+ }
308+
297309 // Replace sentence boundaries with a special marker
298- text = sentenceBoundaryRegex .ReplaceAllString (text , "$1\n \n " )
310+ protected = sentenceBoundaryRegex .ReplaceAllString (protected , "$1\n \n $3 " )
299311
300312 // Split by the marker
301- parts := strings .Split (text , "\n \n " )
313+ parts := strings .Split (protected , "\n \n " )
302314
303315 var sentences []string
304316 for _ , part := range parts {
305317 part = strings .TrimSpace (part )
306318 if part != "" {
319+ // Restore abbreviations
320+ for placeholder , abbr := range replacements {
321+ part = strings .ReplaceAll (part , placeholder , abbr )
322+ }
307323 sentences = append (sentences , part )
308324 }
309325 }
@@ -312,39 +328,58 @@ func splitIntoSentences(text string) []string {
312328}
313329
314330func main () {
331+ checkFlag := flag .Bool ("check" , false , "check if files are formatted without modifying them" )
315332 flag .Parse ()
316333
317334 args := flag .Args ()
335+
336+ // If no arguments, read from stdin and write to stdout
318337 if len (args ) == 0 {
319- fmt .Fprintln (os .Stderr , "Usage: markdown-format <file>" )
320- fmt .Fprintln (os .Stderr , " or pipe input via stdin" )
321- os .Exit (1 )
322- }
323-
324- var input []byte
325- var err error
326-
327- if args [0 ] == "-" {
328- // Read from stdin
329- input , err = io .ReadAll (os .Stdin )
338+ input , err := io .ReadAll (os .Stdin )
330339 if err != nil {
331340 fmt .Fprintf (os .Stderr , "Error reading stdin: %v\n " , err )
332341 os .Exit (1 )
333342 }
334- } else {
335- // Read from file
336- input , err = os .ReadFile (args [0 ])
343+ output , err := formatMarkdown (input )
337344 if err != nil {
338- fmt .Fprintf (os .Stderr , "Error reading file : %v\n " , err )
345+ fmt .Fprintf (os .Stderr , "Error formatting markdown : %v\n " , err )
339346 os .Exit (1 )
340347 }
348+ fmt .Print (string (output ))
349+ return
341350 }
342351
343- output , err := formatMarkdown (input )
344- if err != nil {
345- fmt .Fprintf (os .Stderr , "Error formatting markdown: %v\n " , err )
352+ // Handle file(s) - in-place by default
353+ hasErrors := false
354+ for _ , filename := range args {
355+ input , err := os .ReadFile (filename )
356+ if err != nil {
357+ fmt .Fprintf (os .Stderr , "Error reading file %s: %v\n " , filename , err )
358+ os .Exit (1 )
359+ }
360+ output , err := formatMarkdown (input )
361+ if err != nil {
362+ fmt .Fprintf (os .Stderr , "Error formatting %s: %v\n " , filename , err )
363+ os .Exit (1 )
364+ }
365+
366+ if * checkFlag {
367+ // Check mode: compare without modifying
368+ if ! bytes .Equal (input , output ) {
369+ fmt .Fprintf (os .Stderr , "%s: not formatted\n " , filename )
370+ hasErrors = true
371+ }
372+ } else {
373+ // Default: write in-place
374+ err = os .WriteFile (filename , output , 0644 )
375+ if err != nil {
376+ fmt .Fprintf (os .Stderr , "Error writing file %s: %v\n " , filename , err )
377+ os .Exit (1 )
378+ }
379+ }
380+ }
381+
382+ if hasErrors {
346383 os .Exit (1 )
347384 }
348-
349- fmt .Print (string (output ))
350385}
0 commit comments