1
0
mirror of https://github.com/alecthomas/chroma.git synced 2025-03-29 21:56:56 +02:00

Add InlineCode option for inline code blocks

- 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
This commit is contained in:
Siavash Askari Nasr 2022-03-10 14:46:41 +03:30 committed by Alec Thomas
parent 530c45d213
commit d18e8a46f2
2 changed files with 75 additions and 34 deletions

View File

@ -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. // PreventSurroundingPre prevents the surrounding pre tags around the generated code.
func PreventSurroundingPre(b bool) Option { func PreventSurroundingPre(b bool) Option {
return func(f *Formatter) { return func(f *Formatter) {
f.preventSurroundingPre = b
if b { if b {
f.preWrapper = nopPreWrapper f.preWrapper = nopPreWrapper
} else { } else {
@ -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. // WithPreWrapper allows control of the surrounding pre tags.
func WithPreWrapper(wrapper PreWrapper) Option { func WithPreWrapper(wrapper PreWrapper) Option {
return func(f *Formatter) { return func(f *Formatter) {
@ -163,20 +188,22 @@ var (
// Formatter that generates HTML. // Formatter that generates HTML.
type Formatter struct { type Formatter struct {
standalone bool standalone bool
prefix string prefix string
Classes bool // Exported field to detect when classes are being used Classes bool // Exported field to detect when classes are being used
allClasses bool allClasses bool
customCSS map[chroma.TokenType]string customCSS map[chroma.TokenType]string
preWrapper PreWrapper preWrapper PreWrapper
tabWidth int inlineCode bool
wrapLongLines bool preventSurroundingPre bool
lineNumbers bool tabWidth int
lineNumbersInTable bool wrapLongLines bool
linkableLineNumbers bool lineNumbers bool
lineNumbersIDPrefix string lineNumbersInTable bool
highlightRanges highlightRanges linkableLineNumbers bool
baseLineNumber int lineNumbersIDPrefix string
highlightRanges highlightRanges
baseLineNumber int
} }
type highlightRanges [][2]int type highlightRanges [][2]int
@ -257,26 +284,29 @@ func (f *Formatter) writeHTML(w io.Writer, style *chroma.Style, tokens []chroma.
highlightIndex++ highlightIndex++
} }
// Start of Line if !(f.preventSurroundingPre || f.inlineCode) {
fmt.Fprint(w, `<span`) // Start of Line
if highlight { fmt.Fprint(w, `<span`)
// Line + LineHighlight
if f.Classes { if highlight {
fmt.Fprintf(w, ` class="%s %s"`, f.class(chroma.Line), f.class(chroma.LineHighlight)) // 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 { } 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 // Line number
if f.lineNumbers && !wrapInTable { 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%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 { for _, token := range tokens {
html := html.EscapeString(token.String()) html := html.EscapeString(token.String())
@ -287,11 +317,12 @@ func (f *Formatter) writeHTML(w io.Writer, style *chroma.Style, tokens []chroma.
fmt.Fprint(w, html) 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)) fmt.Fprintf(w, f.preWrapper.End(true))
if wrapInTable { if wrapInTable {

View File

@ -296,7 +296,17 @@ func TestWithPreWrapper(t *testing.T) {
t.Run("PreventSurroundingPre", func(t *testing.T) { t.Run("PreventSurroundingPre", func(t *testing.T) {
s := format(New(PreventSurroundingPre(true), WithClasses(true))) 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) { t.Run("Wrapper", func(t *testing.T) {