package web import ( "html/template" "strings" ) // runToken returns the full user-facing proquint when an ID is numeric. // Non-numeric legacy IDs remain usable by the CLI unchanged. func runToken(value any) string { view := commandRunView(value) if view.Pronounce != "" { return view.Pronounce } return view.RunID } func runDisplay(value any) string { view := commandRunView(value) if view.PronounceShort != "" { return view.PronounceShort } return runToken(view) } func commandRunView(value any) runView { switch current := value.(type) { case runView: return current case childPage: return current.runView } return runView{} } // nuQuote renders one Nushell raw-string argument. // Increasing hash delimiters preserves every byte, including apostrophes, // interpolation syntax, newlines, and strings beginning with a flag. func nuQuote(value string) string { if value != "" { safe := true for _, r := range value { if !((r >= 'a' && r <= 'z') || (r >= 'A' && r <= 'Z') || (r >= '0' && r <= '9') || strings.ContainsRune("_+-.,/:=@%", r)) { safe = false break } } if safe { return value } } for hashes := 1; ; hashes++ { delimiter := "'" + strings.Repeat("#", hashes) if !strings.Contains(value, delimiter) { return "r" + strings.Repeat("#", hashes) + "'" + value + delimiter } } } func commandText(parts ...string) string { quoted := make([]string, len(parts)) for i, part := range parts { quoted[i] = nuQuote(part) } return strings.Join(quoted, " ") } // highlightCommand safely styles a preview while leaving each argument intact. func highlightCommand(parts ...string) template.HTML { var b strings.Builder for i, part := range parts { if i > 0 { b.WriteByte(' ') } class := "command-arg" if i == 0 || i == 1 { class = "command-name" } else if strings.HasPrefix(part, "-") { class = "command-flag" } b.WriteString(``) b.WriteString(template.HTMLEscapeString(nuQuote(part))) b.WriteString(``) } return template.HTML(b.String()) }