diff --git a/app/controller/cutil/formatter.go b/app/controller/cutil/formatter.go index 0389185..b795677 100644 --- a/app/controller/cutil/formatter.go +++ b/app/controller/cutil/formatter.go @@ -3,6 +3,7 @@ package cutil import ( "fmt" h "html" + "regexp" "strings" "github.com/alecthomas/chroma" @@ -19,24 +20,32 @@ var ( noLineNums *html.Formatter ) -func FormatJSON(v any) (string, error) { - return FormatLang(util.ToJSON(v), util.KeyJSON) +func FormatJSON(v any, lineNumLinkAndTitle ...string) (string, error) { + return FormatLang(util.ToJSON(v), util.KeyJSON, lineNumLinkAndTitle...) } -func FormatLang(content string, lang string) (string, error) { +func FormatLang(content string, lang string, lineNumLinkAndTitle ...string) (string, error) { l := lexers.Get(lang) - return FormatString(content, l) + return FormatString(content, l, lineNumLinkAndTitle...) } -func FormatFilename(content string, filename string) (string, error) { +func FormatLangIgnoreErrors(content string, lang string, lineNumLinkAndTitle ...string) string { + ret, err := FormatLang(content, lang, lineNumLinkAndTitle...) + if err != nil { + return fmt.Sprintf("encoding error: %s\n%s", err.Error(), content) + } + return ret +} + +func FormatFilename(content string, filename string, lineNumLinkAndTitle ...string) (string, error) { l := lexers.Match(filename) if l == nil { l = lexers.Fallback } - return FormatString(content, l) + return FormatString(content, l, lineNumLinkAndTitle...) } -func FormatString(content string, l chroma.Lexer) (string, error) { +func FormatString(content string, l chroma.Lexer, lineNumLinkAndTitle ...string) (string, error) { if l == nil { return "", errors.New("no lexer available for this content") } @@ -71,10 +80,37 @@ func FormatString(content string, l chroma.Lexer) (string, error) { if l.Config().Name == "SQL" { ret = strings.ReplaceAll(ret, `$`, `$`) } + if len(lineNumLinkAndTitle) > 0 { + title := "" + if len(lineNumLinkAndTitle) > 1 { + title = lineNumLinkAndTitle[1] + } + ret = injectLinks(ret, lineNumLinkAndTitle[0], title) + } ret = strings.Replace(ret, `
1
`, "", 1) return ret, nil } +var injectLinksRegex = regexp.MustCompile(`(.*?)`) + +func injectLinks(ret string, url string, title string) string { + return injectLinksRegex.ReplaceAllStringFunc(ret, func(match string) string { + content := injectLinksRegex.FindStringSubmatch(match)[1] + var num int + for _, x := range strings.TrimSpace(content) { + if x >= '0' && x <= '9' { + num = num*10 + int(x-'0') + } else { + break + } + } + u := strings.ReplaceAll(url, "{}", fmt.Sprint(num)) + t := strings.ReplaceAll(title, "{}", fmt.Sprint(num)) + anchor := fmt.Sprintf(``, t, u) + return strings.Replace(match, content, anchor+content+"", 1) + }) +} + func FormatMarkdown(s string) (string, error) { match, end := "
" idx := strings.Index(s, match) diff --git a/views/vfile/Detail.html b/views/vfile/Detail.html index 16f3060..a3aae4e 100644 --- a/views/vfile/Detail.html +++ b/views/vfile/Detail.html @@ -9,7 +9,7 @@ "github.com/kyleu/npn/app/util" ) %} -{% func Detail(path []string, b []byte, urlPrefix string, additionalLinks map[string]string, as *app.State, ps *cutil.PageState) %} +{% func Detail(path []string, b []byte, urlPrefix string, additionalLinks map[string]string, as *app.State, ps *cutil.PageState, lineNumLinkAndTitle ...string) %} {%- if additionalLinks != nil && len(additionalLinks) > 0 -%}
{%- for k, v := range additionalLinks -%} @@ -25,7 +25,7 @@

{%- if len(b) > (1024 * 128) -%} File is {%d len(b) %} bytes, which is too large for the file viewer {%- elseif utf8.Valid(b) -%} - {%- code out, _ := cutil.FormatFilename(string(b), path[len(path)-1]) -%} + {%- code out, _ := cutil.FormatFilename(string(b), path[len(path)-1], lineNumLinkAndTitle...) -%} {%s= out %} {%- else -%} diff --git a/views/vfile/Detail.html.go b/views/vfile/Detail.html.go index a9268ca..ed7f17b 100644 --- a/views/vfile/Detail.html.go +++ b/views/vfile/Detail.html.go @@ -30,7 +30,7 @@ var ( ) //line views/vfile/Detail.html:12 -func StreamDetail(qw422016 *qt422016.Writer, path []string, b []byte, urlPrefix string, additionalLinks map[string]string, as *app.State, ps *cutil.PageState) { +func StreamDetail(qw422016 *qt422016.Writer, path []string, b []byte, urlPrefix string, additionalLinks map[string]string, as *app.State, ps *cutil.PageState, lineNumLinkAndTitle ...string) { //line views/vfile/Detail.html:12 qw422016.N().S(` `) @@ -101,7 +101,7 @@ func StreamDetail(qw422016 *qt422016.Writer, path []string, b []byte, urlPrefix //line views/vfile/Detail.html:27 } else if utf8.Valid(b) { //line views/vfile/Detail.html:28 - out, _ := cutil.FormatFilename(string(b), path[len(path)-1]) + out, _ := cutil.FormatFilename(string(b), path[len(path)-1], lineNumLinkAndTitle...) //line views/vfile/Detail.html:28 qw422016.N().S(` `) @@ -193,22 +193,22 @@ func StreamDetail(qw422016 *qt422016.Writer, path []string, b []byte, urlPrefix } //line views/vfile/Detail.html:62 -func WriteDetail(qq422016 qtio422016.Writer, path []string, b []byte, urlPrefix string, additionalLinks map[string]string, as *app.State, ps *cutil.PageState) { +func WriteDetail(qq422016 qtio422016.Writer, path []string, b []byte, urlPrefix string, additionalLinks map[string]string, as *app.State, ps *cutil.PageState, lineNumLinkAndTitle ...string) { //line views/vfile/Detail.html:62 qw422016 := qt422016.AcquireWriter(qq422016) //line views/vfile/Detail.html:62 - StreamDetail(qw422016, path, b, urlPrefix, additionalLinks, as, ps) + StreamDetail(qw422016, path, b, urlPrefix, additionalLinks, as, ps, lineNumLinkAndTitle...) //line views/vfile/Detail.html:62 qt422016.ReleaseWriter(qw422016) //line views/vfile/Detail.html:62 } //line views/vfile/Detail.html:62 -func Detail(path []string, b []byte, urlPrefix string, additionalLinks map[string]string, as *app.State, ps *cutil.PageState) string { +func Detail(path []string, b []byte, urlPrefix string, additionalLinks map[string]string, as *app.State, ps *cutil.PageState, lineNumLinkAndTitle ...string) string { //line views/vfile/Detail.html:62 qb422016 := qt422016.AcquireByteBuffer() //line views/vfile/Detail.html:62 - WriteDetail(qb422016, path, b, urlPrefix, additionalLinks, as, ps) + WriteDetail(qb422016, path, b, urlPrefix, additionalLinks, as, ps, lineNumLinkAndTitle...) //line views/vfile/Detail.html:62 qs422016 := string(qb422016.B) //line views/vfile/Detail.html:62