diff --git a/README.md b/README.md index fc33a2e6f..fb22a4fa2 100644 --- a/README.md +++ b/README.md @@ -183,7 +183,7 @@ following constructor options: - `ClassPrefix(prefix)` - prefix each generated CSS class. - `TabWidth(width)` - Set the rendered tab width, in characters. - `WithLineNumbers()` - Render line numbers (style with `LineNumbers`). -- `LinkableLineNumbers()` - Make the line numbers linkable. +- `LinkableLineNumbers()` - Make the line numbers linkable and be a link to themselves. - `HighlightLines(ranges)` - Highlight lines in these ranges (style with `LineHighlight`). - `LineNumbersInTable()` - Use a table for formatting line numbers and code, rather than spans. diff --git a/formatters/html/html.go b/formatters/html/html.go index ad48da1a4..a0854afa8 100644 --- a/formatters/html/html.go +++ b/formatters/html/html.go @@ -211,7 +211,7 @@ func (f *Formatter) writeHTML(w io.Writer, style *chroma.Style, tokens []chroma. fmt.Fprintf(w, "", f.styleAttr(css, chroma.LineHighlight)) } - fmt.Fprintf(w, "%*d\n", f.styleAttr(css, chroma.LineNumbersTable), f.lineIDAttribute(line), lineDigits, line) + fmt.Fprintf(w, "%s\n", f.styleAttr(css, chroma.LineNumbersTable), f.lineIDAttribute(line), f.lineTitleWithLinkIfNeeded(lineDigits, line)) if highlight { fmt.Fprintf(w, "") @@ -237,7 +237,7 @@ func (f *Formatter) writeHTML(w io.Writer, style *chroma.Style, tokens []chroma. } if f.lineNumbers && !wrapInTable { - fmt.Fprintf(w, "%*d", f.styleAttr(css, chroma.LineNumbers), f.lineIDAttribute(line), lineDigits, line) + fmt.Fprintf(w, "%s", f.styleAttr(css, chroma.LineNumbers), f.lineIDAttribute(line), f.lineTitleWithLinkIfNeeded(lineDigits, line)) } for _, token := range tokens { @@ -272,7 +272,19 @@ func (f *Formatter) lineIDAttribute(line int) string { if !f.linkableLineNumbers { return "" } - return fmt.Sprintf(" id=\"%s%d\"", f.lineNumbersIDPrefix, line) + return fmt.Sprintf(" id=\"%s\"", f.lineID(line)) +} + +func (f *Formatter) lineTitleWithLinkIfNeeded(lineDigits, line int) string { + title := fmt.Sprintf("%*d", lineDigits, line) + if !f.linkableLineNumbers { + return title + } + return fmt.Sprintf("%s", f.lineID(line), title) +} + +func (f *Formatter) lineID(line int) string { + return fmt.Sprintf("%s%d", f.lineNumbersIDPrefix, line) } func (f *Formatter) shouldHighlight(highlightIndex, line int) (bool, bool) { diff --git a/formatters/html/html_test.go b/formatters/html/html_test.go index b056f19a4..408d0df69 100644 --- a/formatters/html/html_test.go +++ b/formatters/html/html_test.go @@ -108,6 +108,32 @@ func TestTableLineNumberNewlines(t *testing.T) { `) } +func TestLinkeableLineNumbers(t *testing.T) { + f := New(WithClasses(true), WithLineNumbers(true), LinkableLineNumbers(true, "line")) + it, err := lexers.Get("go").Tokenise(nil, "package main\nfunc main()\n{\nprintln(\"hello world\")\n}\n") + assert.NoError(t, err) + + var buf bytes.Buffer + err = f.Format(&buf, styles.Fallback, it) + assert.NoError(t, err) + + assert.Contains(t, buf.String(), `id="line1">1`) + assert.Contains(t, buf.String(), `id="line5">5`) +} + +func TestTableLinkeableLineNumbers(t *testing.T) { + f := New(WithClasses(true), WithLineNumbers(true), LineNumbersInTable(true), LinkableLineNumbers(true, "line")) + it, err := lexers.Get("go").Tokenise(nil, "package main\nfunc main()\n{\nprintln(`hello world`)\n}\n") + assert.NoError(t, err) + + var buf bytes.Buffer + err = f.Format(&buf, styles.Fallback, it) + assert.NoError(t, err) + + assert.Contains(t, buf.String(), `id="line1">1`) + assert.Contains(t, buf.String(), `id="line5">5`) +} + func TestTableLineNumberSpacing(t *testing.T) { testCases := []struct { baseLineNumber int