Skip to content

Commit

Permalink
Add InlineCode option for inline code blocks
Browse files Browse the repository at this point in the history
- Add an `InlineCode` option for inline code blocks
- When `PreventSurroundingPre` option is enabled, do not wrap the code by `Line` and `CodeLine`
- Write and update related tests
  • Loading branch information
CIAvash authored and alecthomas committed Jun 14, 2022
1 parent 530c45d commit d18e8a4
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 34 deletions.
97 changes: 64 additions & 33 deletions formatters/html/html.go
Expand Up @@ -38,6 +38,8 @@ func TabWidth(width int) Option { return func(f *Formatter) { f.tabWidth = width
// PreventSurroundingPre prevents the surrounding pre tags around the generated code.
func PreventSurroundingPre(b bool) Option {
return func(f *Formatter) {
f.preventSurroundingPre = b

if b {
f.preWrapper = nopPreWrapper
} else {
Expand All @@ -46,6 +48,29 @@ func PreventSurroundingPre(b bool) Option {
}
}

// InlineCode creates inline code wrapped in a code tag.
func InlineCode(b bool) Option {
return func(f *Formatter) {
f.inlineCode = b
f.preWrapper = preWrapper{
start: func(code bool, styleAttr string) string {
if code {
return fmt.Sprintf(`<code%s>`, styleAttr)
}

return ``
},
end: func(code bool) string {
if code {
return `</code>`
}

return ``
},
}
}
}

// WithPreWrapper allows control of the surrounding pre tags.
func WithPreWrapper(wrapper PreWrapper) Option {
return func(f *Formatter) {
Expand Down Expand Up @@ -163,20 +188,22 @@ var (

// Formatter that generates HTML.
type Formatter struct {
standalone bool
prefix string
Classes bool // Exported field to detect when classes are being used
allClasses bool
customCSS map[chroma.TokenType]string
preWrapper PreWrapper
tabWidth int
wrapLongLines bool
lineNumbers bool
lineNumbersInTable bool
linkableLineNumbers bool
lineNumbersIDPrefix string
highlightRanges highlightRanges
baseLineNumber int
standalone bool
prefix string
Classes bool // Exported field to detect when classes are being used
allClasses bool
customCSS map[chroma.TokenType]string
preWrapper PreWrapper
inlineCode bool
preventSurroundingPre bool
tabWidth int
wrapLongLines bool
lineNumbers bool
lineNumbersInTable bool
linkableLineNumbers bool
lineNumbersIDPrefix string
highlightRanges highlightRanges
baseLineNumber int
}

type highlightRanges [][2]int
Expand Down Expand Up @@ -257,26 +284,29 @@ func (f *Formatter) writeHTML(w io.Writer, style *chroma.Style, tokens []chroma.
highlightIndex++
}

// Start of Line
fmt.Fprint(w, `<span`)
if highlight {
// Line + LineHighlight
if f.Classes {
fmt.Fprintf(w, ` class="%s %s"`, f.class(chroma.Line), f.class(chroma.LineHighlight))
if !(f.preventSurroundingPre || f.inlineCode) {
// Start of Line
fmt.Fprint(w, `<span`)

if highlight {
// Line + LineHighlight
if f.Classes {
fmt.Fprintf(w, ` class="%s %s"`, f.class(chroma.Line), f.class(chroma.LineHighlight))
} else {
fmt.Fprintf(w, ` style="%s %s"`, css[chroma.Line], css[chroma.LineHighlight])
}
fmt.Fprint(w, `>`)
} else {
fmt.Fprintf(w, ` style="%s %s"`, css[chroma.Line], css[chroma.LineHighlight])
fmt.Fprintf(w, "%s>", f.styleAttr(css, chroma.Line))
}
fmt.Fprint(w, `>`)
} else {
fmt.Fprintf(w, "%s>", f.styleAttr(css, chroma.Line))
}

// Line number
if f.lineNumbers && !wrapInTable {
fmt.Fprintf(w, "<span%s%s>%s</span>", f.styleAttr(css, chroma.LineNumbers), f.lineIDAttribute(line), f.lineTitleWithLinkIfNeeded(lineDigits, line))
}
// Line number
if f.lineNumbers && !wrapInTable {
fmt.Fprintf(w, "<span%s%s>%s</span>", f.styleAttr(css, chroma.LineNumbers), f.lineIDAttribute(line), f.lineTitleWithLinkIfNeeded(lineDigits, line))
}

fmt.Fprintf(w, `<span%s>`, f.styleAttr(css, chroma.CodeLine))
fmt.Fprintf(w, `<span%s>`, f.styleAttr(css, chroma.CodeLine))
}

for _, token := range tokens {
html := html.EscapeString(token.String())
Expand All @@ -287,11 +317,12 @@ func (f *Formatter) writeHTML(w io.Writer, style *chroma.Style, tokens []chroma.
fmt.Fprint(w, html)
}

fmt.Fprint(w, `</span>`) // End of CodeLine
if !(f.preventSurroundingPre || f.inlineCode) {
fmt.Fprint(w, `</span>`) // End of CodeLine

fmt.Fprint(w, `</span>`) // End of Line
fmt.Fprint(w, `</span>`) // End of Line
}
}

fmt.Fprintf(w, f.preWrapper.End(true))

if wrapInTable {
Expand Down
12 changes: 11 additions & 1 deletion formatters/html/html_test.go
Expand Up @@ -296,7 +296,17 @@ func TestWithPreWrapper(t *testing.T) {

t.Run("PreventSurroundingPre", func(t *testing.T) {
s := format(New(PreventSurroundingPre(true), WithClasses(true)))
assert.Equal(t, s, `<span class="line"><span class="cl"><span class="nb">echo</span> FOO</span></span>`)
assert.Equal(t, s, `<span class="nb">echo</span> FOO`)
})

t.Run("InlineCode", func(t *testing.T) {
s := format(New(InlineCode(true), WithClasses(true)))
assert.Equal(t, s, `<code class="chroma"><span class="nb">echo</span> FOO</code>`)
})

t.Run("InlineCode, inline styles", func(t *testing.T) {
s := format(New(InlineCode(true)))
assert.Regexp(t, `<code style=".+?"><span style=".+?">echo</span> FOO</code>`, s)
})

t.Run("Wrapper", func(t *testing.T) {
Expand Down

0 comments on commit d18e8a4

Please sign in to comment.