@@ -6,8 +6,10 @@ package baseline
66import (
77 "fmt"
88 "regexp"
9+ "slices"
910 "strconv"
1011 "strings"
12+ "unicode"
1113
1214 "github.com/ossf/security-baseline/pkg/types"
1315)
@@ -42,27 +44,33 @@ func isWrapped(text, matched string) bool {
4244 return openBrackets > closeBrackets
4345}
4446
45- // Function to add links by wrapping terms with square brackets
47+ // Function to add links by wrapping terms with square brackets.
48+ // `term` should be either a Term in a LexiconEntry, or a Synonyms entry.
4649func addLinks (lexicon []types.LexiconEntry , text , term string ) string {
4750 // Escape any special characters in the term to use in regex
4851 escapedTerm := regexp .QuoteMeta (term )
4952
50- // Create a regular expression to match the term as a whole word
53+ // Create a regular expression to match the term as a whole word,
54+ // and the plural of the word (using a simple "add s" rule).
5155 // The `(?i)` part makes it case-insensitive, and `\b` ensures whole word matching
5256 termRegex := regexp .MustCompile (`(?i)\b` + escapedTerm + `(?:s)?\b` )
5357
58+ termIdx := slices .IndexFunc (lexicon , func (t types.LexiconEntry ) bool {
59+ return containsSynonym (t .Synonyms , t .Term , term )
60+ })
61+ if termIdx == - 1 {
62+ // This should never happen (logic error elsewhere)
63+ panic (fmt .Sprintf ("Attempted to add links for non-lexicon string %q" , term ))
64+ }
65+ canonicalTerm := lexicon [termIdx ].Term
66+
5467 // Replace the term with the same term wrapped in brackets, and avoid rewrapping terms
5568 return termRegex .ReplaceAllStringFunc (text , func (matched string ) string {
5669 if isWrapped (text , matched ) {
5770 return matched // Skip wrapping if already wrapped in brackets
5871 }
5972
60- for i , entry := range lexicon {
61- if entry .Term == term && ! containsSynonym (entry .Synonyms , entry .Term , matched ) {
62- lexicon [i ].Synonyms = append (entry .Synonyms , matched ) //nolint:gocritic
63- }
64- }
65- return fmt .Sprintf ("[%s]" , matched )
73+ return fmt .Sprintf ("[%s][%s]" , matched , canonicalTerm )
6674 })
6775}
6876
@@ -80,9 +88,16 @@ func addLinksTemplateFunction(lexicon []types.LexiconEntry, text string) string
8088}
8189
8290func asLinkTemplateFunction (text string ) string {
83- return "#" + strings .ToLower (
84- strings .ReplaceAll (
85- strings .ReplaceAll (text , " " , "-" ), "." , "" ))
91+ return "#" + strings .Map (func (r rune ) rune {
92+ switch {
93+ case unicode .IsLetter (r ) || unicode .IsNumber (r ):
94+ return unicode .ToLower (r )
95+ case r == '.' :
96+ return - 1 // Existing versions drop ".", rather than mapping to "-"
97+ default :
98+ return '-'
99+ }
100+ }, text )
86101}
87102
88103// loop through maturityLevels
0 commit comments