writekit/internal/markdown/themes.go
2026-01-09 00:16:46 +02:00

152 lines
4.5 KiB
Go

package markdown
import (
"strings"
"github.com/alecthomas/chroma/v2"
"github.com/alecthomas/chroma/v2/styles"
)
var chromaToHljs = map[chroma.TokenType]string{
chroma.Keyword: "hljs-keyword",
chroma.KeywordConstant: "hljs-keyword",
chroma.KeywordDeclaration: "hljs-keyword",
chroma.KeywordNamespace: "hljs-keyword",
chroma.KeywordPseudo: "hljs-keyword",
chroma.KeywordReserved: "hljs-keyword",
chroma.KeywordType: "hljs-type",
chroma.Name: "hljs-variable",
chroma.NameBuiltin: "hljs-built_in",
chroma.NameBuiltinPseudo: "hljs-built_in",
chroma.NameClass: "hljs-title class_",
chroma.NameConstant: "hljs-variable constant_",
chroma.NameDecorator: "hljs-meta",
chroma.NameEntity: "hljs-name",
chroma.NameException: "hljs-title class_",
chroma.NameFunction: "hljs-title function_",
chroma.NameFunctionMagic: "hljs-title function_",
chroma.NameLabel: "hljs-symbol",
chroma.NameNamespace: "hljs-title class_",
chroma.NameOther: "hljs-variable",
chroma.NameProperty: "hljs-property",
chroma.NameTag: "hljs-tag",
chroma.NameVariable: "hljs-variable",
chroma.NameVariableClass: "hljs-variable",
chroma.NameVariableGlobal: "hljs-variable",
chroma.NameVariableInstance: "hljs-variable",
chroma.NameVariableMagic: "hljs-variable",
chroma.NameAttribute: "hljs-attr",
chroma.Literal: "hljs-literal",
chroma.LiteralDate: "hljs-number",
chroma.String: "hljs-string",
chroma.StringAffix: "hljs-string",
chroma.StringBacktick: "hljs-string",
chroma.StringChar: "hljs-string",
chroma.StringDelimiter: "hljs-string",
chroma.StringDoc: "hljs-string",
chroma.StringDouble: "hljs-string",
chroma.StringEscape: "hljs-char escape_",
chroma.StringHeredoc: "hljs-string",
chroma.StringInterpol: "hljs-subst",
chroma.StringOther: "hljs-string",
chroma.StringRegex: "hljs-regexp",
chroma.StringSingle: "hljs-string",
chroma.StringSymbol: "hljs-symbol",
chroma.Number: "hljs-number",
chroma.NumberBin: "hljs-number",
chroma.NumberFloat: "hljs-number",
chroma.NumberHex: "hljs-number",
chroma.NumberInteger: "hljs-number",
chroma.NumberIntegerLong: "hljs-number",
chroma.NumberOct: "hljs-number",
chroma.Operator: "hljs-operator",
chroma.OperatorWord: "hljs-keyword",
chroma.Punctuation: "hljs-punctuation",
chroma.Comment: "hljs-comment",
chroma.CommentHashbang: "hljs-meta",
chroma.CommentMultiline: "hljs-comment",
chroma.CommentPreproc: "hljs-meta",
chroma.CommentPreprocFile: "hljs-meta",
chroma.CommentSingle: "hljs-comment",
chroma.CommentSpecial: "hljs-doctag",
chroma.Generic: "hljs-code",
chroma.GenericDeleted: "hljs-deletion",
chroma.GenericEmph: "hljs-emphasis",
chroma.GenericError: "hljs-strong",
chroma.GenericHeading: "hljs-section",
chroma.GenericInserted: "hljs-addition",
chroma.GenericOutput: "hljs-code",
chroma.GenericPrompt: "hljs-meta prompt_",
chroma.GenericStrong: "hljs-strong",
chroma.GenericSubheading: "hljs-section",
chroma.GenericTraceback: "hljs-code",
chroma.GenericUnderline: "hljs-code",
chroma.Text: "",
chroma.TextWhitespace: "",
}
func GenerateHljsCSS(themeName string) (string, error) {
style := styles.Get(themeName)
if style == nil {
style = styles.Get("github")
}
var css strings.Builder
css.WriteString("/* Auto-generated from Chroma theme: " + themeName + " */\n")
bg := style.Get(chroma.Background)
if bg.Background.IsSet() {
css.WriteString(".prose pre { background: " + bg.Background.String() + "; }\n")
}
if bg.Colour.IsSet() {
css.WriteString(".prose pre code { color: " + bg.Colour.String() + "; }\n")
}
seen := make(map[string]bool)
for chromaToken, hljsClass := range chromaToHljs {
if hljsClass == "" {
continue
}
entry := style.Get(chromaToken)
if !entry.Colour.IsSet() && entry.Bold != chroma.Yes && entry.Italic != chroma.Yes {
continue
}
if seen[hljsClass] {
continue
}
seen[hljsClass] = true
selector := "." + strings.ReplaceAll(hljsClass, " ", ".")
css.WriteString(selector + " {")
if entry.Colour.IsSet() {
css.WriteString(" color: " + entry.Colour.String() + ";")
}
if entry.Bold == chroma.Yes {
css.WriteString(" font-weight: bold;")
}
if entry.Italic == chroma.Yes {
css.WriteString(" font-style: italic;")
}
css.WriteString(" }\n")
}
return css.String(), nil
}
func ListThemes() []string {
return styles.Names()
}