diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..ca99310
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,25 @@
+# Binaries for programs and plugins
+.git
+.idea
+.vscode
+.hermit
+*.exe
+*.dll
+*.so
+*.dylib
+/cmd/chroma/chroma
+
+# Test binary, build with `go test -c`
+*.test
+
+# Output of the go coverage tool, specifically when used with LiteIDE
+*.out
+
+# Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736
+.glide/
+
+_models/
+
+_examples/
+*.min.*
+build/
\ No newline at end of file
diff --git a/base16/base16.go b/base16/base16.go
new file mode 100644
index 0000000..98f9336
--- /dev/null
+++ b/base16/base16.go
@@ -0,0 +1,138 @@
+package base16
+
+import (
+	"io"
+
+	"gopkg.in/yaml.v3"
+	"toastielab.dev/toastie-stuff/chroma/v2"
+)
+
+type Base16 struct {
+	// Scheme is the name of the scheme.
+	Scheme string `yaml:"scheme"`
+	// Author is the name of the author.
+	Author string `yaml:"author"`
+	// Theme is either "light" or "dark".
+	Theme string `yaml:"theme"`
+	// Base00 Default Background
+	Base00 string `yaml:"base00"`
+	// Base01 Lighter Background (Used for status bars, line number and folding marks)
+	Base01 string `yaml:"base01"`
+	// Base02 Selection Background
+	Base02 string `yaml:"base02"`
+	// Base03 Comments, Invisibles, Line Highlighting
+	Base03 string `yaml:"base03"`
+	// Base04 Dark Foreground (Used for status bars)
+	Base04 string `yaml:"base04"`
+	// Base05 Default Foreground, Caret, Delimiters, Operators
+	Base05 string `yaml:"base05"`
+	// Base06 Light Foreground (Not often used)
+	Base06 string `yaml:"base06"`
+	// Base07 Light Background (Not often used)
+	Base07 string `yaml:"base07"`
+	// Base08 Variables, XML Tags, Markup Link Text, Markup Lists, Diff Deleted
+	Base08 string `yaml:"base08"`
+	// Base09 Integers, Boolean, Constants, XML Attributes, Markup Link Url
+	Base09 string `yaml:"base09"`
+	// Base0A Classes, Markup Bold, Search Text Background
+	Base0A string `yaml:"base0A"`
+	// Base0B Strings, Inherited Class, Markup Code, Diff Inserted
+	Base0B string `yaml:"base0B"`
+	// Base0C Support, Regular Expressions, Escape Characters, Markup Quotes
+	Base0C string `yaml:"base0C"`
+	// Base0D Functions, Methods, Attribute IDs, Headings
+	Base0D string `yaml:"base0D"`
+	// Base0E Keywords, Storage, Selector, Markup Italic, Diff Changed
+	Base0E string `yaml:"base0E"`
+	// Base0F Deprecated, Opening/Closing Embedded Language Tags, e.g. `<?php ?>`
+	Base0F string `yaml:"base0F"`
+}
+
+func (b *Base16) toStyle() (*chroma.Style, error) {
+	entries := chroma.StyleEntries{
+		chroma.Other:                    "#" + b.Base05,
+		chroma.Error:                    "#" + b.Base08,
+		chroma.Background:               "bg:" + "#" + b.Base00,
+		chroma.Keyword:                  "#" + b.Base0E,
+		chroma.KeywordConstant:          "#" + b.Base0E,
+		chroma.KeywordDeclaration:       "#" + b.Base08,
+		chroma.KeywordNamespace:         "#" + b.Base0E,
+		chroma.KeywordPseudo:            "#" + b.Base0E,
+		chroma.KeywordReserved:          "#" + b.Base0E,
+		chroma.KeywordType:              "#" + b.Base0C,
+		chroma.Name:                     "#" + b.Base05,
+		chroma.NameAttribute:            "#" + b.Base0D,
+		chroma.NameBuiltin:              "#" + b.Base08,
+		chroma.NameBuiltinPseudo:        "#" + b.Base05,
+		chroma.NameClass:                "#" + b.Base0A,
+		chroma.NameConstant:             "#" + b.Base09,
+		chroma.NameDecorator:            "#" + b.Base09,
+		chroma.NameEntity:               "#" + b.Base05,
+		chroma.NameException:            "#" + b.Base05,
+		chroma.NameFunction:             "#" + b.Base0D,
+		chroma.NameLabel:                "#" + b.Base08,
+		chroma.NameNamespace:            "#" + b.Base05,
+		chroma.NameOther:                "#" + b.Base05,
+		chroma.NameTag:                  "#" + b.Base0E,
+		chroma.NameVariable:             "#" + b.Base08,
+		chroma.NameVariableClass:        "#" + b.Base08,
+		chroma.NameVariableGlobal:       "#" + b.Base08,
+		chroma.NameVariableInstance:     "#" + b.Base08,
+		chroma.Literal:                  "#" + b.Base05,
+		chroma.LiteralDate:              "#" + b.Base05,
+		chroma.LiteralString:            "#" + b.Base0B,
+		chroma.LiteralStringBacktick:    "#" + b.Base0B,
+		chroma.LiteralStringChar:        "#" + b.Base0B,
+		chroma.LiteralStringDoc:         "#" + b.Base0B,
+		chroma.LiteralStringDouble:      "#" + b.Base0B,
+		chroma.LiteralStringEscape:      "#" + b.Base0B,
+		chroma.LiteralStringHeredoc:     "#" + b.Base0B,
+		chroma.LiteralStringInterpol:    "#" + b.Base0B,
+		chroma.LiteralStringOther:       "#" + b.Base0B,
+		chroma.LiteralStringRegex:       "#" + b.Base0B,
+		chroma.LiteralStringSingle:      "#" + b.Base0B,
+		chroma.LiteralStringSymbol:      "#" + b.Base0B,
+		chroma.LiteralNumber:            "#" + b.Base09,
+		chroma.LiteralNumberBin:         "#" + b.Base09,
+		chroma.LiteralNumberFloat:       "#" + b.Base09,
+		chroma.LiteralNumberHex:         "#" + b.Base09,
+		chroma.LiteralNumberInteger:     "#" + b.Base09,
+		chroma.LiteralNumberIntegerLong: "#" + b.Base09,
+		chroma.LiteralNumberOct:         "#" + b.Base09,
+		chroma.Operator:                 "#" + b.Base0E,
+		chroma.OperatorWord:             "#" + b.Base0E,
+		chroma.Punctuation:              "#" + b.Base05,
+		chroma.Comment:                  "#" + b.Base03,
+		chroma.CommentHashbang:          "#" + b.Base03,
+		chroma.CommentMultiline:         "#" + b.Base03,
+		chroma.CommentSingle:            "#" + b.Base03,
+		chroma.CommentSpecial:           "#" + b.Base03,
+		chroma.CommentPreproc:           "#" + b.Base03,
+		chroma.Generic:                  "#" + b.Base05,
+		chroma.GenericDeleted:           "#" + b.Base08,
+		chroma.GenericEmph:              "underline #" + b.Base05,
+		chroma.GenericError:             "#" + b.Base08,
+		chroma.GenericHeading:           "bold #" + b.Base05,
+		chroma.GenericInserted:          "bold #" + b.Base05,
+		chroma.GenericOutput:            "#" + b.Base02,
+		chroma.GenericPrompt:            "#" + b.Base05,
+		chroma.GenericStrong:            "italic #" + b.Base05,
+		chroma.GenericSubheading:        "bold #" + b.Base05,
+		chroma.GenericTraceback:         "#" + b.Base05,
+		chroma.GenericUnderline:         "underline",
+		chroma.Text:                     "#" + b.Base05,
+		chroma.TextWhitespace:           "#" + b.Base05,
+	}
+
+	return chroma.NewStyle(b.Scheme, b.Theme, entries)
+}
+
+func NewStyle(r io.Reader) (*chroma.Style, error) {
+	dec := yaml.NewDecoder(r)
+	b16 := &Base16{}
+	if err := dec.Decode(b16); err != nil {
+		return nil, err
+	}
+
+	return b16.toStyle()
+}
diff --git a/coalesce.go b/coalesce.go
new file mode 100644
index 0000000..f504895
--- /dev/null
+++ b/coalesce.go
@@ -0,0 +1,35 @@
+package chroma
+
+// Coalesce is a Lexer interceptor that collapses runs of common types into a single token.
+func Coalesce(lexer Lexer) Lexer { return &coalescer{lexer} }
+
+type coalescer struct{ Lexer }
+
+func (d *coalescer) Tokenise(options *TokeniseOptions, text string) (Iterator, error) {
+	var prev Token
+	it, err := d.Lexer.Tokenise(options, text)
+	if err != nil {
+		return nil, err
+	}
+	return func() Token {
+		for token := it(); token != (EOF); token = it() {
+			if len(token.Value) == 0 {
+				continue
+			}
+			if prev == EOF {
+				prev = token
+			} else {
+				if prev.Type == token.Type && len(prev.Value) < 8192 {
+					prev.Value += token.Value
+				} else {
+					out := prev
+					prev = token
+					return out
+				}
+			}
+		}
+		out := prev
+		prev = EOF
+		return out
+	}, nil
+}
diff --git a/coalesce_test.go b/coalesce_test.go
new file mode 100644
index 0000000..fc39cb8
--- /dev/null
+++ b/coalesce_test.go
@@ -0,0 +1,19 @@
+package chroma
+
+import (
+	"testing"
+
+	"github.com/alecthomas/assert/v2"
+)
+
+func TestCoalesce(t *testing.T) {
+	lexer := Coalesce(mustNewLexer(t, nil, Rules{ // nolint: forbidigo
+		"root": []Rule{
+			{`[!@#$%^&*()]`, Punctuation, nil},
+		},
+	}))
+	actual, err := Tokenise(lexer, nil, "!@#$")
+	assert.NoError(t, err)
+	expected := []Token{{Punctuation, "!@#$"}}
+	assert.Equal(t, expected, actual)
+}
diff --git a/colour.go b/colour.go
new file mode 100644
index 0000000..b7fd6e0
--- /dev/null
+++ b/colour.go
@@ -0,0 +1,192 @@
+package chroma
+
+import (
+	"fmt"
+	"math"
+	"strconv"
+	"strings"
+)
+
+// ANSI2RGB maps ANSI colour names, as supported by Chroma, to hex RGB values.
+var ANSI2RGB = map[string]string{
+	"#ansiblack":     "000000",
+	"#ansidarkred":   "7f0000",
+	"#ansidarkgreen": "007f00",
+	"#ansibrown":     "7f7fe0",
+	"#ansidarkblue":  "00007f",
+	"#ansipurple":    "7f007f",
+	"#ansiteal":      "007f7f",
+	"#ansilightgray": "e5e5e5",
+	// Normal
+	"#ansidarkgray":  "555555",
+	"#ansired":       "ff0000",
+	"#ansigreen":     "00ff00",
+	"#ansiyellow":    "ffff00",
+	"#ansiblue":      "0000ff",
+	"#ansifuchsia":   "ff00ff",
+	"#ansiturquoise": "00ffff",
+	"#ansiwhite":     "ffffff",
+
+	// Aliases without the "ansi" prefix, because...why?
+	"#black":     "000000",
+	"#darkred":   "7f0000",
+	"#darkgreen": "007f00",
+	"#brown":     "7f7fe0",
+	"#darkblue":  "00007f",
+	"#purple":    "7f007f",
+	"#teal":      "007f7f",
+	"#lightgray": "e5e5e5",
+	// Normal
+	"#darkgray":  "555555",
+	"#red":       "ff0000",
+	"#green":     "00ff00",
+	"#yellow":    "ffff00",
+	"#blue":      "0000ff",
+	"#fuchsia":   "ff00ff",
+	"#turquoise": "00ffff",
+	"#white":     "ffffff",
+}
+
+// Colour represents an RGB colour.
+type Colour int32
+
+// NewColour creates a Colour directly from RGB values.
+func NewColour(r, g, b uint8) Colour {
+	return ParseColour(fmt.Sprintf("%02x%02x%02x", r, g, b))
+}
+
+// Distance between this colour and another.
+//
+// This uses the approach described here (https://www.compuphase.com/cmetric.htm).
+// This is not as accurate as LAB, et. al. but is *vastly* simpler and sufficient for our needs.
+func (c Colour) Distance(e2 Colour) float64 {
+	ar, ag, ab := int64(c.Red()), int64(c.Green()), int64(c.Blue())
+	br, bg, bb := int64(e2.Red()), int64(e2.Green()), int64(e2.Blue())
+	rmean := (ar + br) / 2
+	r := ar - br
+	g := ag - bg
+	b := ab - bb
+	return math.Sqrt(float64((((512 + rmean) * r * r) >> 8) + 4*g*g + (((767 - rmean) * b * b) >> 8)))
+}
+
+// Brighten returns a copy of this colour with its brightness adjusted.
+//
+// If factor is negative, the colour is darkened.
+//
+// Uses approach described here (http://www.pvladov.com/2012/09/make-color-lighter-or-darker.html).
+func (c Colour) Brighten(factor float64) Colour {
+	r := float64(c.Red())
+	g := float64(c.Green())
+	b := float64(c.Blue())
+
+	if factor < 0 {
+		factor++
+		r *= factor
+		g *= factor
+		b *= factor
+	} else {
+		r = (255-r)*factor + r
+		g = (255-g)*factor + g
+		b = (255-b)*factor + b
+	}
+	return NewColour(uint8(r), uint8(g), uint8(b))
+}
+
+// BrightenOrDarken brightens a colour if it is < 0.5 brightness or darkens if > 0.5 brightness.
+func (c Colour) BrightenOrDarken(factor float64) Colour {
+	if c.Brightness() < 0.5 {
+		return c.Brighten(factor)
+	}
+	return c.Brighten(-factor)
+}
+
+// ClampBrightness returns a copy of this colour with its brightness adjusted such that
+// it falls within the range [min, max] (or very close to it due to rounding errors).
+// The supplied values use the same [0.0, 1.0] range as Brightness.
+func (c Colour) ClampBrightness(min, max float64) Colour {
+	if !c.IsSet() {
+		return c
+	}
+
+	min = math.Max(min, 0)
+	max = math.Min(max, 1)
+	current := c.Brightness()
+	target := math.Min(math.Max(current, min), max)
+	if current == target {
+		return c
+	}
+
+	r := float64(c.Red())
+	g := float64(c.Green())
+	b := float64(c.Blue())
+	rgb := r + g + b
+	if target > current {
+		// Solve for x: target == ((255-r)*x + r + (255-g)*x + g + (255-b)*x + b) / 255 / 3
+		return c.Brighten((target*255*3 - rgb) / (255*3 - rgb))
+	}
+	// Solve for x: target == (r*(x+1) + g*(x+1) + b*(x+1)) / 255 / 3
+	return c.Brighten((target*255*3)/rgb - 1)
+}
+
+// Brightness of the colour (roughly) in the range 0.0 to 1.0.
+func (c Colour) Brightness() float64 {
+	return (float64(c.Red()) + float64(c.Green()) + float64(c.Blue())) / 255.0 / 3.0
+}
+
+// ParseColour in the forms #rgb, #rrggbb, #ansi<colour>, or #<colour>.
+// Will return an "unset" colour if invalid.
+func ParseColour(colour string) Colour {
+	colour = normaliseColour(colour)
+	n, err := strconv.ParseUint(colour, 16, 32)
+	if err != nil {
+		return 0
+	}
+	return Colour(n + 1)
+}
+
+// MustParseColour is like ParseColour except it panics if the colour is invalid.
+//
+// Will panic if colour is in an invalid format.
+func MustParseColour(colour string) Colour {
+	parsed := ParseColour(colour)
+	if !parsed.IsSet() {
+		panic(fmt.Errorf("invalid colour %q", colour))
+	}
+	return parsed
+}
+
+// IsSet returns true if the colour is set.
+func (c Colour) IsSet() bool { return c != 0 }
+
+func (c Colour) String() string   { return fmt.Sprintf("#%06x", int(c-1)) }
+func (c Colour) GoString() string { return fmt.Sprintf("Colour(0x%06x)", int(c-1)) }
+
+// Red component of colour.
+func (c Colour) Red() uint8 { return uint8(((c - 1) >> 16) & 0xff) }
+
+// Green component of colour.
+func (c Colour) Green() uint8 { return uint8(((c - 1) >> 8) & 0xff) }
+
+// Blue component of colour.
+func (c Colour) Blue() uint8 { return uint8((c - 1) & 0xff) }
+
+// Colours is an orderable set of colours.
+type Colours []Colour
+
+func (c Colours) Len() int           { return len(c) }
+func (c Colours) Swap(i, j int)      { c[i], c[j] = c[j], c[i] }
+func (c Colours) Less(i, j int) bool { return c[i] < c[j] }
+
+// Convert colours to #rrggbb.
+func normaliseColour(colour string) string {
+	if ansi, ok := ANSI2RGB[colour]; ok {
+		return ansi
+	}
+	if strings.HasPrefix(colour, "#") {
+		colour = colour[1:]
+		if len(colour) == 3 {
+			return colour[0:1] + colour[0:1] + colour[1:2] + colour[1:2] + colour[2:3] + colour[2:3]
+		}
+	}
+	return colour
+}
diff --git a/colour_test.go b/colour_test.go
new file mode 100644
index 0000000..8d75f64
--- /dev/null
+++ b/colour_test.go
@@ -0,0 +1,91 @@
+package chroma
+
+import (
+	"math"
+	"testing"
+
+	"github.com/alecthomas/assert/v2"
+)
+
+func TestColourRGB(t *testing.T) {
+	colour := ParseColour("#8913af")
+	assert.Equal(t, uint8(0x89), colour.Red())
+	assert.Equal(t, uint8(0x13), colour.Green())
+	assert.Equal(t, uint8(0xaf), colour.Blue())
+}
+
+func TestColourString(t *testing.T) {
+	assert.Equal(t, "#8913af", ParseColour("#8913af").String())
+}
+
+func distance(a, b uint8) uint8 {
+	if a < b {
+		return b - a
+	}
+	return a - b
+}
+
+func TestColourBrighten(t *testing.T) {
+	actual := NewColour(128, 128, 128).Brighten(0.5)
+	// Closeish to what we expect is fine.
+	assert.True(t, distance(192, actual.Red()) <= 2)
+	assert.True(t, distance(192, actual.Blue()) <= 2)
+	assert.True(t, distance(192, actual.Green()) <= 2)
+	actual = NewColour(128, 128, 128).Brighten(-0.5)
+	assert.True(t, distance(65, actual.Red()) <= 2)
+	assert.True(t, distance(65, actual.Blue()) <= 2)
+	assert.True(t, distance(65, actual.Green()) <= 2)
+}
+
+func TestColourBrightess(t *testing.T) {
+	actual := NewColour(128, 128, 128).Brightness()
+	assert.True(t, distance(128, uint8(actual*255.0)) <= 2)
+}
+
+// hue returns c's hue. See https://stackoverflow.com/a/23094494.
+func hue(c Colour) float64 {
+	r := float64(c.Red()) / 255
+	g := float64(c.Green()) / 255
+	b := float64(c.Blue()) / 255
+
+	min := math.Min(math.Min(r, g), b)
+	max := math.Max(math.Max(r, g), b)
+
+	switch {
+	case r == min:
+		return (g - b) / (max - min)
+	case g == min:
+		return 2 + (b-r)/(max-min)
+	default:
+		return 4 + (r-g)/(max-min)
+	}
+}
+
+func TestColourClampBrightness(t *testing.T) {
+	// Start with a colour with a brightness close to 0.5.
+	initial := NewColour(0, 128, 255)
+	br := initial.Brightness()
+	assertInDelta(t, 0.5, br)
+
+	// Passing a range that includes the colour's brightness should be a no-op.
+	assert.Equal(t, initial.String(), initial.ClampBrightness(br-0.01, br+0.01).String())
+
+	// Clamping to [0, 0] or [1, 1] should produce black or white, respectively.
+	assert.Equal(t, "#000000", initial.ClampBrightness(0, 0).String())
+	assert.Equal(t, "#ffffff", initial.ClampBrightness(1, 1).String())
+
+	// Clamping to a brighter or darker range should produce the requested
+	// brightness while preserving the colour's hue.
+	brighter := initial.ClampBrightness(0.75, 1)
+	assertInDelta(t, 0.75, brighter.Brightness())
+	assertInDelta(t, hue(initial), hue(brighter))
+
+	darker := initial.ClampBrightness(0, 0.25)
+	assertInDelta(t, 0.25, darker.Brightness())
+	assertInDelta(t, hue(initial), hue(darker))
+}
+
+func assertInDelta(t *testing.T, expected, actual float64) {
+	const delta = 0.01 // used for brightness and hue comparisons
+	assert.True(t, actual > (expected-delta) && actual < (expected+delta))
+}
diff --git a/delegate.go b/delegate.go
new file mode 100644
index 0000000..f848194
--- /dev/null
+++ b/delegate.go
@@ -0,0 +1,152 @@
+package chroma
+
+import (
+	"bytes"
+)
+
+type delegatingLexer struct {
+	root     Lexer
+	language Lexer
+}
+
+// DelegatingLexer combines two lexers to handle the common case of a language embedded inside another, such as PHP
+// inside HTML or PHP inside plain text.
+//
+// It takes two lexer as arguments: a root lexer and a language lexer.  First everything is scanned using the language
+// lexer, which must return "Other" for unrecognised tokens. Then all "Other" tokens are lexed using the root lexer.
+// Finally, these two sets of tokens are merged.
+//
+// The lexers from the template lexer package use this base lexer.
+func DelegatingLexer(root Lexer, language Lexer) Lexer {
+	return &delegatingLexer{
+		root:     root,
+		language: language,
+	}
+}
+
+func (d *delegatingLexer) AnalyseText(text string) float32 {
+	return d.root.AnalyseText(text)
+}
+
+func (d *delegatingLexer) SetAnalyser(analyser func(text string) float32) Lexer {
+	d.root.SetAnalyser(analyser)
+	return d
+}
+
+func (d *delegatingLexer) SetRegistry(r *LexerRegistry) Lexer {
+	d.root.SetRegistry(r)
+	d.language.SetRegistry(r)
+	return d
+}
+
+func (d *delegatingLexer) Config() *Config {
+	return d.language.Config()
+}
+
+// An insertion is the character range where language tokens should be inserted.
+type insertion struct {
+	start, end int
+	tokens     []Token
+}
+
+func (d *delegatingLexer) Tokenise(options *TokeniseOptions, text string) (Iterator, error) { // nolint: gocognit
+	tokens, err := Tokenise(Coalesce(d.language), options, text)
+	if err != nil {
+		return nil, err
+	}
+	// Compute insertions and gather "Other" tokens.
+	others := &bytes.Buffer{}
+	insertions := []*insertion{}
+	var insert *insertion
+	offset := 0
+	var last Token
+	for _, t := range tokens {
+		if t.Type == Other {
+			if last != EOF && insert != nil && last.Type != Other {
+				insert.end = offset
+			}
+			others.WriteString(t.Value)
+		} else {
+			if last == EOF || last.Type == Other {
+				insert = &insertion{start: offset}
+				insertions = append(insertions, insert)
+			}
+			insert.tokens = append(insert.tokens, t)
+		}
+		last = t
+		offset += len(t.Value)
+	}
+
+	if len(insertions) == 0 {
+		return d.root.Tokenise(options, text)
+	}
+
+	// Lex the other tokens.
+	rootTokens, err := Tokenise(Coalesce(d.root), options, others.String())
+	if err != nil {
+		return nil, err
+	}
+
+	// Interleave the two sets of tokens.
+	var out []Token
+	offset = 0 // Offset into text.
+	tokenIndex := 0
+	nextToken := func() Token {
+		if tokenIndex >= len(rootTokens) {
+			return EOF
+		}
+		t := rootTokens[tokenIndex]
+		tokenIndex++
+		return t
+	}
+	insertionIndex := 0
+	nextInsertion := func() *insertion {
+		if insertionIndex >= len(insertions) {
+			return nil
+		}
+		i := insertions[insertionIndex]
+		insertionIndex++
+		return i
+	}
+	t := nextToken()
+	i := nextInsertion()
+	for t != EOF || i != nil {
+		// fmt.Printf("%d->%d:%q   %d->%d:%q\n", offset, offset+len(t.Value), t.Value, i.start, i.end, Stringify(i.tokens...))
+		if t == EOF || (i != nil && i.start < offset+len(t.Value)) {
+			var l Token
+			l, t = splitToken(t, i.start-offset)
+			if l != EOF {
+				out = append(out, l)
+				offset += len(l.Value)
+			}
+			out = append(out, i.tokens...)
+			offset += i.end - i.start
+			if t == EOF {
+				t = nextToken()
+			}
+			i = nextInsertion()
+		} else {
+			out = append(out, t)
+			offset += len(t.Value)
+			t = nextToken()
+		}
+	}
+	return Literator(out...), nil
+}
+
+func splitToken(t Token, offset int) (l Token, r Token) {
+	if t == EOF {
+		return EOF, EOF
+	}
+	if offset == 0 {
+		return EOF, t
+	}
+	if offset == len(t.Value) {
+		return t, EOF
+	}
+	l = t.Clone()
+	r = t.Clone()
+	l.Value = l.Value[:offset]
+	r.Value = r.Value[offset:]
+	return
+}
diff --git a/delegate_test.go b/delegate_test.go
new file mode 100644
index 0000000..9c4a09b
--- /dev/null
+++ b/delegate_test.go
@@ -0,0 +1,111 @@
+package chroma
+
+import (
+	"testing"
+
+	"github.com/alecthomas/assert/v2"
+)
+
+func makeDelegationTestLexers(t *testing.T) (lang Lexer, root Lexer) {
+	return mustNewLexer(t, nil, Rules{ // nolint: forbidigo
+			"root": {
+				{`\<\?`, CommentPreproc, Push("inside")},
+				{`.`, Other, nil},
+			},
+			"inside": {
+				{`\?\>`, CommentPreproc, Pop(1)},
+				{`\bwhat\b`, Keyword, nil},
+				{`\s+`, Whitespace, nil},
+			},
+		}),
+		mustNewLexer(t, nil, Rules{ // nolint: forbidigo
+			"root": {
+				{`\bhello\b`, Keyword, nil},
+				{`\b(world|there)\b`, Name, nil},
+				{`\s+`, Whitespace, nil},
+			},
+		})
+}
+
+func TestDelegate(t *testing.T) {
+	testdata := []struct {
+		name     string
+		source   string
+		expected []Token
+	}{
+		{"SourceInMiddle", `hello world <? what ?> there`, []Token{
+			{Keyword, "hello"},
+			{TextWhitespace, " "},
+			{Name, "world"},
+			{TextWhitespace, " "},
+			// lang
+			{CommentPreproc, "<?"},
+			{Whitespace, " "},
+			{Keyword, "what"},
+			{Whitespace, " "},
+			{CommentPreproc, "?>"},
+			// /lang
+			{TextWhitespace, " "},
+			{Name, "there"},
+		}},
+		{"SourceBeginning", `<? what ?> hello world there`, []Token{
+			{CommentPreproc, "<?"},
+			{TextWhitespace, " "},
+			{Keyword, "what"},
+			{TextWhitespace, " "},
+			{CommentPreproc, "?>"},
+			{TextWhitespace, " "},
+			{Keyword, "hello"},
+			{TextWhitespace, " "},
+			{Name, "world"},
+			{TextWhitespace, " "},
+			{Name, "there"},
+		}},
+		{"SourceEnd", `hello world <? what there`, []Token{
+			{Keyword, "hello"},
+			{TextWhitespace, " "},
+			{Name, "world"},
+			{TextWhitespace, " "},
+			// lang
+			{CommentPreproc, "<?"},
+			{Whitespace, " "},
+			{Keyword, "what"},
+			{TextWhitespace, " "},
+			{Error, "there"},
+		}},
+		{"SourceMultiple", "hello world <? what ?> hello there <? what ?> hello", []Token{
+			{Keyword, "hello"},
+			{TextWhitespace, " "},
+			{Name, "world"},
+			{TextWhitespace, " "},
+			{CommentPreproc, "<?"},
+			{TextWhitespace, " "},
+			{Keyword, "what"},
+			{TextWhitespace, " "},
+			{CommentPreproc, "?>"},
+			{TextWhitespace, " "},
+			{Keyword, "hello"},
+			{TextWhitespace, " "},
+			{Name, "there"},
+			{TextWhitespace, " "},
+			{CommentPreproc, "<?"},
+			{TextWhitespace, " "},
+			{Keyword, "what"},
+			{TextWhitespace, " "},
+			{CommentPreproc, "?>"},
+			{TextWhitespace, " "},
+			{Keyword, "hello"},
+		}},
+	}
+	lang, root := makeDelegationTestLexers(t)
+	delegate := DelegatingLexer(root, lang)
+	for _, test := range testdata {
+		// nolint: scopelint
+		t.Run(test.name, func(t *testing.T) {
+			it, err := delegate.Tokenise(nil, test.source)
+			assert.NoError(t, err)
+			actual := it.Tokens()
+			assert.Equal(t, test.expected, actual)
+		})
+	}
+}
diff --git a/doc.go b/doc.go
new file mode 100644
index 0000000..4dde77c
--- /dev/null
+++ b/doc.go
@@ -0,0 +1,7 @@
+// Package chroma takes source code and other structured text and converts it into syntax highlighted HTML, ANSI-
+// coloured text, etc.
+//
+// Chroma is based heavily on Pygments, and includes translators for Pygments lexers and styles.
+//
+// For more information, go here: https://github.com/alecthomas/chroma
+package chroma
diff --git a/emitters.go b/emitters.go
new file mode 100644
index 0000000..0788b5b
--- /dev/null
+++ b/emitters.go
@@ -0,0 +1,218 @@
+package chroma
+
+import (
+	"fmt"
+)
+
+// An Emitter takes group matches and returns tokens.
+type Emitter interface {
+	// Emit tokens for the given regex groups.
+	Emit(groups []string, state *LexerState) Iterator
+}
+
+// SerialisableEmitter is an Emitter that can be serialised and deserialised to/from JSON.
+type SerialisableEmitter interface {
+	Emitter
+	EmitterKind() string
+}
+
+// EmitterFunc is a function that is an Emitter.
+type EmitterFunc func(groups []string, state *LexerState) Iterator
+
+// Emit tokens for groups.
+func (e EmitterFunc) Emit(groups []string, state *LexerState) Iterator {
+	return e(groups, state)
+}
+
+type Emitters []Emitter
+
+type byGroupsEmitter struct {
+	Emitters
+}
+
+// ByGroups emits a token for each matching group in the rule's regex.
+func ByGroups(emitters ...Emitter) Emitter {
+	return &byGroupsEmitter{Emitters: emitters}
+}
+
+func (b *byGroupsEmitter) EmitterKind() string { return "bygroups" }
+
+func (b *byGroupsEmitter) Emit(groups []string, state *LexerState) Iterator {
+	iterators := make([]Iterator, 0, len(groups)-1)
+	if len(b.Emitters) != len(groups)-1 {
+		iterators = append(iterators, Error.Emit(groups, state))
+		// panic(errors.Errorf("number of groups %q does not match number of emitters %v", groups, emitters))
+	} else {
+		for i, group := range groups[1:] {
+			if b.Emitters[i] != nil {
+				iterators = append(iterators, b.Emitters[i].Emit([]string{group}, state))
+			}
+		}
+	}
+	return Concaterator(iterators...)
+}
+
+// ByGroupNames emits a token for each named matching group in the rule's regex.
+func ByGroupNames(emitters map[string]Emitter) Emitter {
+	return EmitterFunc(func(groups []string, state *LexerState) Iterator {
+		iterators := make([]Iterator, 0, len(state.NamedGroups)-1)
+		if len(state.NamedGroups)-1 == 0 {
+			if emitter, ok := emitters[`0`]; ok {
+				iterators = append(iterators, emitter.Emit(groups, state))
+			} else {
+				iterators = append(iterators, Error.Emit(groups, state))
+			}
+		} else {
+			ruleRegex := state.Rules[state.State][state.Rule].Regexp
+			for i := 1; i < len(state.NamedGroups); i++ {
+				groupName := ruleRegex.GroupNameFromNumber(i)
+				group := state.NamedGroups[groupName]
+				if emitter, ok := emitters[groupName]; ok {
+					if emitter != nil {
+						iterators = append(iterators, emitter.Emit([]string{group}, state))
+					}
+				} else {
+					iterators = append(iterators, Error.Emit([]string{group}, state))
+				}
+			}
+		}
+		return Concaterator(iterators...)
+	})
+}
+
+// UsingByGroup emits tokens for the matched groups in the regex using a
+// sublexer. Used when lexing code blocks where the name of a sublexer is
+// contained within the block, for example on a Markdown text block or SQL
+// language block.
+//
+// An attempt to load the sublexer will be made using the captured value from
+// the text of the matched sublexerNameGroup. If a sublexer matching the
+// sublexerNameGroup is available, then tokens for the matched codeGroup will
+// be emitted using the sublexer. Otherwise, if no sublexer is available, then
+// tokens will be emitted from the passed emitter.
+//
+// Example:
+//
+//	var Markdown = internal.Register(MustNewLexer(
+//		&Config{
+//			Name:      "markdown",
+//			Aliases:   []string{"md", "mkd"},
+//			Filenames: []string{"*.md", "*.mkd", "*.markdown"},
+//			MimeTypes: []string{"text/x-markdown"},
+//		},
+//		Rules{
+//			"root": {
+//				{"^(```)(\\w+)(\\n)([\\w\\W]*?)(^```$)",
+//					UsingByGroup(
+//						2, 4,
+//						String, String, String, Text, String,
+//					),
+//					nil,
+//				},
+//			},
+//		},
+//	))
+//
+// See the lexers/markdown.go for the complete example.
+//
+// Note: panic's if the number of emitters does not equal the number of matched
+// groups in the regex.
+func UsingByGroup(sublexerNameGroup, codeGroup int, emitters ...Emitter) Emitter {
+	return &usingByGroup{
+		SublexerNameGroup: sublexerNameGroup,
+		CodeGroup:         codeGroup,
+		Emitters:          emitters,
+	}
+}
+
+type usingByGroup struct {
+	SublexerNameGroup int      `xml:"sublexer_name_group"`
+	CodeGroup         int      `xml:"code_group"`
+	Emitters          Emitters `xml:"emitters"`
+}
+
+func (u *usingByGroup) EmitterKind() string { return "usingbygroup" }
+func (u *usingByGroup) Emit(groups []string, state *LexerState) Iterator {
+	// bounds check
+	if len(u.Emitters) != len(groups)-1 {
+		panic("UsingByGroup expects number of emitters to be the same as len(groups)-1")
+	}
+
+	// grab sublexer
+	sublexer := state.Registry.Get(groups[u.SublexerNameGroup])
+
+	// build iterators
+	iterators := make([]Iterator, len(groups)-1)
+	for i, group := range groups[1:] {
+		if i == u.CodeGroup-1 && sublexer != nil {
+			var err error
+			iterators[i], err = sublexer.Tokenise(nil, groups[u.CodeGroup])
+			if err != nil {
+				panic(err)
+			}
+		} else if u.Emitters[i] != nil {
+			iterators[i] = u.Emitters[i].Emit([]string{group}, state)
+		}
+	}
+	return Concaterator(iterators...)
+}
+
+// UsingLexer returns an Emitter that uses a given Lexer for parsing and emitting.
+//
+// This Emitter is not serialisable.
+func UsingLexer(lexer Lexer) Emitter {
+	return EmitterFunc(func(groups []string, _ *LexerState) Iterator {
+		it, err := lexer.Tokenise(&TokeniseOptions{State: "root", Nested: true}, groups[0])
+		if err != nil {
+			panic(err)
+		}
+		return it
+	})
+}
+
+type usingEmitter struct {
+	Lexer string `xml:"lexer,attr"`
+}
+
+func (u *usingEmitter) EmitterKind() string { return "using" }
+
+func (u *usingEmitter) Emit(groups []string, state *LexerState) Iterator {
+	if state.Registry == nil {
+		panic(fmt.Sprintf("no LexerRegistry available for Using(%q)", u.Lexer))
+	}
+	lexer := state.Registry.Get(u.Lexer)
+	if lexer == nil {
+		panic(fmt.Sprintf("no such lexer %q", u.Lexer))
+	}
+	it, err := lexer.Tokenise(&TokeniseOptions{State: "root", Nested: true}, groups[0])
+	if err != nil {
+		panic(err)
+	}
+	return it
+}
+
+// Using returns an Emitter that uses a given Lexer reference for parsing and emitting.
+//
+// The referenced lexer must be stored in the same LexerRegistry.
+func Using(lexer string) Emitter {
+	return &usingEmitter{Lexer: lexer}
+}
+
+type usingSelfEmitter struct {
+	State string `xml:"state,attr"`
+}
+
+func (u *usingSelfEmitter) EmitterKind() string { return "usingself" }
+
+func (u *usingSelfEmitter) Emit(groups []string, state *LexerState) Iterator {
+	it, err := state.Lexer.Tokenise(&TokeniseOptions{State: u.State, Nested: true}, groups[0])
+	if err != nil {
+		panic(err)
+	}
+	return it
+}
+
+// UsingSelf is like Using, but uses the current Lexer.
+func UsingSelf(stateName string) Emitter {
+	return &usingSelfEmitter{stateName}
+}
diff --git a/formatter.go b/formatter.go
new file mode 100644
index 0000000..00dd5d8
--- /dev/null
+++ b/formatter.go
@@ -0,0 +1,43 @@
+package chroma
+
+import (
+	"io"
+)
+
+// A Formatter for Chroma lexers.
+type Formatter interface {
+	// Format returns a formatting function for tokens.
+	//
+	// If the iterator panics, the Formatter should recover.
+	Format(w io.Writer, style *Style, iterator Iterator) error
+}
+
+// A FormatterFunc is a Formatter implemented as a function.
+//
+// Guards against iterator panics.
+type FormatterFunc func(w io.Writer, style *Style, iterator Iterator) error
+
+func (f FormatterFunc) Format(w io.Writer, s *Style, it Iterator) (err error) { // nolint
+	defer func() {
+		if perr := recover(); perr != nil {
+			err = perr.(error)
+		}
+	}()
+	return f(w, s, it)
+}
+
+type recoveringFormatter struct {
+	Formatter
+}
+
+func (r recoveringFormatter) Format(w io.Writer, s *Style, it Iterator) (err error) {
+	defer func() {
+		if perr := recover(); perr != nil {
+			err = perr.(error)
+		}
+	}()
+	return r.Formatter.Format(w, s, it)
+}
+
+// RecoveringFormatter wraps a formatter with panic recovery.
+func RecoveringFormatter(formatter Formatter) Formatter { return recoveringFormatter{formatter} }
diff --git a/go.mod b/go.mod
new file mode 100644
index 0000000..06e3656
--- /dev/null
+++ b/go.mod
@@ -0,0 +1,11 @@
+module toastielab.dev/toastie-stuff/chroma/v2
+
+go 1.24.1
+
+require (
+	github.com/alecthomas/assert/v2 v2.10.0
+	github.com/alecthomas/repr v0.4.0
+	github.com/dlclark/regexp2 v1.11.0
+)
+
+require github.com/hexops/gotextdiff v1.0.3 // indirect
\ No newline at end of file
diff --git a/go.sum b/go.sum
new file mode 100644
index 0000000..4bd5c9d
--- /dev/null
+++ b/go.sum
@@ -0,0 +1,5 @@
+github.com/alecthomas/assert/v2 v2.10.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k=
+github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
+github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI=
+github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
+github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=
diff --git a/iterator.go b/iterator.go
new file mode 100644
index 0000000..d5175de
--- /dev/null
+++ b/iterator.go
@@ -0,0 +1,76 @@
+package chroma
+
+import "strings"
+
+// An Iterator across tokens.
+//
+// EOF will be returned at the end of the Token stream.
+//
+// If an error occurs within an Iterator, it may propagate this in a panic. Formatters should recover.
+type Iterator func() Token
+
+// Tokens consumes all tokens from the iterator and returns them as a slice.
+func (i Iterator) Tokens() []Token {
+	var out []Token
+	for t := i(); t != EOF; t = i() {
+		out = append(out, t)
+	}
+	return out
+}
+
+// Concaterator concatenates tokens from a series of iterators.
+func Concaterator(iterators ...Iterator) Iterator {
+	return func() Token {
+		for len(iterators) > 0 {
+			t := iterators[0]()
+			if t != EOF {
+				return t
+			}
+			iterators = iterators[1:]
+		}
+		return EOF
+	}
+}
+
+// Literator converts a sequence of literal Tokens into an Iterator.
+func Literator(tokens ...Token) Iterator {
+	return func() Token {
+		if len(tokens) == 0 {
+			return EOF
+		}
+		token := tokens[0]
+		tokens = tokens[1:]
+		return token
+	}
+}
+
+// SplitTokensIntoLines splits tokens containing newlines in two.
+func SplitTokensIntoLines(tokens []Token) (out [][]Token) {
+	var line []Token // nolint: prealloc
+	for _, token := range tokens {
+		for strings.Contains(token.Value, "\n") {
+			parts := strings.SplitAfterN(token.Value, "\n", 2)
+			// Token becomes the tail.
+			token.Value = parts[1]
+
+			// Append the head to the line and flush the line.
+			clone := token.Clone()
+			clone.Value = parts[0]
+			line = append(line, clone)
+			out = append(out, line)
+			line = nil
+		}
+		line = append(line, token)
+	}
+	if len(line) > 0 {
+		out = append(out, line)
+	}
+	// Strip empty trailing token line.
+	if len(out) > 0 {
+		last := out[len(out)-1]
+		if len(last) == 1 && last[0].Value == "" {
+			out = out[:len(out)-1]
+		}
+	}
+	return
+}
diff --git a/lexer.go b/lexer.go
new file mode 100644
index 0000000..eb027bf
--- /dev/null
+++ b/lexer.go
@@ -0,0 +1,162 @@
+package chroma
+
+import (
+	"fmt"
+	"strings"
+)
+
+var (
+	defaultOptions = &TokeniseOptions{
+		State:    "root",
+		EnsureLF: true,
+	}
+)
+
+// Config for a lexer.
+type Config struct {
+	// Name of the lexer.
+	Name string `xml:"name,omitempty"`
+
+	// Shortcuts for the lexer
+	Aliases []string `xml:"alias,omitempty"`
+
+	// File name globs
+	Filenames []string `xml:"filename,omitempty"`
+
+	// Secondary file name globs
+	AliasFilenames []string `xml:"alias_filename,omitempty"`
+
+	// MIME types
+	MimeTypes []string `xml:"mime_type,omitempty"`
+
+	// Regex matching is case-insensitive.
+	CaseInsensitive bool `xml:"case_insensitive,omitempty"`
+
+	// Regex matches all characters.
+	DotAll bool `xml:"dot_all,omitempty"`
+
+	// Regex does not match across lines ($ matches EOL).
+	//
+	// Defaults to multiline.
+	NotMultiline bool `xml:"not_multiline,omitempty"`
+
+	// Don't strip leading and trailing newlines from the input.
+	// DontStripNL bool
+
+	// Strip all leading and trailing whitespace from the input
+	// StripAll bool
+
+	// Make sure that the input ends with a newline. This
+	// is required for some lexers that consume input linewise.
+	EnsureNL bool `xml:"ensure_nl,omitempty"`
+
+	// If given and greater than 0, expand tabs in the input.
+	// TabSize int
+
+	// Priority of lexer.
+	//
+	// If this is 0 it will be treated as a default of 1.
+	Priority float32 `xml:"priority,omitempty"`
+
+	// Analyse is a list of regexes to match against the input.
+	//
+	// If a match is found, the score is returned if single attribute is set to true,
+	// otherwise the sum of all the score of matching patterns will be
+	// used as the final score.
+	Analyse *AnalyseConfig `xml:"analyse,omitempty"`
+}
+
+// AnalyseConfig defines the list of regexes analysers.
+type AnalyseConfig struct {
+	Regexes []RegexConfig `xml:"regex,omitempty"`
+	// If true, the first matching score is returned.
+	First bool `xml:"first,attr"`
+}
+
+// RegexConfig defines a single regex pattern and its score in case of match.
+type RegexConfig struct {
+	Pattern string  `xml:"pattern,attr"`
+	Score   float32 `xml:"score,attr"`
+}
+
+// Token output to formatter.
+type Token struct {
+	Type  TokenType `json:"type"`
+	Value string    `json:"value"`
+}
+
+func (t *Token) String() string   { return t.Value }
+func (t *Token) GoString() string { return fmt.Sprintf("&Token{%s, %q}", t.Type, t.Value) }
+
+// Clone returns a clone of the Token.
+func (t *Token) Clone() Token {
+	return *t
+}
+
+// EOF is returned by lexers at the end of input.
+var EOF Token
+
+// TokeniseOptions contains options for tokenisers.
+type TokeniseOptions struct {
+	// State to start tokenisation in. Defaults to "root".
+	State string
+	// Nested tokenisation.
+	Nested bool
+
+	// If true, all EOLs are converted into LF
+	// by replacing CRLF and CR
+	EnsureLF bool
+}
+
+// A Lexer for tokenising source code.
+type Lexer interface {
+	// Config describing the features of the Lexer.
+	Config() *Config
+	// Tokenise returns an Iterator over tokens in text.
+	Tokenise(options *TokeniseOptions, text string) (Iterator, error)
+	// SetRegistry sets the registry this Lexer is associated with.
+	//
+	// The registry should be used by the Lexer if it needs to look up other
+	// lexers.
+	SetRegistry(registry *LexerRegistry) Lexer
+	// SetAnalyser sets a function the Lexer should use for scoring how
+	// likely a fragment of text is to match this lexer, between 0.0 and 1.0.
+	// A value of 1 indicates high confidence.
+	//
+	// Lexers may ignore this if they implement their own analysers.
+	SetAnalyser(analyser func(text string) float32) Lexer
+	// AnalyseText scores how likely a fragment of text is to match
+	// this lexer, between 0.0 and 1.0. A value of 1 indicates high confidence.
+	AnalyseText(text string) float32
+}
+
+// Lexers is a slice of lexers sortable by name.
+type Lexers []Lexer
+
+func (l Lexers) Len() int      { return len(l) }
+func (l Lexers) Swap(i, j int) { l[i], l[j] = l[j], l[i] }
+func (l Lexers) Less(i, j int) bool {
+	return strings.ToLower(l[i].Config().Name) < strings.ToLower(l[j].Config().Name)
+}
+
+// PrioritisedLexers is a slice of lexers sortable by priority.
+type PrioritisedLexers []Lexer
+
+func (l PrioritisedLexers) Len() int      { return len(l) }
+func (l PrioritisedLexers) Swap(i, j int) { l[i], l[j] = l[j], l[i] }
+func (l PrioritisedLexers) Less(i, j int) bool {
+	ip := l[i].Config().Priority
+	if ip == 0 {
+		ip = 1
+	}
+	jp := l[j].Config().Priority
+	if jp == 0 {
+		jp = 1
+	}
+	return ip > jp
+}
+
+// Analyser determines how appropriate this lexer is for the given text.
+type Analyser interface {
+	AnalyseText(text string) float32
+}
diff --git a/lexer_test.go b/lexer_test.go
new file mode 100644
index 0000000..0f0ab5f
--- /dev/null
+++ b/lexer_test.go
@@ -0,0 +1,48 @@
+package chroma
+
+import (
+	"testing"
+
+	"github.com/alecthomas/assert/v2"
+)
+
+func TestTokenTypeClassifiers(t *testing.T) {
+	assert.True(t, GenericDeleted.InCategory(Generic))
+	assert.True(t, LiteralStringBacktick.InSubCategory(String))
+	assert.Equal(t, LiteralStringBacktick.String(), "LiteralStringBacktick")
+}
+
+func TestSimpleLexer(t *testing.T) {
+	lexer := mustNewLexer(t, &Config{
+		Name:      "INI",
+		Aliases:   []string{"ini", "cfg"},
+		Filenames: []string{"*.ini", "*.cfg"},
+	}, map[string][]Rule{
+		"root": {
+			{`\s+`, Whitespace, nil},
+			{`;.*?$`, Comment, nil},
+			{`\[.*?\]$`, Keyword, nil},
+			{`(.*?)(\s*)(=)(\s*)(.*?)$`, ByGroups(Name, Whitespace, Operator, Whitespace, String), nil},
+		},
+	})
+	actual, err := Tokenise(lexer, nil, `
+	; this is a comment
+	[section]
+	a = 10
+`)
+	assert.NoError(t, err)
+	expected := []Token{
+		{Whitespace, "\n\t"},
+		{Comment, "; this is a comment"},
+		{Whitespace, "\n\t"},
+		{Keyword, "[section]"},
+		{Whitespace, "\n\t"},
+		{Name, "a"},
+		{Whitespace, " "},
+		{Operator, "="},
+		{Whitespace, " "},
+		{LiteralString, "10"},
+		{Whitespace, "\n"},
+	}
+	assert.Equal(t, expected, actual)
+}
diff --git a/mutator_test.go b/mutator_test.go
new file mode 100644
index 0000000..6561fc4
--- /dev/null
+++ b/mutator_test.go
@@ -0,0 +1,57 @@
+package chroma
+
+import (
+	"testing"
+
+	"github.com/alecthomas/assert/v2"
+)
+
+func TestInclude(t *testing.T) {
+	include := Include("other")
+	actual := CompiledRules{
+		"root": {{Rule: include}},
+		"other": {
+			{Rule: Rule{Pattern: "//.+", Type: Comment}},
+			{Rule: Rule{Pattern: `"[^"]*"`, Type: String}},
+		},
+	}
+	lexer := &RegexLexer{rules: actual}
+	err := include.Mutator.(LexerMutator).MutateLexer(lexer.rules, "root", 0)
+	assert.NoError(t, err)
+	expected := CompiledRules{
+		"root": {
+			{Rule: Rule{
+				Pattern: "//.+",
+				Type:    Comment,
+			}},
+			{Rule: Rule{
+				Pattern: `"[^"]*"`,
+				Type:    String,
+			}},
+		},
+		"other": {
+			{Rule: Rule{
+				Pattern: "//.+",
+				Type:    Comment,
+			}},
+			{Rule: Rule{
+				Pattern: `"[^"]*"`,
+				Type:    String,
+			}},
+		},
+	}
+	assert.Equal(t, expected, actual)
+}
+
+func TestCombine(t *testing.T) {
+	l := mustNewLexer(t, nil, Rules{ // nolint: forbidigo
+		"root":  {{`hello`, String, Combined("world", "bye", "space")}},
+		"world": {{`world`, Name, nil}},
+		"bye":   {{`bye`, Name, nil}},
+		"space": {{`\s+`, Whitespace, nil}},
+	})
+	it, err := l.Tokenise(nil, "hello world")
+	assert.NoError(t, err)
+	expected := []Token{{String, `hello`}, {Whitespace, ` `}, {Name, `world`}}
+	assert.Equal(t, expected, it.Tokens())
+}
diff --git a/mutators.go b/mutators.go
new file mode 100644
index 0000000..e80ad97
--- /dev/null
+++ b/mutators.go
@@ -0,0 +1,201 @@
+package chroma
+
+import (
+	"encoding/xml"
+	"fmt"
+	"strings"
+)
+
+// A Mutator modifies the behaviour of the lexer.
+type Mutator interface {
+	// Mutate the lexer state machine as it is processing.
+	Mutate(state *LexerState) error
+}
+
+// SerialisableMutator is a Mutator that can be serialised and deserialised.
+type SerialisableMutator interface {
+	Mutator
+	MutatorKind() string
+}
+
+// A LexerMutator is an additional interface that a Mutator can implement
+// to modify the lexer when it is compiled.
+type LexerMutator interface {
+	// MutateLexer can be implemented to mutate the lexer itself.
+	//
+	// Rules are the lexer rules, state is the state key for the rule the mutator is associated with.
+	MutateLexer(rules CompiledRules, state string, rule int) error
+}
+
+// A MutatorFunc is a Mutator that mutates the lexer state machine as it is processing.
+type MutatorFunc func(state *LexerState) error
+
+func (m MutatorFunc) Mutate(state *LexerState) error { return m(state) } // nolint
+
+type multiMutator struct {
+	Mutators []Mutator `xml:"mutator"`
+}
+
+func (m *multiMutator) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
+	for {
+		token, err := d.Token()
+		if err != nil {
+			return err
+		}
+		switch token := token.(type) {
+		case xml.StartElement:
+			mutator, err := unmarshalMutator(d, token)
+			if err != nil {
+				return err
+			}
+			m.Mutators = append(m.Mutators, mutator)
+
+		case xml.EndElement:
+			return nil
+		}
+	}
+}
+
+func (m *multiMutator) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
+	name := xml.Name{Local: "mutators"}
+	if err := e.EncodeToken(xml.StartElement{Name: name}); err != nil {
+		return err
+	}
+	for _, m := range m.Mutators {
+		if err := marshalMutator(e, m); err != nil {
+			return err
+		}
+	}
+	return e.EncodeToken(xml.EndElement{Name: name})
+}
+
+func (m *multiMutator) MutatorKind() string { return "mutators" }
+
+func (m *multiMutator) Mutate(state *LexerState) error {
+	for _, modifier := range m.Mutators {
+		if err := modifier.Mutate(state); err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+// Mutators applies a set of Mutators in order.
+func Mutators(modifiers ...Mutator) Mutator {
+	return &multiMutator{modifiers}
+}
+
+type includeMutator struct {
+	State string `xml:"state,attr"`
+}
+
+// Include the given state.
+func Include(state string) Rule {
+	return Rule{Mutator: &includeMutator{state}}
+}
+
+func (i *includeMutator) MutatorKind() string { return "include" }
+
+func (i *includeMutator) Mutate(s *LexerState) error {
+	return fmt.Errorf("should never reach here Include(%q)", i.State)
+}
+
+func (i *includeMutator) MutateLexer(rules CompiledRules, state string, rule int) error {
+	includedRules, ok := rules[i.State]
+	if !ok {
+		return fmt.Errorf("invalid include state %q", i.State)
+	}
+	rules[state] = append(rules[state][:rule], append(includedRules, rules[state][rule+1:]...)...)
+	return nil
+}
+
+type combinedMutator struct {
+	States []string `xml:"state,attr"`
+}
+
+func (c *combinedMutator) MutatorKind() string { return "combined" }
+
+// Combined creates a new anonymous state from the given states, and pushes that state.
+func Combined(states ...string) Mutator {
+	return &combinedMutator{states}
+}
+
+func (c *combinedMutator) Mutate(s *LexerState) error {
+	return fmt.Errorf("should never reach here Combined(%v)", c.States)
+}
+
+func (c *combinedMutator) MutateLexer(rules CompiledRules, state string, rule int) error {
+	name := "__combined_" + strings.Join(c.States, "__")
+	if _, ok := rules[name]; !ok {
+		combined := []*CompiledRule{}
+		for _, state := range c.States {
+			rules, ok := rules[state]
+			if !ok {
+				return fmt.Errorf("invalid combine state %q", state)
+			}
+			combined = append(combined, rules...)
+		}
+		rules[name] = combined
+	}
+	rules[state][rule].Mutator = Push(name)
+	return nil
+}
+
+type pushMutator struct {
+	States []string `xml:"state,attr"`
+}
+
+func (p *pushMutator) MutatorKind() string { return "push" }
+
+func (p *pushMutator) Mutate(s *LexerState) error {
+	if len(p.States) == 0 {
+		s.Stack = append(s.Stack, s.State)
+	} else {
+		for _, state := range p.States {
+			if state == "#pop" {
+				s.Stack = s.Stack[:len(s.Stack)-1]
+			} else {
+				s.Stack = append(s.Stack, state)
+			}
+		}
+	}
+	return nil
+}
+
+// Push states onto the stack.
+func Push(states ...string) Mutator {
+	return &pushMutator{states}
+}
+
+type popMutator struct {
+	Depth int `xml:"depth,attr"`
+}
+
+func (p *popMutator) MutatorKind() string { return "pop" }
+
+func (p *popMutator) Mutate(state *LexerState) error {
+	if len(state.Stack) == 0 {
+		return fmt.Errorf("nothing to pop")
+	}
+	state.Stack = state.Stack[:len(state.Stack)-p.Depth]
+	return nil
+}
+
+// Pop state from the stack when rule matches.
+func Pop(n int) Mutator {
+	return &popMutator{n}
+}
+
+// Default returns a Rule that applies a set of Mutators.
+func Default(mutators ...Mutator) Rule {
+	return Rule{Mutator: Mutators(mutators...)}
+}
+
+// Stringify returns the raw string for a set of tokens.
+func Stringify(tokens ...Token) string {
+	out := []string{}
+	for _, t := range tokens {
+		out = append(out, t.Value)
+	}
+	return strings.Join(out, "")
+}
diff --git a/regexp.go b/regexp.go
new file mode 100644
index 0000000..0dcb077
--- /dev/null
+++ b/regexp.go
@@ -0,0 +1,483 @@
+package chroma
+
+import (
+	"fmt"
+	"os"
+	"path/filepath"
+	"regexp"
+	"sort"
+	"strings"
+	"sync"
+	"time"
+	"unicode/utf8"
+
+	"github.com/dlclark/regexp2"
+)
+
+// A Rule is the fundamental matching unit of the Regex lexer state machine.
+type Rule struct {
+	Pattern string
+	Type    Emitter
+	Mutator Mutator
+}
+
+// Words creates a regex that matches any of the given literal words.
+func Words(prefix, suffix string, words ...string) string {
+	sort.Slice(words, func(i, j int) bool {
+		return len(words[j]) < len(words[i])
+	})
+	for i, word := range words {
+		words[i] = regexp.QuoteMeta(word)
+	}
+	return prefix + `(` + strings.Join(words, `|`) + `)` + suffix
+}
+
+// Tokenise text using lexer, returning tokens as a slice.
+func Tokenise(lexer Lexer, options *TokeniseOptions, text string) ([]Token, error) {
+	var out []Token
+	it, err := lexer.Tokenise(options, text)
+	if err != nil {
+		return nil, err
+	}
+	for t := it(); t != EOF; t = it() {
+		out = append(out, t)
+	}
+	return out, nil
+}
+
+// Rules maps from state to a sequence of Rules.
+type Rules map[string][]Rule
+
+// Rename clones rules then a rule.
+func (r Rules) Rename(oldRule, newRule string) Rules {
+	r = r.Clone()
+	r[newRule] = r[oldRule]
+	delete(r, oldRule)
+	return r
+}
+
+// Clone returns a clone of the Rules.
+func (r Rules) Clone() Rules {
+	out := map[string][]Rule{}
+	for key, rules := range r {
+		out[key] = make([]Rule, len(rules))
+		copy(out[key], rules)
+	}
+	return out
+}
+
+// Merge creates a clone of "r" then merges "rules" into the clone.
+func (r Rules) Merge(rules Rules) Rules {
+	out := r.Clone()
+	for k, v := range rules.Clone() {
+		out[k] = v
+	}
+	return out
+}
+
+// MustNewLexer creates a new Lexer with deferred rules generation or panics.
+func MustNewLexer(config *Config, rules func() Rules) *RegexLexer {
+	lexer, err := NewLexer(config, rules)
+	if err != nil {
+		panic(err)
+	}
+	return lexer
+}
+
+// NewLexer creates a new regex-based Lexer.
+//
+// "rules" is a state machine transition map. Each key is a state. Values are sets of rules
+// that match input, optionally modify lexer state, and output tokens.
+func NewLexer(config *Config, rulesFunc func() Rules) (*RegexLexer, error) {
+	if config == nil {
+		config = &Config{}
+	}
+	for _, glob := range append(config.Filenames, config.AliasFilenames...) {
+		_, err := filepath.Match(glob, "")
+		if err != nil {
+			return nil, fmt.Errorf("%s: %q is not a valid glob: %w", config.Name, glob, err)
+		}
+	}
+	r := &RegexLexer{
+		config:         config,
+		fetchRulesFunc: func() (Rules, error) { return rulesFunc(), nil },
+	}
+	// One-off code to generate XML lexers in the Chroma source tree.
+	// var nameCleanRe = regexp.MustCompile(`[^-+A-Za-z0-9_]`)
+	// name := strings.ToLower(nameCleanRe.ReplaceAllString(config.Name, "_"))
+	// data, err := Marshal(r)
+	// if err != nil {
+	// 	if errors.Is(err, ErrNotSerialisable) {
+	// 		fmt.Fprintf(os.Stderr, "warning: %q: %s\n", name, err)
+	// 		return r, nil
+	// 	}
+	// 	return nil, err
+	// }
+	// _, file, _, ok := runtime.Caller(2)
+	// if !ok {
+	// 	panic("??")
+	// }
+	// fmt.Println(file)
+	// if strings.Contains(file, "/lexers/") {
+	// 	dir := filepath.Join(filepath.Dir(file), "embedded")
+	// 	err = os.MkdirAll(dir, 0700)
+	// 	if err != nil {
+	// 		return nil, err
+	// 	}
+	// 	filename := filepath.Join(dir, name) + ".xml"
+	// 	fmt.Println(filename)
+	// 	err = ioutil.WriteFile(filename, data, 0600)
+	// 	if err != nil {
+	// 		return nil, err
+	// 	}
+	// }
+	return r, nil
+}
+
+// Trace enables debug tracing.
+func (r *RegexLexer) Trace(trace bool) *RegexLexer {
+	r.trace = trace
+	return r
+}
+
+// A CompiledRule is a Rule with a pre-compiled regex.
+//
+// Note that regular expressions are lazily compiled on first use of the lexer.
+type CompiledRule struct {
+	Rule
+	Regexp *regexp2.Regexp
+	flags  string
+}
+
+// CompiledRules is a map of rule name to sequence of compiled rules in that rule.
+type CompiledRules map[string][]*CompiledRule
+
+// LexerState contains the state for a single lex.
+type LexerState struct {
+	Lexer    *RegexLexer
+	Registry *LexerRegistry
+	Text     []rune
+	Pos      int
+	Rules    CompiledRules
+	Stack    []string
+	State    string
+	Rule     int
+	// Group matches.
+	Groups []string
+	// Named Group matches.
+	NamedGroups map[string]string
+	// Custum context for mutators.
+	MutatorContext map[interface{}]interface{}
+	iteratorStack  []Iterator
+	options        *TokeniseOptions
+	newlineAdded   bool
+}
+
+// Set mutator context.
+func (l *LexerState) Set(key interface{}, value interface{}) {
+	l.MutatorContext[key] = value
+}
+
+// Get mutator context.
+func (l *LexerState) Get(key interface{}) interface{} {
+	return l.MutatorContext[key]
+}
+
+// Iterator returns the next Token from the lexer.
+func (l *LexerState) Iterator() Token { // nolint: gocognit
+	end := len(l.Text)
+	if l.newlineAdded {
+		end--
+	}
+	for l.Pos < end && len(l.Stack) > 0 {
+		// Exhaust the iterator stack, if any.
+		for len(l.iteratorStack) > 0 {
+			n := len(l.iteratorStack) - 1
+			t := l.iteratorStack[n]()
+			if t == EOF {
+				l.iteratorStack = l.iteratorStack[:n]
+				continue
+			}
+			return t
+		}
+
+		l.State = l.Stack[len(l.Stack)-1]
+		if l.Lexer.trace {
+			fmt.Fprintf(os.Stderr, "%s: pos=%d, text=%q\n", l.State, l.Pos, string(l.Text[l.Pos:]))
+		}
+		selectedRule, ok := l.Rules[l.State]
+		if !ok {
+			panic("unknown state " + l.State)
+		}
+		ruleIndex, rule, groups, namedGroups := matchRules(l.Text, l.Pos, selectedRule)
+		// No match.
+		if groups == nil {
+			// From Pygments :\
+			//
+			// If the RegexLexer encounters a newline that is flagged as an error token, the stack is
+			// emptied and the lexer continues scanning in the 'root' state. This can help producing
+			// error-tolerant highlighting for erroneous input, e.g. when a single-line string is not
+			// closed.
+			if l.Text[l.Pos] == '\n' && l.State != l.options.State {
+				l.Stack = []string{l.options.State}
+				continue
+			}
+			l.Pos++
+			return Token{Error, string(l.Text[l.Pos-1 : l.Pos])}
+		}
+		l.Rule = ruleIndex
+		l.Groups = groups
+		l.NamedGroups = namedGroups
+		l.Pos += utf8.RuneCountInString(groups[0])
+		if rule.Mutator != nil {
+			if err := rule.Mutator.Mutate(l); err != nil {
+				panic(err)
+			}
+		}
+		if rule.Type != nil {
+			l.iteratorStack = append(l.iteratorStack, rule.Type.Emit(l.Groups, l))
+		}
+	}
+	// Exhaust the IteratorStack, if any.
+	// Duplicate code, but eh.
+	for len(l.iteratorStack) > 0 {
+		n := len(l.iteratorStack) - 1
+		t := l.iteratorStack[n]()
+		if t == EOF {
+			l.iteratorStack = l.iteratorStack[:n]
+			continue
+		}
+		return t
+	}
+
+	// If we get to here and we still have text, return it as an error.
+	if l.Pos != len(l.Text) && len(l.Stack) == 0 {
+		value := string(l.Text[l.Pos:])
+		l.Pos = len(l.Text)
+		return Token{Type: Error, Value: value}
+	}
+	return EOF
+}
+
+// RegexLexer is the default lexer implementation used in Chroma.
+type RegexLexer struct {
+	registry *LexerRegistry // The LexerRegistry this Lexer is associated with, if any.
+	config   *Config
+	analyser func(text string) float32
+	trace    bool
+
+	mu             sync.Mutex
+	compiled       bool
+	rawRules       Rules
+	rules          map[string][]*CompiledRule
+	fetchRulesFunc func() (Rules, error)
+	compileOnce    sync.Once
+}
+
+func (r *RegexLexer) String() string {
+	return r.config.Name
+}
+
+// Rules in the Lexer.
+func (r *RegexLexer) Rules() (Rules, error) {
+	if err := r.needRules(); err != nil {
+		return nil, err
+	}
+	return r.rawRules, nil
+}
+
+// SetRegistry the lexer will use to lookup other lexers if necessary.
+func (r *RegexLexer) SetRegistry(registry *LexerRegistry) Lexer {
+	r.registry = registry
+	return r
+}
+
+// SetAnalyser sets the analyser function used to perform content inspection.
+func (r *RegexLexer) SetAnalyser(analyser func(text string) float32) Lexer {
+	r.analyser = analyser
+	return r
+}
+
+// AnalyseText scores how likely a fragment of text is to match this lexer, between 0.0 and 1.0.
+func (r *RegexLexer) AnalyseText(text string) float32 {
+	if r.analyser != nil {
+		return r.analyser(text)
+	}
+	return 0
+}
+
+// SetConfig replaces the Config for this Lexer.
+func (r *RegexLexer) SetConfig(config *Config) *RegexLexer {
+	r.config = config
+	return r
+}
+
+// Config returns the Config for this Lexer.
+func (r *RegexLexer) Config() *Config {
+	return r.config
+}
+
+// Regex compilation is deferred until the lexer is used. This is to avoid significant init() time costs.
+func (r *RegexLexer) maybeCompile() (err error) {
+	r.mu.Lock()
+	defer r.mu.Unlock()
+	if r.compiled {
+		return nil
+	}
+	for state, rules := range r.rules {
+		for i, rule := range rules {
+			if rule.Regexp == nil {
+				pattern := "(?:" + rule.Pattern + ")"
+				if rule.flags != "" {
+					pattern = "(?" + rule.flags + ")" + pattern
+				}
+				pattern = `\G` + pattern
+				rule.Regexp, err = regexp2.Compile(pattern, 0)
+				if err != nil {
+					return fmt.Errorf("failed to compile rule %s.%d: %s", state, i, err)
+				}
+				rule.Regexp.MatchTimeout = time.Millisecond * 250
+			}
+		}
+	}
+restart:
+	seen := map[LexerMutator]bool{}
+	for state := range r.rules {
+		for i := 0; i < len(r.rules[state]); i++ {
+			rule := r.rules[state][i]
+			if compile, ok := rule.Mutator.(LexerMutator); ok {
+				if seen[compile] {
+					return fmt.Errorf("saw mutator %T twice; this should not happen", compile)
+				}
+				seen[compile] = true
+				if err := compile.MutateLexer(r.rules, state, i); err != nil {
+					return err
+				}
+				// Process the rules again in case the mutator added/removed rules.
+				//
+				// This sounds bad, but shouldn't be significant in practice.
+				goto restart
+			}
+		}
+	}
+	r.compiled = true
+	return nil
+}
+
+func (r *RegexLexer) fetchRules() error {
+	rules, err := r.fetchRulesFunc()
+	if err != nil {
+		return fmt.Errorf("%s: failed to compile rules: %w", r.config.Name, err)
+	}
+	if _, ok := rules["root"]; !ok {
+		return fmt.Errorf("no \"root\" state")
+	}
+	compiledRules := map[string][]*CompiledRule{}
+	for state, rules := range rules {
+		compiledRules[state] = nil
+		for _, rule := range rules {
+			flags := ""
+			if !r.config.NotMultiline {
+				flags += "m"
+			}
+			if r.config.CaseInsensitive {
+				flags += "i"
+			}
+			if r.config.DotAll {
+				flags += "s"
+			}
+			compiledRules[state] = append(compiledRules[state], &CompiledRule{Rule: rule, flags: flags})
+		}
+	}
+
+	r.rawRules = rules
+	r.rules = compiledRules
+	return nil
+}
+
+func (r *RegexLexer) needRules() error {
+	var err error
+	if r.fetchRulesFunc != nil {
+		r.compileOnce.Do(func() {
+			err = r.fetchRules()
+		})
+	}
+	if err := r.maybeCompile(); err != nil {
+		return err
+	}
+	return err
+}
+
+// Tokenise text using lexer, returning an iterator.
+func (r *RegexLexer) Tokenise(options *TokeniseOptions, text string) (Iterator, error) {
+	err := r.needRules()
+	if err != nil {
+		return nil, err
+	}
+	if options == nil {
+		options = defaultOptions
+	}
+	if options.EnsureLF {
+		text = ensureLF(text)
+	}
+	newlineAdded := false
+	if !options.Nested && r.config.EnsureNL && !strings.HasSuffix(text, "\n") {
+		text += "\n"
+		newlineAdded = true
+	}
+	state := &LexerState{
+		Registry:       r.registry,
+		newlineAdded:   newlineAdded,
+		options:        options,
+		Lexer:          r,
+		Text:           []rune(text),
+		Stack:          []string{options.State},
+		Rules:          r.rules,
+		MutatorContext: map[interface{}]interface{}{},
+	}
+	return state.Iterator, nil
+}
+
+// MustRules is like Rules() but will panic on error.
+func (r *RegexLexer) MustRules() Rules {
+	rules, err := r.Rules()
+	if err != nil {
+		panic(err)
+	}
+	return rules
+}
+
+func matchRules(text []rune, pos int, rules []*CompiledRule) (int, *CompiledRule, []string, map[string]string) {
+	for i, rule := range rules {
+		match, err := rule.Regexp.FindRunesMatchStartingAt(text, pos)
+		if match != nil && err == nil && match.Index == pos {
+			groups := []string{}
+			namedGroups := make(map[string]string)
+			for _, g := range match.Groups() {
+				namedGroups[g.Name] = g.String()
+				groups = append(groups, g.String())
+			}
+			return i, rule, groups, namedGroups
+		}
+	}
+	return 0, &CompiledRule{}, nil, nil
+}
+
+// replace \r and \r\n with \n
+// same as strings.ReplaceAll but more efficient
+func ensureLF(text string) string {
+	buf := make([]byte, len(text))
+	var j int
+	for i := 0; i < len(text); i++ {
+		c := text[i]
+		if c == '\r' {
+			if i < len(text)-1 && text[i+1] == '\n' {
+				continue
+			}
+			c = '\n'
+		}
+		buf[j] = c
+		j++
+	}
+	return string(buf[:j])
+}
diff --git a/regexp_test.go b/regexp_test.go
new file mode 100644
index 0000000..6a22c20
--- /dev/null
+++ b/regexp_test.go
@@ -0,0 +1,194 @@
+package chroma
+
+import (
+	"testing"
+
+	"github.com/alecthomas/assert/v2"
+)
+
+func mustNewLexer(t *testing.T, config *Config, rules Rules) *RegexLexer { // nolint: forbidigo
+	lexer, err := NewLexer(config, func() Rules {
+		return rules
+	})
+	assert.NoError(t, err)
+	return lexer
+}
+
+func TestNewlineAtEndOfFile(t *testing.T) {
+	l := Coalesce(mustNewLexer(t, &Config{EnsureNL: true}, Rules{ // nolint: forbidigo
+		"root": {
+			{`(\w+)(\n)`, ByGroups(Keyword, Whitespace), nil},
+		},
+	}))
+	it, err := l.Tokenise(nil, `hello`)
+	assert.NoError(t, err)
+	assert.Equal(t, []Token{{Keyword, "hello"}, {Whitespace, "\n"}}, it.Tokens())
+
+	l = Coalesce(mustNewLexer(t, nil, Rules{ // nolint: forbidigo
+		"root": {
+			{`(\w+)(\n)`, ByGroups(Keyword, Whitespace), nil},
+		},
+	}))
+	it, err = l.Tokenise(nil, `hello`)
+	assert.NoError(t, err)
+	assert.Equal(t, []Token{{Error, "hello"}}, it.Tokens())
+}
+
+func TestMatchingAtStart(t *testing.T) {
+	l := Coalesce(mustNewLexer(t, &Config{}, Rules{ // nolint: forbidigo
+		"root": {
+			{`\s+`, Whitespace, nil},
+			{`^-`, Punctuation, Push("directive")},
+			{`->`, Operator, nil},
+		},
+		"directive": {
+			{"module", NameEntity, Pop(1)},
+		},
+	}))
+	it, err := l.Tokenise(nil, `-module ->`)
+	assert.NoError(t, err)
+	assert.Equal(t,
+		[]Token{{Punctuation, "-"}, {NameEntity, "module"}, {Whitespace, " "}, {Operator, "->"}},
+		it.Tokens())
+}
+
+func TestEnsureLFOption(t *testing.T) {
+	l := Coalesce(mustNewLexer(t, &Config{}, Rules{ // nolint: forbidigo
+		"root": {
+			{`(\w+)(\r?\n|\r)`, ByGroups(Keyword, Whitespace), nil},
+		},
+	}))
+	it, err := l.Tokenise(&TokeniseOptions{
+		State:    "root",
+		EnsureLF: true,
+	}, "hello\r\nworld\r")
+	assert.NoError(t, err)
+	assert.Equal(t, []Token{
+		{Keyword, "hello"},
+		{Whitespace, "\n"},
+		{Keyword, "world"},
+		{Whitespace, "\n"},
+	}, it.Tokens())
+
+	l = Coalesce(mustNewLexer(t, nil, Rules{ // nolint: forbidigo
+		"root": {
+			{`(\w+)(\r?\n|\r)`, ByGroups(Keyword, Whitespace), nil},
+		},
+	}))
+	it, err = l.Tokenise(&TokeniseOptions{
+		State:    "root",
+		EnsureLF: false,
+	}, "hello\r\nworld\r")
+	assert.NoError(t, err)
+	assert.Equal(t, []Token{
+		{Keyword, "hello"},
+		{Whitespace, "\r\n"},
+		{Keyword, "world"},
+		{Whitespace, "\r"},
+	}, it.Tokens())
+}
+
+func TestEnsureLFFunc(t *testing.T) {
+	tests := []struct{ in, out string }{
+		{in: "", out: ""},
+		{in: "abc", out: "abc"},
+		{in: "\r", out: "\n"},
+		{in: "a\r", out: "a\n"},
+		{in: "\rb", out: "\nb"},
+		{in: "a\rb", out: "a\nb"},
+		{in: "\r\n", out: "\n"},
+		{in: "a\r\n", out: "a\n"},
+		{in: "\r\nb", out: "\nb"},
+		{in: "a\r\nb", out: "a\nb"},
+		{in: "\r\r\r\n\r", out: "\n\n\n\n"},
+	}
+	for _, test := range tests {
+		out := ensureLF(test.in)
+		assert.Equal(t, out, test.out)
+	}
+}
+
+func TestByGroupNames(t *testing.T) {
+	l := Coalesce(mustNewLexer(t, nil, Rules{ // nolint: forbidigo
+		"root": {
+			{
+				`(?<key>\w+)(?<operator>=)(?<value>\w+)`,
+				ByGroupNames(map[string]Emitter{
+					`key`:      String,
+					`operator`: Operator,
+					`value`:    String,
+				}),
+				nil,
+			},
+		},
+	}))
+	it, err := l.Tokenise(nil, `abc=123`)
+	assert.NoError(t, err)
+	assert.Equal(t, []Token{{String, `abc`}, {Operator, `=`}, {String, `123`}}, it.Tokens())
+
+	l = Coalesce(mustNewLexer(t, nil, Rules{ // nolint: forbidigo
+		"root": {
+			{
+				`(?<key>\w+)(?<operator>=)(?<value>\w+)`,
+				ByGroupNames(map[string]Emitter{
+					`key`:   String,
+					`value`: String,
+				}),
+				nil,
+			},
+		},
+	}))
+	it, err = l.Tokenise(nil, `abc=123`)
+	assert.NoError(t, err)
+	assert.Equal(t, []Token{{String, `abc`}, {Error, `=`}, {String, `123`}}, it.Tokens())
+
+	l = Coalesce(mustNewLexer(t, nil, Rules{ // nolint: forbidigo
+		"root": {
+			{
+				`(?<key>\w+)=(?<value>\w+)`,
+				ByGroupNames(map[string]Emitter{
+					`key`:   String,
+					`value`: String,
+				}),
+				nil,
+			},
+		},
+	}))
+	it, err = l.Tokenise(nil, `abc=123`)
+	assert.NoError(t, err)
+	assert.Equal(t, []Token{{String, `abc123`}}, it.Tokens())
+
+	l = Coalesce(mustNewLexer(t, nil, Rules{ // nolint: forbidigo
+		"root": {
+			{
+				`(?<key>\w+)(?<op>=)(?<value>\w+)`,
+				ByGroupNames(map[string]Emitter{
+					`key`:      String,
+					`operator`: Operator,
+					`value`:    String,
+				}),
+				nil,
+			},
+		},
+	}))
+	it, err = l.Tokenise(nil, `abc=123`)
+	assert.NoError(t, err)
+	assert.Equal(t, []Token{{String, `abc`}, {Error, `=`}, {String, `123`}}, it.Tokens())
+
+	l = Coalesce(mustNewLexer(t, nil, Rules{ // nolint: forbidigo
+		"root": {
+			{
+				`\w+=\w+`,
+				ByGroupNames(map[string]Emitter{
+					`key`:      String,
+					`operator`: Operator,
+					`value`:    String,
+				}),
+				nil,
+			},
+		},
+	}))
+	it, err = l.Tokenise(nil, `abc=123`)
+	assert.NoError(t, err)
+	assert.Equal(t, []Token{{Error, `abc=123`}}, it.Tokens())
+}
diff --git a/registry.go b/registry.go
new file mode 100644
index 0000000..4742e8c
--- /dev/null
+++ b/registry.go
@@ -0,0 +1,210 @@
+package chroma
+
+import (
+	"path/filepath"
+	"sort"
+	"strings"
+)
+
+var (
+	ignoredSuffixes = [...]string{
+		// Editor backups
+		"~", ".bak", ".old", ".orig",
+		// Debian and derivatives apt/dpkg/ucf backups
+		".dpkg-dist", ".dpkg-old", ".ucf-dist", ".ucf-new", ".ucf-old",
+		// Red Hat and derivatives rpm backups
+		".rpmnew", ".rpmorig", ".rpmsave",
+		// Build system input/template files
+		".in",
+	}
+)
+
+// LexerRegistry is a registry of Lexers.
+type LexerRegistry struct {
+	Lexers  Lexers
+	byName  map[string]Lexer
+	byAlias map[string]Lexer
+}
+
+// NewLexerRegistry creates a new LexerRegistry of Lexers.
+func NewLexerRegistry() *LexerRegistry {
+	return &LexerRegistry{
+		byName:  map[string]Lexer{},
+		byAlias: map[string]Lexer{},
+	}
+}
+
+// Names of all lexers, optionally including aliases.
+func (l *LexerRegistry) Names(withAliases bool) []string {
+	out := []string{}
+	for _, lexer := range l.Lexers {
+		config := lexer.Config()
+		out = append(out, config.Name)
+		if withAliases {
+			out = append(out, config.Aliases...)
+		}
+	}
+	sort.Strings(out)
+	return out
+}
+
+// Get a Lexer by name, alias or file extension.
+func (l *LexerRegistry) Get(name string) Lexer {
+	if lexer := l.byName[name]; lexer != nil {
+		return lexer
+	}
+	if lexer := l.byAlias[name]; lexer != nil {
+		return lexer
+	}
+	if lexer := l.byName[strings.ToLower(name)]; lexer != nil {
+		return lexer
+	}
+	if lexer := l.byAlias[strings.ToLower(name)]; lexer != nil {
+		return lexer
+	}
+
+	candidates := PrioritisedLexers{}
+	// Try file extension.
+	if lexer := l.Match("filename." + name); lexer != nil {
+		candidates = append(candidates, lexer)
+	}
+	// Try exact filename.
+	if lexer := l.Match(name); lexer != nil {
+		candidates = append(candidates, lexer)
+	}
+	if len(candidates) == 0 {
+		return nil
+	}
+	sort.Sort(candidates)
+	return candidates[0]
+}
+
+// MatchMimeType attempts to find a lexer for the given MIME type.
+func (l *LexerRegistry) MatchMimeType(mimeType string) Lexer {
+	matched := PrioritisedLexers{}
+	for _, l := range l.Lexers {
+		for _, lmt := range l.Config().MimeTypes {
+			if mimeType == lmt {
+				matched = append(matched, l)
+			}
+		}
+	}
+	if len(matched) != 0 {
+		sort.Sort(matched)
+		return matched[0]
+	}
+	return nil
+}
+
+// Match returns the first lexer matching filename.
+//
+// Note that this iterates over all file patterns in all lexers, so is not fast.
+func (l *LexerRegistry) Match(filename string) Lexer {
+	filename = filepath.Base(filename)
+	matched := PrioritisedLexers{}
+	// First, try primary filename matches.
+	for _, lexer := range l.Lexers {
+		config := lexer.Config()
+		for _, glob := range config.Filenames {
+			ok, err := filepath.Match(glob, filename)
+			if err != nil { // nolint
+				panic(err)
+			} else if ok {
+				matched = append(matched, lexer)
+			} else {
+				for _, suf := range &ignoredSuffixes {
+					ok, err := filepath.Match(glob+suf, filename)
+					if err != nil {
+						panic(err)
+					} else if ok {
+						matched = append(matched, lexer)
+						break
+					}
+				}
+			}
+		}
+	}
+	if len(matched) > 0 {
+		sort.Sort(matched)
+		return matched[0]
+	}
+	matched = nil
+	// Next, try filename aliases.
+	for _, lexer := range l.Lexers {
+		config := lexer.Config()
+		for _, glob := range config.AliasFilenames {
+			ok, err := filepath.Match(glob, filename)
+			if err != nil { // nolint
+				panic(err)
+			} else if ok {
+				matched = append(matched, lexer)
+			} else {
+				for _, suf := range &ignoredSuffixes {
+					ok, err := filepath.Match(glob+suf, filename)
+					if err != nil {
+						panic(err)
+					} else if ok {
+						matched = append(matched, lexer)
+						break
+					}
+				}
+			}
+		}
+	}
+	if len(matched) > 0 {
+		sort.Sort(matched)
+		return matched[0]
+	}
+	return nil
+}
+
+// Analyse text content and return the "best" lexer..
+func (l *LexerRegistry) Analyse(text string) Lexer {
+	var picked Lexer
+	highest := float32(0.0)
+	for _, lexer := range l.Lexers {
+		if analyser, ok := lexer.(Analyser); ok {
+			weight := analyser.AnalyseText(text)
+			if weight > highest {
+				picked = lexer
+				highest = weight
+			}
+		}
+	}
+	return picked
+}
+
+// Register a Lexer with the LexerRegistry. If the lexer is already registered
+// it will be replaced.
+func (l *LexerRegistry) Register(lexer Lexer) Lexer {
+	lexer.SetRegistry(l)
+	config := lexer.Config()
+
+	l.byName[config.Name] = lexer
+	l.byName[strings.ToLower(config.Name)] = lexer
+
+	for _, alias := range config.Aliases {
+		l.byAlias[alias] = lexer
+		l.byAlias[strings.ToLower(alias)] = lexer
+	}
+
+	l.Lexers = add(l.Lexers, lexer)
+
+	return lexer
+}
+
+// add adds a lexer to a slice of lexers if it doesn't already exist, or if found will replace it.
+func add(lexers Lexers, lexer Lexer) Lexers {
+	for i, val := range lexers {
+		if val == nil {
+			continue
+		}
+
+		if val.Config().Name == lexer.Config().Name {
+			lexers[i] = lexer
+			return lexers
+		}
+	}
+
+	return append(lexers, lexer)
+}
diff --git a/remap.go b/remap.go
new file mode 100644
index 0000000..bcf5e66
--- /dev/null
+++ b/remap.go
@@ -0,0 +1,94 @@
+package chroma
+
+type remappingLexer struct {
+	lexer  Lexer
+	mapper func(Token) []Token
+}
+
+// RemappingLexer remaps a token to a set of, potentially empty, tokens.
+func RemappingLexer(lexer Lexer, mapper func(Token) []Token) Lexer {
+	return &remappingLexer{lexer, mapper}
+}
+
+func (r *remappingLexer) AnalyseText(text string) float32 {
+	return r.lexer.AnalyseText(text)
+}
+
+func (r *remappingLexer) SetAnalyser(analyser func(text string) float32) Lexer {
+	r.lexer.SetAnalyser(analyser)
+	return r
+}
+
+func (r *remappingLexer) SetRegistry(registry *LexerRegistry) Lexer {
+	r.lexer.SetRegistry(registry)
+	return r
+}
+
+func (r *remappingLexer) Config() *Config {
+	return r.lexer.Config()
+}
+
+func (r *remappingLexer) Tokenise(options *TokeniseOptions, text string) (Iterator, error) {
+	it, err := r.lexer.Tokenise(options, text)
+	if err != nil {
+		return nil, err
+	}
+	var buffer []Token
+	return func() Token {
+		for {
+			if len(buffer) > 0 {
+				t := buffer[0]
+				buffer = buffer[1:]
+				return t
+			}
+			t := it()
+			if t == EOF {
+				return t
+			}
+			buffer = r.mapper(t)
+		}
+	}, nil
+}
+
+// TypeMapping defines type maps for the TypeRemappingLexer.
+type TypeMapping []struct {
+	From, To TokenType
+	Words    []string
+}
+
+// TypeRemappingLexer remaps types of tokens coming from a parent Lexer.
+//
+// eg. Map "defvaralias" tokens of type NameVariable to NameFunction:
+//
+//	mapping := TypeMapping{
+//		{NameVariable, NameFunction, []string{"defvaralias"},
+//	}
+//	lexer = TypeRemappingLexer(lexer, mapping)
+func TypeRemappingLexer(lexer Lexer, mapping TypeMapping) Lexer {
+	// Lookup table for fast remapping.
+	lut := map[TokenType]map[string]TokenType{}
+	for _, rt := range mapping {
+		km, ok := lut[rt.From]
+		if !ok {
+			km = map[string]TokenType{}
+			lut[rt.From] = km
+		}
+		if len(rt.Words) == 0 {
+			km[""] = rt.To
+		} else {
+			for _, k := range rt.Words {
+				km[k] = rt.To
+			}
+		}
+	}
+	return RemappingLexer(lexer, func(t Token) []Token {
+		if k, ok := lut[t.Type]; ok {
+			if tt, ok := k[t.Value]; ok {
+				t.Type = tt
+			} else if tt, ok := k[""]; ok {
+				t.Type = tt
+			}
+		}
+		return []Token{t}
+	})
+}
diff --git a/remap_test.go b/remap_test.go
new file mode 100644
index 0000000..80d74ef
--- /dev/null
+++ b/remap_test.go
@@ -0,0 +1,29 @@
+package chroma
+
+import (
+	"testing"
+
+	"github.com/alecthomas/assert/v2"
+)
+
+func TestRemappingLexer(t *testing.T) {
+	var lexer Lexer = mustNewLexer(t, nil, Rules{ // nolint: forbidigo
+		"root": {
+			{`\s+`, Whitespace, nil},
+			{`\w+`, Name, nil},
+		},
+	})
+	lexer = TypeRemappingLexer(lexer, TypeMapping{
+		{Name, Keyword, []string{"if", "else"}},
+	})
+
+	it, err := lexer.Tokenise(nil, `if true then print else end`)
+	assert.NoError(t, err)
+	expected := []Token{
+		{Keyword, "if"}, {TextWhitespace, " "}, {Name, "true"}, {TextWhitespace, " "}, {Name, "then"},
+		{TextWhitespace, " "}, {Name, "print"}, {TextWhitespace, " "}, {Keyword, "else"},
+		{TextWhitespace, " "}, {Name, "end"},
+	}
+	actual := it.Tokens()
+	assert.Equal(t, expected, actual)
+}
diff --git a/serialise.go b/serialise.go
new file mode 100644
index 0000000..645a5fa
--- /dev/null
+++ b/serialise.go
@@ -0,0 +1,479 @@
+package chroma
+
+import (
+	"compress/gzip"
+	"encoding/xml"
+	"errors"
+	"fmt"
+	"io"
+	"io/fs"
+	"math"
+	"path/filepath"
+	"reflect"
+	"regexp"
+	"strings"
+
+	"github.com/dlclark/regexp2"
+)
+
+// Serialisation of Chroma rules to XML. The format is:
+//
+//	<rules>
+//	  <state name="$STATE">
+//	    <rule [pattern="$PATTERN"]>
+//	      [<$EMITTER ...>]
+//	      [<$MUTATOR ...>]
+//	    </rule>
+//	  </state>
+//	</rules>
+//
+// eg. Include("String") would become:
+//
+//	<rule>
+//	  <include state="String" />
+//	</rule>
+//
+//	[null, null, {"kind": "include", "state": "String"}]
+//
+// eg. Rule{`\d+`, Text, nil} would become:
+//
+//	<rule pattern="\\d+">
+//	  <token type="Text"/>
+//	</rule>
+//
+// eg. Rule{`"`, String, Push("String")}
+//
+//	<rule pattern="\"">
+//	  <token type="String" />
+//	  <push state="String" />
+//	</rule>
+//
+// eg. Rule{`(\w+)(\n)`, ByGroups(Keyword, Whitespace), nil},
+//
+//	<rule pattern="(\\w+)(\\n)">
+//	  <bygroups token="Keyword" token="Whitespace" />
+//	  <push state="String" />
+//	</rule>
+var (
+	// ErrNotSerialisable is returned if a lexer contains Rules that cannot be serialised.
+	ErrNotSerialisable = fmt.Errorf("not serialisable")
+	emitterTemplates   = func() map[string]SerialisableEmitter {
+		out := map[string]SerialisableEmitter{}
+		for _, emitter := range []SerialisableEmitter{
+			&byGroupsEmitter{},
+			&usingSelfEmitter{},
+			TokenType(0),
+			&usingEmitter{},
+			&usingByGroup{},
+		} {
+			out[emitter.EmitterKind()] = emitter
+		}
+		return out
+	}()
+	mutatorTemplates = func() map[string]SerialisableMutator {
+		out := map[string]SerialisableMutator{}
+		for _, mutator := range []SerialisableMutator{
+			&includeMutator{},
+			&combinedMutator{},
+			&multiMutator{},
+			&pushMutator{},
+			&popMutator{},
+		} {
+			out[mutator.MutatorKind()] = mutator
+		}
+		return out
+	}()
+)
+
+// fastUnmarshalConfig unmarshals only the Config from a serialised lexer.
+func fastUnmarshalConfig(from fs.FS, path string) (*Config, error) {
+	r, err := from.Open(path)
+	if err != nil {
+		return nil, err
+	}
+	defer r.Close()
+	dec := xml.NewDecoder(r)
+	for {
+		token, err := dec.Token()
+		if err != nil {
+			if errors.Is(err, io.EOF) {
+				return nil, fmt.Errorf("could not find <config> element")
+			}
+			return nil, err
+		}
+		switch se := token.(type) {
+		case xml.StartElement:
+			if se.Name.Local != "config" {
+				break
+			}
+
+			var config Config
+			err = dec.DecodeElement(&config, &se)
+			if err != nil {
+				return nil, fmt.Errorf("%s: %w", path, err)
+			}
+			return &config, nil
+		}
+	}
+}
+
+// MustNewXMLLexer constructs a new RegexLexer from an XML file or panics.
+func MustNewXMLLexer(from fs.FS, path string) *RegexLexer {
+	lex, err := NewXMLLexer(from, path)
+	if err != nil {
+		panic(err)
+	}
+	return lex
+}
+
+// NewXMLLexer creates a new RegexLexer from a serialised RegexLexer.
+func NewXMLLexer(from fs.FS, path string) (*RegexLexer, error) {
+	config, err := fastUnmarshalConfig(from, path)
+	if err != nil {
+		return nil, err
+	}
+
+	for _, glob := range append(config.Filenames, config.AliasFilenames...) {
+		_, err := filepath.Match(glob, "")
+		if err != nil {
+			return nil, fmt.Errorf("%s: %q is not a valid glob: %w", config.Name, glob, err)
+		}
+	}
+
+	var analyserFn func(string) float32
+
+	if config.Analyse != nil {
+		type regexAnalyse struct {
+			re    *regexp2.Regexp
+			score float32
+		}
+
+		regexAnalysers := make([]regexAnalyse, 0, len(config.Analyse.Regexes))
+
+		for _, ra := range config.Analyse.Regexes {
+			re, err := regexp2.Compile(ra.Pattern, regexp2.None)
+			if err != nil {
+				return nil, fmt.Errorf("%s: %q is not a valid analyser regex: %w", config.Name, ra.Pattern, err)
+			}
+
+			regexAnalysers = append(regexAnalysers, regexAnalyse{re, ra.Score})
+		}
+
+		analyserFn = func(text string) float32 {
+			var score float32
+
+			for _, ra := range regexAnalysers {
+				ok, err := ra.re.MatchString(text)
+				if err != nil {
+					return 0
+				}
+
+				if ok && config.Analyse.First {
+					return float32(math.Min(float64(ra.score), 1.0))
+				}
+
+				if ok {
+					score += ra.score
+				}
+			}
+
+			return float32(math.Min(float64(score), 1.0))
+		}
+	}
+
+	return &RegexLexer{
+		config:   config,
+		analyser: analyserFn,
+		fetchRulesFunc: func() (Rules, error) {
+			var lexer struct {
+				Config
+				Rules Rules `xml:"rules"`
+			}
+			// Try to open .xml fallback to .xml.gz
+			fr, err := from.Open(path)
+			if err != nil {
+				if errors.Is(err, fs.ErrNotExist) {
+					path += ".gz"
+					fr, err = from.Open(path)
+					if err != nil {
+						return nil, err
+					}
+				} else {
+					return nil, err
+				}
+			}
+			defer fr.Close()
+			var r io.Reader = fr
+			if strings.HasSuffix(path, ".gz") {
+				r, err = gzip.NewReader(r)
+				if err != nil {
+					return nil, fmt.Errorf("%s: %w", path, err)
+				}
+			}
+			err = xml.NewDecoder(r).Decode(&lexer)
+			if err != nil {
+				return nil, fmt.Errorf("%s: %w", path, err)
+			}
+			return lexer.Rules, nil
+		},
+	}, nil
+}
+
+// Marshal a RegexLexer to XML.
+func Marshal(l *RegexLexer) ([]byte, error) {
+	type lexer struct {
+		Config Config `xml:"config"`
+		Rules  Rules  `xml:"rules"`
+	}
+
+	rules, err := l.Rules()
+	if err != nil {
+		return nil, err
+	}
+	root := &lexer{
+		Config: *l.Config(),
+		Rules:  rules,
+	}
+	data, err := xml.MarshalIndent(root, "", "  ")
+	if err != nil {
+		return nil, err
+	}
+	re := regexp.MustCompile(`></[a-zA-Z]+>`)
+	data = re.ReplaceAll(data, []byte(`/>`))
+	return data, nil
+}
+
+// Unmarshal a RegexLexer from XML.
+func Unmarshal(data []byte) (*RegexLexer, error) {
+	type lexer struct {
+		Config Config `xml:"config"`
+		Rules  Rules  `xml:"rules"`
+	}
+	root := &lexer{}
+	err := xml.Unmarshal(data, root)
+	if err != nil {
+		return nil, fmt.Errorf("invalid Lexer XML: %w", err)
+	}
+	lex, err := NewLexer(&root.Config, func() Rules { return root.Rules })
+	if err != nil {
+		return nil, err
+	}
+	return lex, nil
+}
+
+func marshalMutator(e *xml.Encoder, mutator Mutator) error {
+	if mutator == nil {
+		return nil
+	}
+	smutator, ok := mutator.(SerialisableMutator)
+	if !ok {
+		return fmt.Errorf("unsupported mutator: %w", ErrNotSerialisable)
+	}
+	return e.EncodeElement(mutator, xml.StartElement{Name: xml.Name{Local: smutator.MutatorKind()}})
+}
+
+func unmarshalMutator(d *xml.Decoder, start xml.StartElement) (Mutator, error) {
+	kind := start.Name.Local
+	mutator, ok := mutatorTemplates[kind]
+	if !ok {
+		return nil, fmt.Errorf("unknown mutator %q: %w", kind, ErrNotSerialisable)
+	}
+	value, target := newFromTemplate(mutator)
+	if err := d.DecodeElement(target, &start); err != nil {
+		return nil, err
+	}
+	return value().(SerialisableMutator), nil
+}
+
+func marshalEmitter(e *xml.Encoder, emitter Emitter) error {
+	if emitter == nil {
+		return nil
+	}
+	semitter, ok := emitter.(SerialisableEmitter)
+	if !ok {
+		return fmt.Errorf("unsupported emitter %T: %w", emitter, ErrNotSerialisable)
+	}
+	return e.EncodeElement(emitter, xml.StartElement{
+		Name: xml.Name{Local: semitter.EmitterKind()},
+	})
+}
+
+func unmarshalEmitter(d *xml.Decoder, start xml.StartElement) (Emitter, error) {
+	kind := start.Name.Local
+	mutator, ok := emitterTemplates[kind]
+	if !ok {
+		return nil, fmt.Errorf("unknown emitter %q: %w", kind, ErrNotSerialisable)
+	}
+	value, target := newFromTemplate(mutator)
+	if err := d.DecodeElement(target, &start); err != nil {
+		return nil, err
+	}
+	return value().(SerialisableEmitter), nil
+}
+
+func (r Rule) MarshalXML(e *xml.Encoder, _ xml.StartElement) error {
+	start := xml.StartElement{
+		Name: xml.Name{Local: "rule"},
+	}
+	if r.Pattern != "" {
+		start.Attr = append(start.Attr, xml.Attr{
+			Name:  xml.Name{Local: "pattern"},
+			Value: r.Pattern,
+		})
+	}
+	if err := e.EncodeToken(start); err != nil {
+		return err
+	}
+	if err := marshalEmitter(e, r.Type); err != nil {
+		return err
+	}
+	if err := marshalMutator(e, r.Mutator); err != nil {
+		return err
+	}
+	return e.EncodeToken(xml.EndElement{Name: start.Name})
+}
+
+func (r *Rule) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
+	for _, attr := range start.Attr {
+		if attr.Name.Local == "pattern" {
+			r.Pattern = attr.Value
+			break
+		}
+	}
+	for {
+		token, err := d.Token()
+		if err != nil {
+			return err
+		}
+		switch token := token.(type) {
+		case xml.StartElement:
+			mutator, err := unmarshalMutator(d, token)
+			if err != nil && !errors.Is(err, ErrNotSerialisable) {
+				return err
+			} else if err == nil {
+				if r.Mutator != nil {
+					return fmt.Errorf("duplicate mutator")
+				}
+				r.Mutator = mutator
+				continue
+			}
+			emitter, err := unmarshalEmitter(d, token)
+			if err != nil && !errors.Is(err, ErrNotSerialisable) { // nolint: gocritic
+				return err
+			} else if err == nil {
+				if r.Type != nil {
+					return fmt.Errorf("duplicate emitter")
+				}
+				r.Type = emitter
+				continue
+			} else {
+				return err
+			}
+
+		case xml.EndElement:
+			return nil
+		}
+	}
+}
+
+type xmlRuleState struct {
+	Name  string `xml:"name,attr"`
+	Rules []Rule `xml:"rule"`
+}
+
+type xmlRules struct {
+	States []xmlRuleState `xml:"state"`
+}
+
+func (r Rules) MarshalXML(e *xml.Encoder, _ xml.StartElement) error {
+	xr := xmlRules{}
+	for state, rules := range r {
+		xr.States = append(xr.States, xmlRuleState{
+			Name:  state,
+			Rules: rules,
+		})
+	}
+	return e.EncodeElement(xr, xml.StartElement{Name: xml.Name{Local: "rules"}})
+}
+
+func (r *Rules) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
+	xr := xmlRules{}
+	if err := d.DecodeElement(&xr, &start); err != nil {
+		return err
+	}
+	if *r == nil {
+		*r = Rules{}
+	}
+	for _, state := range xr.States {
+		(*r)[state.Name] = state.Rules
+	}
+	return nil
+}
+
+type xmlTokenType struct {
+	Type string `xml:"type,attr"`
+}
+
+func (t *TokenType) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
+	el := xmlTokenType{}
+	if err := d.DecodeElement(&el, &start); err != nil {
+		return err
+	}
+	tt, err := TokenTypeString(el.Type)
+	if err != nil {
+		return err
+	}
+	*t = tt
+	return nil
+}
+
+func (t TokenType) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
+	start.Attr = append(start.Attr, xml.Attr{Name: xml.Name{Local: "type"}, Value: t.String()})
+	if err := e.EncodeToken(start); err != nil {
+		return err
+	}
+	return e.EncodeToken(xml.EndElement{Name: start.Name})
+}
+
+// This hijinks is a bit unfortunate but without it we can't deserialise into TokenType.
+func newFromTemplate(template interface{}) (value func() interface{}, target interface{}) {
+	t := reflect.TypeOf(template)
+	if t.Kind() == reflect.Ptr {
+		v := reflect.New(t.Elem())
+		return v.Interface, v.Interface()
+	}
+	v := reflect.New(t)
+	return func() interface{} { return v.Elem().Interface() }, v.Interface()
+}
+
+func (b *Emitters) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
+	for {
+		token, err := d.Token()
+		if err != nil {
+			return err
+		}
+		switch token := token.(type) {
+		case xml.StartElement:
+			emitter, err := unmarshalEmitter(d, token)
+			if err != nil {
+				return err
+			}
+			*b = append(*b, emitter)
+
+		case xml.EndElement:
+			return nil
+		}
+	}
+}
+
+func (b Emitters) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
+	if err := e.EncodeToken(start); err != nil {
+		return err
+	}
+	for _, m := range b {
+		if err := marshalEmitter(e, m); err != nil {
+			return err
+		}
+	}
+	return e.EncodeToken(xml.EndElement{Name: start.Name})
+}
diff --git a/serialise_test.go b/serialise_test.go
new file mode 100644
index 0000000..9177b54
--- /dev/null
+++ b/serialise_test.go
@@ -0,0 +1,166 @@
+package chroma
+
+import (
+	"bytes"
+	"compress/gzip"
+	"encoding/xml"
+	"fmt"
+	"regexp"
+	"testing"
+
+	"github.com/alecthomas/assert/v2"
+)
+
+func TestEmitterSerialisationRoundTrip(t *testing.T) {
+	tests := []struct {
+		name    string
+		emitter Emitter
+	}{
+		{"ByGroups", ByGroups(Name, Using("Go"))},
+		{"UsingSelf", UsingSelf("root")},
+		{"Using", Using("Go")},
+		{"UsingByGroup", UsingByGroup(1, 2, Name)},
+		{"TokenType", Name},
+	}
+	for _, test := range tests {
+		// nolint: scopelint
+		t.Run(test.name, func(t *testing.T) {
+			data, err := xml.Marshal(test.emitter)
+			assert.NoError(t, err)
+			t.Logf("%s", data)
+			value, target := newFromTemplate(test.emitter)
+			err = xml.Unmarshal(data, target)
+			assert.NoError(t, err)
+			assert.Equal(t, test.emitter, value().(Emitter))
+		})
+	}
+}
+
+func TestMutatorSerialisationRoundTrip(t *testing.T) {
+	tests := []struct {
+		name    string
+		mutator Mutator
+	}{
+		{"Include", Include("string").Mutator},
+		{"Combined", Combined("a", "b", "c")},
+		{"Multi", Mutators(Include("string").Mutator, Push("quote"))},
+		{"Push", Push("include")},
+		{"Pop", Pop(1)},
+	}
+	for _, test := range tests {
+		// nolint: scopelint
+		t.Run(test.name, func(t *testing.T) {
+			data, err := xml.Marshal(test.mutator)
+			assert.NoError(t, err)
+			t.Logf("%s", data)
+			value, target := newFromTemplate(test.mutator)
+			err = xml.Unmarshal(data, target)
+			assert.NoError(t, err)
+			assert.Equal(t, test.mutator, value().(Mutator))
+		})
+	}
+}
+
+func TestMarshal(t *testing.T) {
+	actual := MustNewLexer(&Config{
+		Name:      "PkgConfig",
+		Aliases:   []string{"pkgconfig"},
+		Filenames: []string{"*.pc"},
+	}, func() Rules {
+		return Rules{
+			"root": {
+				{`#.*$`, CommentSingle, nil},
+				{`^(\w+)(=)`, ByGroups(NameAttribute, Operator), nil},
+				{`^([\w.]+)(:)`, ByGroups(NameTag, Punctuation), Push("spvalue")},
+				Include("interp"),
+				{`[^${}#=:\n.]+`, Text, nil},
+				{`.`, Text, nil},
+			},
+			"interp": {
+				{`\$\$`, Text, nil},
+				{`\$\{`, LiteralStringInterpol, Push("curly")},
+			},
+			"curly": {
+				{`\}`, LiteralStringInterpol, Pop(1)},
+				{`\w+`, NameAttribute, nil},
+			},
+			"spvalue": {
+				Include("interp"),
+				{`#.*$`, CommentSingle, Pop(1)},
+				{`\n`, Text, Pop(1)},
+				{`[^${}#\n]+`, Text, nil},
+				{`.`, Text, nil},
+			},
+		}
+	})
+	data, err := Marshal(actual)
+	assert.NoError(t, err)
+	expected, err := Unmarshal(data)
+	assert.NoError(t, err)
+	assert.Equal(t, expected.Config(), actual.Config())
+	assert.Equal(t, mustRules(t, expected), mustRules(t, actual))
+}
+
+func mustRules(t testing.TB, r *RegexLexer) Rules {
+	t.Helper()
+	rules, err := r.Rules()
+	assert.NoError(t, err)
+	return rules
+}
+
+func TestRuleSerialisation(t *testing.T) {
+	tests := []Rule{
+		Include("String"),
+		{`\d+`, Text, nil},
+		{`"`, String, Push("String")},
+	}
+	for _, test := range tests {
+		data, err := xml.Marshal(test)
+		assert.NoError(t, err)
+		t.Log(string(data))
+		actual := Rule{}
+		err = xml.Unmarshal(data, &actual)
+		assert.NoError(t, err)
+		assert.Equal(t, test, actual)
+	}
+}
+
+func TestRulesSerialisation(t *testing.T) {
+	expected := Rules{
+		"root": {
+			{`#.*$`, CommentSingle, nil},
+			{`^(\w+)(=)`, ByGroups(NameAttribute, Operator), nil},
+			{`^([\w.]+)(:)`, ByGroups(NameTag, Punctuation), Push("spvalue")},
+			Include("interp"),
+			{`[^${}#=:\n.]+`, Text, nil},
+			{`.`, Text, nil},
+		},
+		"interp": {
+			{`\$\$`, Text, nil},
+			{`\$\{`, LiteralStringInterpol, Push("curly")},
+		},
+		"curly": {
+			{`\}`, LiteralStringInterpol, Pop(1)},
+			{`\w+`, NameAttribute, nil},
+		},
+		"spvalue": {
+			Include("interp"),
+			{`#.*$`, CommentSingle, Pop(1)},
+			{`\n`, Text, Pop(1)},
+			{`[^${}#\n]+`, Text, nil},
+			{`.`, Text, nil},
+		},
+	}
+	data, err := xml.MarshalIndent(expected, "  ", "  ")
+	assert.NoError(t, err)
+	re := regexp.MustCompile(`></[a-zA-Z]+>`)
+	data = re.ReplaceAll(data, []byte(`/>`))
+	b := &bytes.Buffer{}
+	w := gzip.NewWriter(b)
+	fmt.Fprintln(w, string(data))
+	w.Close()
+	actual := Rules{}
+	err = xml.Unmarshal(data, &actual)
+	assert.NoError(t, err)
+	assert.Equal(t, expected, actual)
+}
diff --git a/style.go b/style.go
new file mode 100644
index 0000000..8cadaec
--- /dev/null
+++ b/style.go
@@ -0,0 +1,493 @@
+package chroma
+
+import (
+	"encoding/xml"
+	"fmt"
+	"io"
+	"sort"
+	"strings"
+)
+
+// Trilean value for StyleEntry value inheritance.
+type Trilean uint8
+
+// Trilean states.
+const (
+	Pass Trilean = iota
+	Yes
+	No
+)
+
+func (t Trilean) String() string {
+	switch t {
+	case Yes:
+		return "Yes"
+	case No:
+		return "No"
+	default:
+		return "Pass"
+	}
+}
+
+// Prefix returns s with "no" as a prefix if Trilean is no.
+func (t Trilean) Prefix(s string) string {
+	if t == Yes {
+		return s
+	} else if t == No {
+		return "no" + s
+	}
+	return ""
+}
+
+// A StyleEntry in the Style map.
+type StyleEntry struct {
+	// Hex colours.
+	Colour     Colour
+	Background Colour
+	Border     Colour
+
+	Bold      Trilean
+	Italic    Trilean
+	Underline Trilean
+	NoInherit bool
+}
+
+func (s StyleEntry) MarshalText() ([]byte, error) {
+	return []byte(s.String()), nil
+}
+
+func (s StyleEntry) String() string {
+	out := []string{}
+	if s.Bold != Pass {
+		out = append(out, s.Bold.Prefix("bold"))
+	}
+	if s.Italic != Pass {
+		out = append(out, s.Italic.Prefix("italic"))
+	}
+	if s.Underline != Pass {
+		out = append(out, s.Underline.Prefix("underline"))
+	}
+	if s.NoInherit {
+		out = append(out, "noinherit")
+	}
+	if s.Colour.IsSet() {
+		out = append(out, s.Colour.String())
+	}
+	if s.Background.IsSet() {
+		out = append(out, "bg:"+s.Background.String())
+	}
+	if s.Border.IsSet() {
+		out = append(out, "border:"+s.Border.String())
+	}
+	return strings.Join(out, " ")
+}
+
+// Sub subtracts e from s where elements match.
+func (s StyleEntry) Sub(e StyleEntry) StyleEntry {
+	out := StyleEntry{}
+	if e.Colour != s.Colour {
+		out.Colour = s.Colour
+	}
+	if e.Background != s.Background {
+		out.Background = s.Background
+	}
+	if e.Bold != s.Bold {
+		out.Bold = s.Bold
+	}
+	if e.Italic != s.Italic {
+		out.Italic = s.Italic
+	}
+	if e.Underline != s.Underline {
+		out.Underline = s.Underline
+	}
+	if e.Border != s.Border {
+		out.Border = s.Border
+	}
+	return out
+}
+
+// Inherit styles from ancestors.
+//
+// Ancestors should be provided from oldest to newest.
+func (s StyleEntry) Inherit(ancestors ...StyleEntry) StyleEntry {
+	out := s
+	for i := len(ancestors) - 1; i >= 0; i-- {
+		if out.NoInherit {
+			return out
+		}
+		ancestor := ancestors[i]
+		if !out.Colour.IsSet() {
+			out.Colour = ancestor.Colour
+		}
+		if !out.Background.IsSet() {
+			out.Background = ancestor.Background
+		}
+		if !out.Border.IsSet() {
+			out.Border = ancestor.Border
+		}
+		if out.Bold == Pass {
+			out.Bold = ancestor.Bold
+		}
+		if out.Italic == Pass {
+			out.Italic = ancestor.Italic
+		}
+		if out.Underline == Pass {
+			out.Underline = ancestor.Underline
+		}
+	}
+	return out
+}
+
+func (s StyleEntry) IsZero() bool {
+	return s.Colour == 0 && s.Background == 0 && s.Border == 0 && s.Bold == Pass && s.Italic == Pass &&
+		s.Underline == Pass && !s.NoInherit
+}
+
+// A StyleBuilder is a mutable structure for building styles.
+//
+// Once built, a Style is immutable.
+type StyleBuilder struct {
+	entries map[TokenType]string
+	name    string
+	theme   string
+	parent  *Style
+}
+
+func NewStyleBuilder(name string, theme string) *StyleBuilder {
+	return &StyleBuilder{name: name, theme: theme, entries: map[TokenType]string{}}
+}
+
+func (s *StyleBuilder) AddAll(entries StyleEntries) *StyleBuilder {
+	for ttype, entry := range entries {
+		s.entries[ttype] = entry
+	}
+	return s
+}
+
+func (s *StyleBuilder) Get(ttype TokenType) StyleEntry {
+	// This is less than ideal, but it's the price for not having to check errors on each Add().
+	entry, _ := ParseStyleEntry(s.entries[ttype])
+	if s.parent != nil {
+		entry = entry.Inherit(s.parent.Get(ttype))
+	}
+	return entry
+}
+
+// Add an entry to the Style map.
+//
+// See http://pygments.org/docs/styles/#style-rules for details.
+func (s *StyleBuilder) Add(ttype TokenType, entry string) *StyleBuilder { // nolint: gocyclo
+	s.entries[ttype] = entry
+	return s
+}
+
+func (s *StyleBuilder) AddEntry(ttype TokenType, entry StyleEntry) *StyleBuilder {
+	s.entries[ttype] = entry.String()
+	return s
+}
+
+// Transform passes each style entry currently defined in the builder to the supplied
+// function and saves the returned value. This can be used to adjust a style's colours;
+// see Colour's ClampBrightness function, for example.
+func (s *StyleBuilder) Transform(transform func(StyleEntry) StyleEntry) *StyleBuilder {
+	types := make(map[TokenType]struct{})
+	for tt := range s.entries {
+		types[tt] = struct{}{}
+	}
+	if s.parent != nil {
+		for _, tt := range s.parent.Types() {
+			types[tt] = struct{}{}
+		}
+	}
+	for tt := range types {
+		s.AddEntry(tt, transform(s.Get(tt)))
+	}
+	return s
+}
+
+func (s *StyleBuilder) Build() (*Style, error) {
+	style := &Style{
+		Name:    s.name,
+		Theme:   s.theme,
+		entries: map[TokenType]StyleEntry{},
+		parent:  s.parent,
+	}
+	for ttype, descriptor := range s.entries {
+		entry, err := ParseStyleEntry(descriptor)
+		if err != nil {
+			return nil, fmt.Errorf("invalid entry for %s: %s", ttype, err)
+		}
+		style.entries[ttype] = entry
+	}
+	return style, nil
+}
+
+// StyleEntries mapping TokenType to colour definition.
+type StyleEntries map[TokenType]string
+
+// NewXMLStyle parses an XML style definition.
+func NewXMLStyle(r io.Reader) (*Style, error) {
+	dec := xml.NewDecoder(r)
+	style := &Style{}
+	return style, dec.Decode(style)
+}
+
+// MustNewXMLStyle is like NewXMLStyle but panics on error.
+func MustNewXMLStyle(r io.Reader) *Style {
+	style, err := NewXMLStyle(r)
+	if err != nil {
+		panic(err)
+	}
+	return style
+}
+
+// NewStyle creates a new style definition.
+func NewStyle(name string, theme string, entries StyleEntries) (*Style, error) {
+	return NewStyleBuilder(name, theme).AddAll(entries).Build()
+}
+
+// MustNewStyle creates a new style or panics.
+func MustNewStyle(name string, theme string, entries StyleEntries) *Style {
+	style, err := NewStyle(name, theme, entries)
+	if err != nil {
+		panic(err)
+	}
+	return style
+}
+
+// A Style definition.
+//
+// See http://pygments.org/docs/styles/ for details. Semantics are intended to be identical.
+type Style struct {
+	Name    string
+	Theme   string
+	entries map[TokenType]StyleEntry
+	parent  *Style
+}
+
+func (s *Style) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
+	if s.parent != nil {
+		return fmt.Errorf("cannot marshal style with parent")
+	}
+	start.Name = xml.Name{Local: "style"}
+	start.Attr = []xml.Attr{
+		{Name: xml.Name{Local: "name"}, Value: s.Name},
+		{Name: xml.Name{Local: "theme"}, Value: s.Theme},
+	}
+	if err := e.EncodeToken(start); err != nil {
+		return err
+	}
+	sorted := make([]TokenType, 0, len(s.entries))
+	for ttype := range s.entries {
+		sorted = append(sorted, ttype)
+	}
+	sort.Slice(sorted, func(i, j int) bool { return sorted[i] < sorted[j] })
+	for _, ttype := range sorted {
+		entry := s.entries[ttype]
+		el := xml.StartElement{Name: xml.Name{Local: "entry"}}
+		el.Attr = []xml.Attr{
+			{Name: xml.Name{Local: "type"}, Value: ttype.String()},
+			{Name: xml.Name{Local: "style"}, Value: entry.String()},
+		}
+		if err := e.EncodeToken(el); err != nil {
+			return err
+		}
+		if err := e.EncodeToken(xml.EndElement{Name: el.Name}); err != nil {
+			return err
+		}
+	}
+	return e.EncodeToken(xml.EndElement{Name: start.Name})
+}
+
+func (s *Style) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
+	for _, attr := range start.Attr {
+		if attr.Name.Local == "name" {
+			s.Name = attr.Value
+		} else if attr.Name.Local == "theme" {
+			s.Theme = attr.Value
+		} else {
+			return fmt.Errorf("unexpected attribute %s", attr.Name.Local)
+		}
+	}
+	if s.Name == "" {
+		return fmt.Errorf("missing style name attribute")
+	}
+	if s.Theme == "" {
+		return fmt.Errorf("missing style theme attribute")
+	}
+	s.entries = map[TokenType]StyleEntry{}
+	for {
+		tok, err := d.Token()
+		if err != nil {
+			return err
+		}
+		switch el := tok.(type) {
+		case xml.StartElement:
+			if el.Name.Local != "entry" {
+				return fmt.Errorf("unexpected element %s", el.Name.Local)
+			}
+			var ttype TokenType
+			var entry StyleEntry
+			for _, attr := range el.Attr {
+				switch attr.Name.Local {
+				case "type":
+					ttype, err = TokenTypeString(attr.Value)
+					if err != nil {
+						return err
+					}
+
+				case "style":
+					entry, err = ParseStyleEntry(attr.Value)
+					if err != nil {
+						return err
+					}
+
+				default:
+					return fmt.Errorf("unexpected attribute %s", attr.Name.Local)
+				}
+			}
+			s.entries[ttype] = entry
+
+		case xml.EndElement:
+			if el.Name.Local == start.Name.Local {
+				return nil
+			}
+		}
+	}
+}
+
+// Types that are styled.
+func (s *Style) Types() []TokenType {
+	dedupe := map[TokenType]bool{}
+	for tt := range s.entries {
+		dedupe[tt] = true
+	}
+	if s.parent != nil {
+		for _, tt := range s.parent.Types() {
+			dedupe[tt] = true
+		}
+	}
+	out := make([]TokenType, 0, len(dedupe))
+	for tt := range dedupe {
+		out = append(out, tt)
+	}
+	return out
+}
+
+// Builder creates a mutable builder from this Style.
+//
+// The builder can then be safely modified. This is a cheap operation.
+func (s *Style) Builder() *StyleBuilder {
+	return &StyleBuilder{
+		name:    s.Name,
+		theme:   s.Theme,
+		entries: map[TokenType]string{},
+		parent:  s,
+	}
+}
+
+// Has checks if an exact style entry match exists for a token type.
+//
+// This is distinct from Get() which will merge parent tokens.
+func (s *Style) Has(ttype TokenType) bool {
+	return !s.get(ttype).IsZero() || s.synthesisable(ttype)
+}
+
+// Get a style entry. Will try sub-category or category if an exact match is not found, and
+// finally return the Background.
+func (s *Style) Get(ttype TokenType) StyleEntry {
+	return s.get(ttype).Inherit(
+		s.get(Background),
+		s.get(Text),
+		s.get(ttype.Category()),
+		s.get(ttype.SubCategory()))
+}
+
+func (s *Style) get(ttype TokenType) StyleEntry {
+	out := s.entries[ttype]
+	if out.IsZero() && s.parent != nil {
+		return s.parent.get(ttype)
+	}
+	if out.IsZero() && s.synthesisable(ttype) {
+		out = s.synthesise(ttype)
+	}
+	return out
+}
+
+func (s *Style) synthesise(ttype TokenType) StyleEntry {
+	bg := s.get(Background)
+	text := StyleEntry{Colour: bg.Colour}
+	text.Colour = text.Colour.BrightenOrDarken(0.5)
+
+	switch ttype {
+	// If we don't have a line highlight colour, make one that is 10% brighter/darker than the background.
+	case LineHighlight:
+		return StyleEntry{Background: bg.Background.BrightenOrDarken(0.1)}
+
+	// If we don't have line numbers, use the text colour but 20% brighter/darker
+	case LineNumbers, LineNumbersTable:
+		return text
+
+	default:
+		return StyleEntry{}
+	}
+}
+
+func (s *Style) synthesisable(ttype TokenType) bool {
+	return ttype == LineHighlight || ttype == LineNumbers || ttype == LineNumbersTable
+}
+
+// MustParseStyleEntry parses a Pygments style entry or panics.
+func MustParseStyleEntry(entry string) StyleEntry {
+	out, err := ParseStyleEntry(entry)
+	if err != nil {
+		panic(err)
+	}
+	return out
+}
+
+// ParseStyleEntry parses a Pygments style entry.
+func ParseStyleEntry(entry string) (StyleEntry, error) { // nolint: gocyclo
+	out := StyleEntry{}
+	parts := strings.Fields(entry)
+	for _, part := range parts {
+		switch {
+		case part == "italic":
+			out.Italic = Yes
+		case part == "noitalic":
+			out.Italic = No
+		case part == "bold":
+			out.Bold = Yes
+		case part == "nobold":
+			out.Bold = No
+		case part == "underline":
+			out.Underline = Yes
+		case part == "nounderline":
+			out.Underline = No
+		case part == "inherit":
+			out.NoInherit = false
+		case part == "noinherit":
+			out.NoInherit = true
+		case part == "bg:":
+			out.Background = 0
+		case strings.HasPrefix(part, "bg:#"):
+			out.Background = ParseColour(part[3:])
+			if !out.Background.IsSet() {
+				return StyleEntry{}, fmt.Errorf("invalid background colour %q", part)
+			}
+		case strings.HasPrefix(part, "border:#"):
+			out.Border = ParseColour(part[7:])
+			if !out.Border.IsSet() {
+				return StyleEntry{}, fmt.Errorf("invalid border colour %q", part)
+			}
+		case strings.HasPrefix(part, "#"):
+			out.Colour = ParseColour(part)
+			if !out.Colour.IsSet() {
+				return StyleEntry{}, fmt.Errorf("invalid colour %q", part)
+			}
+		default:
+			return StyleEntry{}, fmt.Errorf("unknown style element %q", part)
+		}
+	}
+	return out, nil
+}
diff --git a/style_test.go b/style_test.go
new file mode 100644
index 0000000..becf19d
--- /dev/null
+++ b/style_test.go
@@ -0,0 +1,122 @@
+package chroma
+
+import (
+	"encoding/xml"
+	"testing"
+
+	"github.com/alecthomas/assert/v2"
+)
+
+func TestStyleInherit(t *testing.T) {
+	s, err := NewStyle("test", "dark", StyleEntries{
+		Name:         "bold #f00",
+		NameVariable: "#fff",
+	})
+	assert.NoError(t, err)
+	assert.Equal(t, StyleEntry{Colour: 0x1000000, Bold: Yes}, s.Get(NameVariable))
+}
+
+func TestStyleColours(t *testing.T) {
+	s, err := NewStyle("test", "dark", StyleEntries{
+		Name: "#f00 bg:#001 border:#ansiblue",
+	})
+	assert.NoError(t, err)
+	assert.Equal(t, StyleEntry{Colour: 0xff0001, Background: 0x000012, Border: 0x000100}, s.Get(Name))
+}
+
+func TestStyleClone(t *testing.T) {
+	parent, err := NewStyle("test", "dark", StyleEntries{
+		Background: "bg:#ffffff",
+	})
+	assert.NoError(t, err)
+	clone, err := parent.Builder().Add(Comment, "#0f0").Build()
+	assert.NoError(t, err)
+
+	assert.Equal(t, "bg:#ffffff", clone.Get(Background).String())
+	assert.Equal(t, "#00ff00 bg:#ffffff", clone.Get(Comment).String())
+	assert.Equal(t, "bg:#ffffff", parent.Get(Comment).String())
+}
+
+func TestSynthesisedStyleEntries(t *testing.T) {
+	style, err := NewStyle("test", "dark", StyleEntries{
+		Background: "bg:#ffffff",
+	})
+	assert.NoError(t, err)
+	assert.True(t, style.Has(LineHighlight))
+	assert.True(t, style.Has(LineNumbersTable))
+	assert.True(t, style.Has(LineNumbers))
+	assert.Equal(t, "bg:#e5e5e5", style.Get(LineHighlight).String())
+	assert.Equal(t, "#7f7f7f bg:#ffffff", style.Get(LineNumbers).String())
+	assert.Equal(t, "#7f7f7f bg:#ffffff", style.Get(LineNumbersTable).String())
+}
+
+func TestSynthesisedStyleClone(t *testing.T) {
+	style, err := NewStyle("test", "dark", StyleEntries{
+		Background:    "bg:#ffffff",
+		LineHighlight: "bg:#ffffff",
+		LineNumbers:   "bg:#fffff1",
+	})
+	assert.NoError(t, err)
+	style, err = style.Builder().Build()
+	assert.NoError(t, err)
+	assert.True(t, style.Has(LineHighlight))
+	assert.True(t, style.Has(LineNumbers))
+	assert.Equal(t, "bg:#ffffff", style.Get(LineHighlight).String())
+	assert.Equal(t, "bg:#fffff1", style.Get(LineNumbers).String())
+}
+
+func TestStyleBuilderTransform(t *testing.T) {
+	orig, err := NewStyle("test", "dark", StyleEntries{
+		Name:         "#000",
+		NameVariable: "bold #f00",
+	})
+	assert.NoError(t, err)
+
+	// Derive a style that inherits entries from orig.
+	builder := orig.Builder()
+	builder.Add(NameVariableGlobal, "#f30")
+	deriv, err := builder.Build()
+	assert.NoError(t, err)
+
+	// Use Transform to brighten or darken all of the colours in the derived style.
+	light, err := deriv.Builder().Transform(func(se StyleEntry) StyleEntry {
+		se.Colour = se.Colour.ClampBrightness(0.9, 1)
+		return se
+	}).Build()
+	assert.NoError(t, err, "Transform failed: %v", err)
+	assert.True(t, light.Get(Name).Colour.Brightness() >= 0.89)
+	assert.True(t, light.Get(NameVariable).Colour.Brightness() >= 0.89)
+	assert.True(t, light.Get(NameVariableGlobal).Colour.Brightness() >= 0.89)
+
+	dark, err := deriv.Builder().Transform(func(se StyleEntry) StyleEntry {
+		se.Colour = se.Colour.ClampBrightness(0, 0.1)
+		return se
+	}).Build()
+	assert.NoError(t, err, "Transform failed: %v", err)
+	assert.True(t, dark.Get(Name).Colour.Brightness() <= 0.11)
+	assert.True(t, dark.Get(NameVariable).Colour.Brightness() <= 0.11)
+	assert.True(t, dark.Get(NameVariableGlobal).Colour.Brightness() <= 0.11)
+
+	// The original styles should be unchanged.
+	assert.Equal(t, "#000000", orig.Get(Name).Colour.String())
+	assert.Equal(t, "#ff0000", orig.Get(NameVariable).Colour.String())
+	assert.Equal(t, "#ff3300", deriv.Get(NameVariableGlobal).Colour.String())
+}
+
+func TestStyleMarshaller(t *testing.T) {
+	expected, err := NewStyle("test", "dark", StyleEntries{
+		Whitespace: "bg:#ffffff",
+		Text:       "#000000 underline",
+	})
+	assert.NoError(t, err)
+	data, err := xml.MarshalIndent(expected, "", "  ")
+	assert.NoError(t, err)
+	assert.Equal(t, `<style name="test">
+  <entry type="Text" style="underline #000000"></entry>
+  <entry type="TextWhitespace" style="bg:#ffffff"></entry>
+</style>`, string(data))
+	actual := &Style{}
+	err = xml.Unmarshal(data, actual)
+	assert.NoError(t, err)
+	assert.Equal(t, expected, actual)
+}
diff --git a/styles/api.go b/styles/api.go
new file mode 100644
index 0000000..2936aeb
--- /dev/null
+++ b/styles/api.go
@@ -0,0 +1,93 @@
+package styles
+
+import (
+	"embed"
+	"io/fs"
+	"path/filepath"
+	"sort"
+
+	"toastielab.dev/toastie-stuff/chroma/v2"
+	"toastielab.dev/toastie-stuff/chroma/v2/base16"
+)
+
+//go:embed embedded
+var embedded embed.FS
+
+// Registry of Styles.
+var Registry = func() map[string]*chroma.Style {
+	registry := map[string]*chroma.Style{}
+	// Register all embedded styles.
+	embeddedSub, err := fs.Sub(embedded, "embedded")
+	if err != nil {
+		panic(err)
+	}
+	styles, err := LoadFromFS(embeddedSub)
+	if err != nil {
+		panic(err)
+	}
+	for _, style := range styles {
+		registry[style.Name] = style
+	}
+	return registry
+}()
+
+// Fallback style. Reassign to change the default fallback style.
+var Fallback = Registry["swapoff"]
+
+func LoadFromFS(fsys fs.FS) ([]*chroma.Style, error) {
+	files, err := fs.ReadDir(fsys, ".")
+	if err != nil {
+		return nil, err
+	}
+
+	styles := make([]*chroma.Style, 0, len(files))
+	for _, file := range files {
+		if file.IsDir() {
+			continue
+		}
+
+		r, err := fsys.Open(file.Name())
+		if err != nil {
+			return nil, err
+		}
+
+		var style *chroma.Style
+		switch filepath.Ext(file.Name()) {
+		case ".xml":
+			style, err = chroma.NewXMLStyle(r)
+		case ".yaml", ".yml":
+			style, err = base16.NewStyle(r)
+		}
+		if err != nil {
+			return nil, err
+		}
+
+		styles = append(styles, style)
+	}
+
+	return styles, nil
+}
+
+// Register a chroma.Style.
+func Register(style *chroma.Style) *chroma.Style {
+	Registry[style.Name] = style
+	return style
+}
+
+// Names of all available styles.
+func Names() []string {
+	out := []string{}
+	for name := range Registry {
+		out = append(out, name)
+	}
+	sort.Strings(out)
+	return out
+}
+
+// Get named style, or Fallback.
+func Get(name string) *chroma.Style {
+	if style, ok := Registry[name]; ok {
+		return style
+	}
+	return Fallback
+}
diff --git a/styles/embedded/abap.xml b/styles/embedded/abap.xml
new file mode 100644
index 0000000..8f0f1d3
--- /dev/null
+++ b/styles/embedded/abap.xml
@@ -0,0 +1,11 @@
+<style name="abap" theme="light">
+  <entry type="Error" style="#ff0000"/>
+  <entry type="Background" style="bg:#ffffff"/>
+  <entry type="Keyword" style="#0000ff"/>
+  <entry type="Name" style="#000000"/>
+  <entry type="LiteralString" style="#55aa22"/>
+  <entry type="LiteralNumber" style="#33aaff"/>
+  <entry type="OperatorWord" style="#0000ff"/>
+  <entry type="Comment" style="italic #888888"/>
+  <entry type="CommentSpecial" style="#888888"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/algol.xml b/styles/embedded/algol.xml
new file mode 100644
index 0000000..8abc640
--- /dev/null
+++ b/styles/embedded/algol.xml
@@ -0,0 +1,18 @@
+<style name="algol" theme="light">
+  <entry type="Error" style="border:#ff0000"/>
+  <entry type="Background" style="bg:#ffffff"/>
+  <entry type="Keyword" style="bold underline"/>
+  <entry type="KeywordDeclaration" style="italic"/>
+  <entry type="NameBuiltin" style="bold italic"/>
+  <entry type="NameBuiltinPseudo" style="bold italic"/>
+  <entry type="NameClass" style="bold italic #666666"/>
+  <entry type="NameConstant" style="bold italic #666666"/>
+  <entry type="NameFunction" style="bold italic #666666"/>
+  <entry type="NameNamespace" style="bold italic #666666"/>
+  <entry type="NameVariable" style="bold italic #666666"/>
+  <entry type="LiteralString" style="italic #666666"/>
+  <entry type="OperatorWord" style="bold"/>
+  <entry type="Comment" style="italic #888888"/>
+  <entry type="CommentSpecial" style="bold noitalic #888888"/>
+  <entry type="CommentPreproc" style="bold noitalic #888888"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/algol_nu.xml b/styles/embedded/algol_nu.xml
new file mode 100644
index 0000000..ad296ca
--- /dev/null
+++ b/styles/embedded/algol_nu.xml
@@ -0,0 +1,18 @@
+<style name="algol_nu" theme="light">
+  <entry type="Error" style="border:#ff0000"/>
+  <entry type="Background" style="bg:#ffffff"/>
+  <entry type="Keyword" style="bold"/>
+  <entry type="KeywordDeclaration" style="italic"/>
+  <entry type="NameBuiltin" style="bold italic"/>
+  <entry type="NameBuiltinPseudo" style="bold italic"/>
+  <entry type="NameClass" style="bold italic #666666"/>
+  <entry type="NameConstant" style="bold italic #666666"/>
+  <entry type="NameFunction" style="bold italic #666666"/>
+  <entry type="NameNamespace" style="bold italic #666666"/>
+  <entry type="NameVariable" style="bold italic #666666"/>
+  <entry type="LiteralString" style="italic #666666"/>
+  <entry type="OperatorWord" style="bold"/>
+  <entry type="Comment" style="italic #888888"/>
+  <entry type="CommentSpecial" style="bold noitalic #888888"/>
+  <entry type="CommentPreproc" style="bold noitalic #888888"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/arduino.xml b/styles/embedded/arduino.xml
new file mode 100644
index 0000000..bbf6197
--- /dev/null
+++ b/styles/embedded/arduino.xml
@@ -0,0 +1,18 @@
+<style name="arduino" theme="light">
+  <entry type="Error" style="#a61717"/>
+  <entry type="Background" style="bg:#ffffff"/>
+  <entry type="Keyword" style="#728e00"/>
+  <entry type="KeywordConstant" style="#00979d"/>
+  <entry type="KeywordPseudo" style="#00979d"/>
+  <entry type="KeywordReserved" style="#00979d"/>
+  <entry type="KeywordType" style="#00979d"/>
+  <entry type="Name" style="#434f54"/>
+  <entry type="NameBuiltin" style="#728e00"/>
+  <entry type="NameFunction" style="#d35400"/>
+  <entry type="NameOther" style="#728e00"/>
+  <entry type="LiteralString" style="#7f8c8d"/>
+  <entry type="LiteralNumber" style="#8a7b52"/>
+  <entry type="Operator" style="#728e00"/>
+  <entry type="Comment" style="#95a5a6"/>
+  <entry type="CommentPreproc" style="#728e00"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/autumn.xml b/styles/embedded/autumn.xml
new file mode 100644
index 0000000..453e407
--- /dev/null
+++ b/styles/embedded/autumn.xml
@@ -0,0 +1,36 @@
+<style name="autumn" theme="light">
+  <entry type="Error" style="#ff0000 bg:#ffaaaa"/>
+  <entry type="Background" style="bg:#ffffff"/>
+  <entry type="Keyword" style="#0000aa"/>
+  <entry type="KeywordType" style="#00aaaa"/>
+  <entry type="NameAttribute" style="#1e90ff"/>
+  <entry type="NameBuiltin" style="#00aaaa"/>
+  <entry type="NameClass" style="underline #00aa00"/>
+  <entry type="NameConstant" style="#aa0000"/>
+  <entry type="NameDecorator" style="#888888"/>
+  <entry type="NameEntity" style="bold #880000"/>
+  <entry type="NameFunction" style="#00aa00"/>
+  <entry type="NameNamespace" style="underline #00aaaa"/>
+  <entry type="NameTag" style="bold #1e90ff"/>
+  <entry type="NameVariable" style="#aa0000"/>
+  <entry type="LiteralString" style="#aa5500"/>
+  <entry type="LiteralStringRegex" style="#009999"/>
+  <entry type="LiteralStringSymbol" style="#0000aa"/>
+  <entry type="LiteralNumber" style="#009999"/>
+  <entry type="OperatorWord" style="#0000aa"/>
+  <entry type="Comment" style="italic #aaaaaa"/>
+  <entry type="CommentSpecial" style="italic #0000aa"/>
+  <entry type="CommentPreproc" style="noitalic #4c8317"/>
+  <entry type="GenericDeleted" style="#aa0000"/>
+  <entry type="GenericEmph" style="italic"/>
+  <entry type="GenericError" style="#aa0000"/>
+  <entry type="GenericHeading" style="bold #000080"/>
+  <entry type="GenericInserted" style="#00aa00"/>
+  <entry type="GenericOutput" style="#888888"/>
+  <entry type="GenericPrompt" style="#555555"/>
+  <entry type="GenericStrong" style="bold"/>
+  <entry type="GenericSubheading" style="bold #800080"/>
+  <entry type="GenericTraceback" style="#aa0000"/>
+  <entry type="GenericUnderline" style="underline"/>
+  <entry type="TextWhitespace" style="#bbbbbb"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/average.xml b/styles/embedded/average.xml
new file mode 100644
index 0000000..65502fa
--- /dev/null
+++ b/styles/embedded/average.xml
@@ -0,0 +1,74 @@
+<style name="average" theme="dark">
+  <entry type="Other" style="#757575"/>
+  <entry type="Error" style="#ec0000"/>
+  <entry type="Background" style="bg:#000000"/>
+  <entry type="Keyword" style="#ec0000"/>
+  <entry type="KeywordConstant" style="#ec0000"/>
+  <entry type="KeywordDeclaration" style="#ec0000"/>
+  <entry type="KeywordNamespace" style="#ec0000"/>
+  <entry type="KeywordPseudo" style="#ec0000"/>
+  <entry type="KeywordReserved" style="#ec0000"/>
+  <entry type="KeywordType" style="#5f5fff"/>
+  <entry type="Name" style="#757575"/>
+  <entry type="NameAttribute" style="#5f5fff"/>
+  <entry type="NameBuiltin" style="#ec0000"/>
+  <entry type="NameBuiltinPseudo" style="#757575"/>
+  <entry type="NameClass" style="#5f5fff"/>
+  <entry type="NameConstant" style="#008900"/>
+  <entry type="NameDecorator" style="#008900"/>
+  <entry type="NameEntity" style="#757575"/>
+  <entry type="NameException" style="#757575"/>
+  <entry type="NameFunction" style="#5f5fff"/>
+  <entry type="NameLabel" style="#ec0000"/>
+  <entry type="NameNamespace" style="#757575"/>
+  <entry type="NameOther" style="#757575"/>
+  <entry type="NameTag" style="#ec0000"/>
+  <entry type="NameVariable" style="#ec0000"/>
+  <entry type="NameVariableClass" style="#ec0000"/>
+  <entry type="NameVariableGlobal" style="#ec0000"/>
+  <entry type="NameVariableInstance" style="#ec0000"/>
+  <entry type="Literal" style="#757575"/>
+  <entry type="LiteralDate" style="#757575"/>
+  <entry type="LiteralString" style="#008900"/>
+  <entry type="LiteralStringBacktick" style="#008900"/>
+  <entry type="LiteralStringChar" style="#008900"/>
+  <entry type="LiteralStringDoc" style="#008900"/>
+  <entry type="LiteralStringDouble" style="#008900"/>
+  <entry type="LiteralStringEscape" style="#008900"/>
+  <entry type="LiteralStringHeredoc" style="#008900"/>
+  <entry type="LiteralStringInterpol" style="#008900"/>
+  <entry type="LiteralStringOther" style="#008900"/>
+  <entry type="LiteralStringRegex" style="#008900"/>
+  <entry type="LiteralStringSingle" style="#008900"/>
+  <entry type="LiteralStringSymbol" style="#008900"/>
+  <entry type="LiteralNumber" style="#008900"/>
+  <entry type="LiteralNumberBin" style="#008900"/>
+  <entry type="LiteralNumberFloat" style="#008900"/>
+  <entry type="LiteralNumberHex" style="#008900"/>
+  <entry type="LiteralNumberInteger" style="#008900"/>
+  <entry type="LiteralNumberIntegerLong" style="#008900"/>
+  <entry type="LiteralNumberOct" style="#008900"/>
+  <entry type="Operator" style="#ec0000"/>
+  <entry type="OperatorWord" style="#ec0000"/>
+  <entry type="Punctuation" style="#757575"/>
+  <entry type="Comment" style="#757575"/>
+  <entry type="CommentHashbang" style="#757575"/>
+  <entry type="CommentMultiline" style="#757575"/>
+  <entry type="CommentSingle" style="#757575"/>
+  <entry type="CommentSpecial" style="#757575"/>
+  <entry type="CommentPreproc" style="#757575"/>
+  <entry type="Generic" style="#757575"/>
+  <entry type="GenericDeleted" style="#ec0000"/>
+  <entry type="GenericEmph" style="underline #757575"/>
+  <entry type="GenericError" style="#ec0000"/>
+  <entry type="GenericHeading" style="bold #757575"/>
+  <entry type="GenericInserted" style="bold #757575"/>
+  <entry type="GenericOutput" style="#757575"/>
+  <entry type="GenericPrompt" style="#757575"/>
+  <entry type="GenericStrong" style="italic #757575"/>
+  <entry type="GenericSubheading" style="bold #757575"/>
+  <entry type="GenericTraceback" style="#757575"/>
+  <entry type="GenericUnderline" style="underline"/>
+  <entry type="Text" style="#757575"/>
+  <entry type="TextWhitespace" style="#757575"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/base16-snazzy.xml b/styles/embedded/base16-snazzy.xml
new file mode 100644
index 0000000..d4a5c0a
--- /dev/null
+++ b/styles/embedded/base16-snazzy.xml
@@ -0,0 +1,74 @@
+<style name="base16-snazzy" theme="dark">
+  <entry type="Other" style="#e2e4e5"/>
+  <entry type="Error" style="#ff5c57"/>
+  <entry type="Background" style="bg:#282a36"/>
+  <entry type="Keyword" style="#ff6ac1"/>
+  <entry type="KeywordConstant" style="#ff6ac1"/>
+  <entry type="KeywordDeclaration" style="#ff5c57"/>
+  <entry type="KeywordNamespace" style="#ff6ac1"/>
+  <entry type="KeywordPseudo" style="#ff6ac1"/>
+  <entry type="KeywordReserved" style="#ff6ac1"/>
+  <entry type="KeywordType" style="#9aedfe"/>
+  <entry type="Name" style="#e2e4e5"/>
+  <entry type="NameAttribute" style="#57c7ff"/>
+  <entry type="NameBuiltin" style="#ff5c57"/>
+  <entry type="NameBuiltinPseudo" style="#e2e4e5"/>
+  <entry type="NameClass" style="#f3f99d"/>
+  <entry type="NameConstant" style="#ff9f43"/>
+  <entry type="NameDecorator" style="#ff9f43"/>
+  <entry type="NameEntity" style="#e2e4e5"/>
+  <entry type="NameException" style="#e2e4e5"/>
+  <entry type="NameFunction" style="#57c7ff"/>
+  <entry type="NameLabel" style="#ff5c57"/>
+  <entry type="NameNamespace" style="#e2e4e5"/>
+  <entry type="NameOther" style="#e2e4e5"/>
+  <entry type="NameTag" style="#ff6ac1"/>
+  <entry type="NameVariable" style="#ff5c57"/>
+  <entry type="NameVariableClass" style="#ff5c57"/>
+  <entry type="NameVariableGlobal" style="#ff5c57"/>
+  <entry type="NameVariableInstance" style="#ff5c57"/>
+  <entry type="Literal" style="#e2e4e5"/>
+  <entry type="LiteralDate" style="#e2e4e5"/>
+  <entry type="LiteralString" style="#5af78e"/>
+  <entry type="LiteralStringBacktick" style="#5af78e"/>
+  <entry type="LiteralStringChar" style="#5af78e"/>
+  <entry type="LiteralStringDoc" style="#5af78e"/>
+  <entry type="LiteralStringDouble" style="#5af78e"/>
+  <entry type="LiteralStringEscape" style="#5af78e"/>
+  <entry type="LiteralStringHeredoc" style="#5af78e"/>
+  <entry type="LiteralStringInterpol" style="#5af78e"/>
+  <entry type="LiteralStringOther" style="#5af78e"/>
+  <entry type="LiteralStringRegex" style="#5af78e"/>
+  <entry type="LiteralStringSingle" style="#5af78e"/>
+  <entry type="LiteralStringSymbol" style="#5af78e"/>
+  <entry type="LiteralNumber" style="#ff9f43"/>
+  <entry type="LiteralNumberBin" style="#ff9f43"/>
+  <entry type="LiteralNumberFloat" style="#ff9f43"/>
+  <entry type="LiteralNumberHex" style="#ff9f43"/>
+  <entry type="LiteralNumberInteger" style="#ff9f43"/>
+  <entry type="LiteralNumberIntegerLong" style="#ff9f43"/>
+  <entry type="LiteralNumberOct" style="#ff9f43"/>
+  <entry type="Operator" style="#ff6ac1"/>
+  <entry type="OperatorWord" style="#ff6ac1"/>
+  <entry type="Punctuation" style="#e2e4e5"/>
+  <entry type="Comment" style="#78787e"/>
+  <entry type="CommentHashbang" style="#78787e"/>
+  <entry type="CommentMultiline" style="#78787e"/>
+  <entry type="CommentSingle" style="#78787e"/>
+  <entry type="CommentSpecial" style="#78787e"/>
+  <entry type="CommentPreproc" style="#78787e"/>
+  <entry type="Generic" style="#e2e4e5"/>
+  <entry type="GenericDeleted" style="#ff5c57"/>
+  <entry type="GenericEmph" style="underline #e2e4e5"/>
+  <entry type="GenericError" style="#ff5c57"/>
+  <entry type="GenericHeading" style="bold #e2e4e5"/>
+  <entry type="GenericInserted" style="bold #e2e4e5"/>
+  <entry type="GenericOutput" style="#43454f"/>
+  <entry type="GenericPrompt" style="#e2e4e5"/>
+  <entry type="GenericStrong" style="italic #e2e4e5"/>
+  <entry type="GenericSubheading" style="bold #e2e4e5"/>
+  <entry type="GenericTraceback" style="#e2e4e5"/>
+  <entry type="GenericUnderline" style="underline"/>
+  <entry type="Text" style="#e2e4e5"/>
+  <entry type="TextWhitespace" style="#e2e4e5"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/borland.xml b/styles/embedded/borland.xml
new file mode 100644
index 0000000..0c1d4e9
--- /dev/null
+++ b/styles/embedded/borland.xml
@@ -0,0 +1,26 @@
+<style name="borland" theme="light">
+  <entry type="Error" style="#a61717 bg:#e3d2d2"/>
+  <entry type="Background" style="bg:#ffffff"/>
+  <entry type="Keyword" style="bold #000080"/>
+  <entry type="NameAttribute" style="#ff0000"/>
+  <entry type="NameTag" style="bold #000080"/>
+  <entry type="LiteralString" style="#0000ff"/>
+  <entry type="LiteralStringChar" style="#800080"/>
+  <entry type="LiteralNumber" style="#0000ff"/>
+  <entry type="OperatorWord" style="bold"/>
+  <entry type="Comment" style="italic #008800"/>
+  <entry type="CommentSpecial" style="bold noitalic"/>
+  <entry type="CommentPreproc" style="noitalic #008080"/>
+  <entry type="GenericDeleted" style="#000000 bg:#ffdddd"/>
+  <entry type="GenericEmph" style="italic"/>
+  <entry type="GenericError" style="#aa0000"/>
+  <entry type="GenericHeading" style="#999999"/>
+  <entry type="GenericInserted" style="#000000 bg:#ddffdd"/>
+  <entry type="GenericOutput" style="#888888"/>
+  <entry type="GenericPrompt" style="#555555"/>
+  <entry type="GenericStrong" style="bold"/>
+  <entry type="GenericSubheading" style="#aaaaaa"/>
+  <entry type="GenericTraceback" style="#aa0000"/>
+  <entry type="GenericUnderline" style="underline"/>
+  <entry type="TextWhitespace" style="#bbbbbb"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/bw.xml b/styles/embedded/bw.xml
new file mode 100644
index 0000000..e454f61
--- /dev/null
+++ b/styles/embedded/bw.xml
@@ -0,0 +1,23 @@
+<style name="bw" theme="light">
+  <entry type="Error" style="border:#ff0000"/>
+  <entry type="Background" style="bg:#ffffff"/>
+  <entry type="Keyword" style="bold"/>
+  <entry type="KeywordPseudo" style="nobold"/>
+  <entry type="KeywordType" style="nobold"/>
+  <entry type="NameClass" style="bold"/>
+  <entry type="NameEntity" style="bold"/>
+  <entry type="NameException" style="bold"/>
+  <entry type="NameNamespace" style="bold"/>
+  <entry type="NameTag" style="bold"/>
+  <entry type="LiteralString" style="italic"/>
+  <entry type="LiteralStringEscape" style="bold"/>
+  <entry type="LiteralStringInterpol" style="bold"/>
+  <entry type="OperatorWord" style="bold"/>
+  <entry type="Comment" style="italic"/>
+  <entry type="CommentPreproc" style="noitalic"/>
+  <entry type="GenericEmph" style="italic"/>
+  <entry type="GenericHeading" style="bold"/>
+  <entry type="GenericPrompt" style="bold"/>
+  <entry type="GenericStrong" style="bold"/>
+  <entry type="GenericSubheading" style="bold"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/catppuccin-frappe.xml b/styles/embedded/catppuccin-frappe.xml
new file mode 100644
index 0000000..b3827a3
--- /dev/null
+++ b/styles/embedded/catppuccin-frappe.xml
@@ -0,0 +1,83 @@
+<style name="catppuccin-frappe" theme="dark">
+  <entry type="Background" style="bg:#303446 #c6d0f5"/>
+  <entry type="CodeLine" style="#c6d0f5"/>
+  <entry type="Error" style="#e78284"/>
+  <entry type="Other" style="#c6d0f5"/>
+  <entry type="LineTableTD" style=""/>
+  <entry type="LineTable" style=""/>
+  <entry type="LineHighlight" style="bg:#51576d"/>
+  <entry type="LineNumbersTable" style="#838ba7"/>
+  <entry type="LineNumbers" style="#838ba7"/>
+  <entry type="Keyword" style="#ca9ee6"/>
+  <entry type="KeywordReserved" style="#ca9ee6"/>
+  <entry type="KeywordPseudo" style="#ca9ee6"/>
+  <entry type="KeywordConstant" style="#ef9f76"/>
+  <entry type="KeywordDeclaration" style="#e78284"/>
+  <entry type="KeywordNamespace" style="#81c8be"/>
+  <entry type="KeywordType" style="#e78284"/>
+  <entry type="Name" style="#c6d0f5"/>
+  <entry type="NameClass" style="#e5c890"/>
+  <entry type="NameConstant" style="#e5c890"/>
+  <entry type="NameDecorator" style="bold #8caaee"/>
+  <entry type="NameEntity" style="#81c8be"/>
+  <entry type="NameException" style="#ef9f76"/>
+  <entry type="NameFunction" style="#8caaee"/>
+  <entry type="NameFunctionMagic" style="#8caaee"/>
+  <entry type="NameLabel" style="#99d1db"/>
+  <entry type="NameNamespace" style="#ef9f76"/>
+  <entry type="NameProperty" style="#ef9f76"/>
+  <entry type="NameTag" style="#ca9ee6"/>
+  <entry type="NameVariable" style="#f2d5cf"/>
+  <entry type="NameVariableClass" style="#f2d5cf"/>
+  <entry type="NameVariableGlobal" style="#f2d5cf"/>
+  <entry type="NameVariableInstance" style="#f2d5cf"/>
+  <entry type="NameVariableMagic" style="#f2d5cf"/>
+  <entry type="NameAttribute" style="#8caaee"/>
+  <entry type="NameBuiltin" style="#99d1db"/>
+  <entry type="NameBuiltinPseudo" style="#99d1db"/>
+  <entry type="NameOther" style="#c6d0f5"/>
+  <entry type="Literal" style="#c6d0f5"/>
+  <entry type="LiteralDate" style="#c6d0f5"/>
+  <entry type="LiteralString" style="#a6d189"/>
+  <entry type="LiteralStringChar" style="#a6d189"/>
+  <entry type="LiteralStringSingle" style="#a6d189"/>
+  <entry type="LiteralStringDouble" style="#a6d189"/>
+  <entry type="LiteralStringBacktick" style="#a6d189"/>
+  <entry type="LiteralStringOther" style="#a6d189"/>
+  <entry type="LiteralStringSymbol" style="#a6d189"/>
+  <entry type="LiteralStringInterpol" style="#a6d189"/>
+  <entry type="LiteralStringAffix" style="#e78284"/>
+  <entry type="LiteralStringDelimiter" style="#8caaee"/>
+  <entry type="LiteralStringEscape" style="#8caaee"/>
+  <entry type="LiteralStringRegex" style="#81c8be"/>
+  <entry type="LiteralStringDoc" style="#737994"/>
+  <entry type="LiteralStringHeredoc" style="#737994"/>
+  <entry type="LiteralNumber" style="#ef9f76"/>
+  <entry type="LiteralNumberBin" style="#ef9f76"/>
+  <entry type="LiteralNumberHex" style="#ef9f76"/>
+  <entry type="LiteralNumberInteger" style="#ef9f76"/>
+  <entry type="LiteralNumberFloat" style="#ef9f76"/>
+  <entry type="LiteralNumberIntegerLong" style="#ef9f76"/>
+  <entry type="LiteralNumberOct" style="#ef9f76"/>
+  <entry type="Operator" style="bold #99d1db"/>
+  <entry type="OperatorWord" style="bold #99d1db"/>
+  <entry type="Comment" style="italic #737994"/>
+  <entry type="CommentSingle" style="italic #737994"/>
+  <entry type="CommentMultiline" style="italic #737994"/>
+  <entry type="CommentSpecial" style="italic #737994"/>
+  <entry type="CommentHashbang" style="italic #737994"/>
+  <entry type="CommentPreproc" style="italic #737994"/>
+  <entry type="CommentPreprocFile" style="bold #737994"/>
+  <entry type="Generic" style="#c6d0f5"/>
+  <entry type="GenericInserted" style="bg:#414559 #a6d189"/>
+  <entry type="GenericDeleted" style="#e78284 bg:#414559"/>
+  <entry type="GenericEmph" style="italic #c6d0f5"/>
+  <entry type="GenericStrong" style="bold #c6d0f5"/>
+  <entry type="GenericUnderline" style="underline #c6d0f5"/>
+  <entry type="GenericHeading" style="bold #ef9f76"/>
+  <entry type="GenericSubheading" style="bold #ef9f76"/>
+  <entry type="GenericOutput" style="#c6d0f5"/>
+  <entry type="GenericPrompt" style="#c6d0f5"/>
+  <entry type="GenericError" style="#e78284"/>
+  <entry type="GenericTraceback" style="#e78284"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/catppuccin-latte.xml b/styles/embedded/catppuccin-latte.xml
new file mode 100644
index 0000000..48187f2
--- /dev/null
+++ b/styles/embedded/catppuccin-latte.xml
@@ -0,0 +1,83 @@
+<style name="catppuccin-latte" theme="light">
+  <entry type="Background" style="bg:#eff1f5 #4c4f69"/>
+  <entry type="CodeLine" style="#4c4f69"/>
+  <entry type="Error" style="#d20f39"/>
+  <entry type="Other" style="#4c4f69"/>
+  <entry type="LineTableTD" style=""/>
+  <entry type="LineTable" style=""/>
+  <entry type="LineHighlight" style="bg:#bcc0cc"/>
+  <entry type="LineNumbersTable" style="#8c8fa1"/>
+  <entry type="LineNumbers" style="#8c8fa1"/>
+  <entry type="Keyword" style="#8839ef"/>
+  <entry type="KeywordReserved" style="#8839ef"/>
+  <entry type="KeywordPseudo" style="#8839ef"/>
+  <entry type="KeywordConstant" style="#fe640b"/>
+  <entry type="KeywordDeclaration" style="#d20f39"/>
+  <entry type="KeywordNamespace" style="#179299"/>
+  <entry type="KeywordType" style="#d20f39"/>
+  <entry type="Name" style="#4c4f69"/>
+  <entry type="NameClass" style="#df8e1d"/>
+  <entry type="NameConstant" style="#df8e1d"/>
+  <entry type="NameDecorator" style="bold #1e66f5"/>
+  <entry type="NameEntity" style="#179299"/>
+  <entry type="NameException" style="#fe640b"/>
+  <entry type="NameFunction" style="#1e66f5"/>
+  <entry type="NameFunctionMagic" style="#1e66f5"/>
+  <entry type="NameLabel" style="#04a5e5"/>
+  <entry type="NameNamespace" style="#fe640b"/>
+  <entry type="NameProperty" style="#fe640b"/>
+  <entry type="NameTag" style="#8839ef"/>
+  <entry type="NameVariable" style="#dc8a78"/>
+  <entry type="NameVariableClass" style="#dc8a78"/>
+  <entry type="NameVariableGlobal" style="#dc8a78"/>
+  <entry type="NameVariableInstance" style="#dc8a78"/>
+  <entry type="NameVariableMagic" style="#dc8a78"/>
+  <entry type="NameAttribute" style="#1e66f5"/>
+  <entry type="NameBuiltin" style="#04a5e5"/>
+  <entry type="NameBuiltinPseudo" style="#04a5e5"/>
+  <entry type="NameOther" style="#4c4f69"/>
+  <entry type="Literal" style="#4c4f69"/>
+  <entry type="LiteralDate" style="#4c4f69"/>
+  <entry type="LiteralString" style="#40a02b"/>
+  <entry type="LiteralStringChar" style="#40a02b"/>
+  <entry type="LiteralStringSingle" style="#40a02b"/>
+  <entry type="LiteralStringDouble" style="#40a02b"/>
+  <entry type="LiteralStringBacktick" style="#40a02b"/>
+  <entry type="LiteralStringOther" style="#40a02b"/>
+  <entry type="LiteralStringSymbol" style="#40a02b"/>
+  <entry type="LiteralStringInterpol" style="#40a02b"/>
+  <entry type="LiteralStringAffix" style="#d20f39"/>
+  <entry type="LiteralStringDelimiter" style="#1e66f5"/>
+  <entry type="LiteralStringEscape" style="#1e66f5"/>
+  <entry type="LiteralStringRegex" style="#179299"/>
+  <entry type="LiteralStringDoc" style="#9ca0b0"/>
+  <entry type="LiteralStringHeredoc" style="#9ca0b0"/>
+  <entry type="LiteralNumber" style="#fe640b"/>
+  <entry type="LiteralNumberBin" style="#fe640b"/>
+  <entry type="LiteralNumberHex" style="#fe640b"/>
+  <entry type="LiteralNumberInteger" style="#fe640b"/>
+  <entry type="LiteralNumberFloat" style="#fe640b"/>
+  <entry type="LiteralNumberIntegerLong" style="#fe640b"/>
+  <entry type="LiteralNumberOct" style="#fe640b"/>
+  <entry type="Operator" style="bold #04a5e5"/>
+  <entry type="OperatorWord" style="bold #04a5e5"/>
+  <entry type="Comment" style="italic #9ca0b0"/>
+  <entry type="CommentSingle" style="italic #9ca0b0"/>
+  <entry type="CommentMultiline" style="italic #9ca0b0"/>
+  <entry type="CommentSpecial" style="italic #9ca0b0"/>
+  <entry type="CommentHashbang" style="italic #9ca0b0"/>
+  <entry type="CommentPreproc" style="italic #9ca0b0"/>
+  <entry type="CommentPreprocFile" style="bold #9ca0b0"/>
+  <entry type="Generic" style="#4c4f69"/>
+  <entry type="GenericInserted" style="bg:#ccd0da #40a02b"/>
+  <entry type="GenericDeleted" style="#d20f39 bg:#ccd0da"/>
+  <entry type="GenericEmph" style="italic #4c4f69"/>
+  <entry type="GenericStrong" style="bold #4c4f69"/>
+  <entry type="GenericUnderline" style="underline #4c4f69"/>
+  <entry type="GenericHeading" style="bold #fe640b"/>
+  <entry type="GenericSubheading" style="bold #fe640b"/>
+  <entry type="GenericOutput" style="#4c4f69"/>
+  <entry type="GenericPrompt" style="#4c4f69"/>
+  <entry type="GenericError" style="#d20f39"/>
+  <entry type="GenericTraceback" style="#d20f39"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/catppuccin-macchiato.xml b/styles/embedded/catppuccin-macchiato.xml
new file mode 100644
index 0000000..ca53113
--- /dev/null
+++ b/styles/embedded/catppuccin-macchiato.xml
@@ -0,0 +1,83 @@
+<style name="catppuccin-macchiato" theme="dark">
+  <entry type="Background" style="bg:#24273a #cad3f5"/>
+  <entry type="CodeLine" style="#cad3f5"/>
+  <entry type="Error" style="#ed8796"/>
+  <entry type="Other" style="#cad3f5"/>
+  <entry type="LineTableTD" style=""/>
+  <entry type="LineTable" style=""/>
+  <entry type="LineHighlight" style="bg:#494d64"/>
+  <entry type="LineNumbersTable" style="#8087a2"/>
+  <entry type="LineNumbers" style="#8087a2"/>
+  <entry type="Keyword" style="#c6a0f6"/>
+  <entry type="KeywordReserved" style="#c6a0f6"/>
+  <entry type="KeywordPseudo" style="#c6a0f6"/>
+  <entry type="KeywordConstant" style="#f5a97f"/>
+  <entry type="KeywordDeclaration" style="#ed8796"/>
+  <entry type="KeywordNamespace" style="#8bd5ca"/>
+  <entry type="KeywordType" style="#ed8796"/>
+  <entry type="Name" style="#cad3f5"/>
+  <entry type="NameClass" style="#eed49f"/>
+  <entry type="NameConstant" style="#eed49f"/>
+  <entry type="NameDecorator" style="bold #8aadf4"/>
+  <entry type="NameEntity" style="#8bd5ca"/>
+  <entry type="NameException" style="#f5a97f"/>
+  <entry type="NameFunction" style="#8aadf4"/>
+  <entry type="NameFunctionMagic" style="#8aadf4"/>
+  <entry type="NameLabel" style="#91d7e3"/>
+  <entry type="NameNamespace" style="#f5a97f"/>
+  <entry type="NameProperty" style="#f5a97f"/>
+  <entry type="NameTag" style="#c6a0f6"/>
+  <entry type="NameVariable" style="#f4dbd6"/>
+  <entry type="NameVariableClass" style="#f4dbd6"/>
+  <entry type="NameVariableGlobal" style="#f4dbd6"/>
+  <entry type="NameVariableInstance" style="#f4dbd6"/>
+  <entry type="NameVariableMagic" style="#f4dbd6"/>
+  <entry type="NameAttribute" style="#8aadf4"/>
+  <entry type="NameBuiltin" style="#91d7e3"/>
+  <entry type="NameBuiltinPseudo" style="#91d7e3"/>
+  <entry type="NameOther" style="#cad3f5"/>
+  <entry type="Literal" style="#cad3f5"/>
+  <entry type="LiteralDate" style="#cad3f5"/>
+  <entry type="LiteralString" style="#a6da95"/>
+  <entry type="LiteralStringChar" style="#a6da95"/>
+  <entry type="LiteralStringSingle" style="#a6da95"/>
+  <entry type="LiteralStringDouble" style="#a6da95"/>
+  <entry type="LiteralStringBacktick" style="#a6da95"/>
+  <entry type="LiteralStringOther" style="#a6da95"/>
+  <entry type="LiteralStringSymbol" style="#a6da95"/>
+  <entry type="LiteralStringInterpol" style="#a6da95"/>
+  <entry type="LiteralStringAffix" style="#ed8796"/>
+  <entry type="LiteralStringDelimiter" style="#8aadf4"/>
+  <entry type="LiteralStringEscape" style="#8aadf4"/>
+  <entry type="LiteralStringRegex" style="#8bd5ca"/>
+  <entry type="LiteralStringDoc" style="#6e738d"/>
+  <entry type="LiteralStringHeredoc" style="#6e738d"/>
+  <entry type="LiteralNumber" style="#f5a97f"/>
+  <entry type="LiteralNumberBin" style="#f5a97f"/>
+  <entry type="LiteralNumberHex" style="#f5a97f"/>
+  <entry type="LiteralNumberInteger" style="#f5a97f"/>
+  <entry type="LiteralNumberFloat" style="#f5a97f"/>
+  <entry type="LiteralNumberIntegerLong" style="#f5a97f"/>
+  <entry type="LiteralNumberOct" style="#f5a97f"/>
+  <entry type="Operator" style="bold #91d7e3"/>
+  <entry type="OperatorWord" style="bold #91d7e3"/>
+  <entry type="Comment" style="italic #6e738d"/>
+  <entry type="CommentSingle" style="italic #6e738d"/>
+  <entry type="CommentMultiline" style="italic #6e738d"/>
+  <entry type="CommentSpecial" style="italic #6e738d"/>
+  <entry type="CommentHashbang" style="italic #6e738d"/>
+  <entry type="CommentPreproc" style="italic #6e738d"/>
+  <entry type="CommentPreprocFile" style="bold #6e738d"/>
+  <entry type="Generic" style="#cad3f5"/>
+  <entry type="GenericInserted" style="bg:#363a4f #a6da95"/>
+  <entry type="GenericDeleted" style="#ed8796 bg:#363a4f"/>
+  <entry type="GenericEmph" style="italic #cad3f5"/>
+  <entry type="GenericStrong" style="bold #cad3f5"/>
+  <entry type="GenericUnderline" style="underline #cad3f5"/>
+  <entry type="GenericHeading" style="bold #f5a97f"/>
+  <entry type="GenericSubheading" style="bold #f5a97f"/>
+  <entry type="GenericOutput" style="#cad3f5"/>
+  <entry type="GenericPrompt" style="#cad3f5"/>
+  <entry type="GenericError" style="#ed8796"/>
+  <entry type="GenericTraceback" style="#ed8796"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/catppuccin-mocha.xml b/styles/embedded/catppuccin-mocha.xml
new file mode 100644
index 0000000..2ece4e5
--- /dev/null
+++ b/styles/embedded/catppuccin-mocha.xml
@@ -0,0 +1,83 @@
+<style name="catppuccin-mocha" theme="dark">
+  <entry type="Background" style="bg:#1e1e2e #cdd6f4"/>
+  <entry type="CodeLine" style="#cdd6f4"/>
+  <entry type="Error" style="#f38ba8"/>
+  <entry type="Other" style="#cdd6f4"/>
+  <entry type="LineTableTD" style=""/>
+  <entry type="LineTable" style=""/>
+  <entry type="LineHighlight" style="bg:#45475a"/>
+  <entry type="LineNumbersTable" style="#7f849c"/>
+  <entry type="LineNumbers" style="#7f849c"/>
+  <entry type="Keyword" style="#cba6f7"/>
+  <entry type="KeywordReserved" style="#cba6f7"/>
+  <entry type="KeywordPseudo" style="#cba6f7"/>
+  <entry type="KeywordConstant" style="#fab387"/>
+  <entry type="KeywordDeclaration" style="#f38ba8"/>
+  <entry type="KeywordNamespace" style="#94e2d5"/>
+  <entry type="KeywordType" style="#f38ba8"/>
+  <entry type="Name" style="#cdd6f4"/>
+  <entry type="NameClass" style="#f9e2af"/>
+  <entry type="NameConstant" style="#f9e2af"/>
+  <entry type="NameDecorator" style="bold #89b4fa"/>
+  <entry type="NameEntity" style="#94e2d5"/>
+  <entry type="NameException" style="#fab387"/>
+  <entry type="NameFunction" style="#89b4fa"/>
+  <entry type="NameFunctionMagic" style="#89b4fa"/>
+  <entry type="NameLabel" style="#89dceb"/>
+  <entry type="NameNamespace" style="#fab387"/>
+  <entry type="NameProperty" style="#fab387"/>
+  <entry type="NameTag" style="#cba6f7"/>
+  <entry type="NameVariable" style="#f5e0dc"/>
+  <entry type="NameVariableClass" style="#f5e0dc"/>
+  <entry type="NameVariableGlobal" style="#f5e0dc"/>
+  <entry type="NameVariableInstance" style="#f5e0dc"/>
+  <entry type="NameVariableMagic" style="#f5e0dc"/>
+  <entry type="NameAttribute" style="#89b4fa"/>
+  <entry type="NameBuiltin" style="#89dceb"/>
+  <entry type="NameBuiltinPseudo" style="#89dceb"/>
+  <entry type="NameOther" style="#cdd6f4"/>
+  <entry type="Literal" style="#cdd6f4"/>
+  <entry type="LiteralDate" style="#cdd6f4"/>
+  <entry type="LiteralString" style="#a6e3a1"/>
+  <entry type="LiteralStringChar" style="#a6e3a1"/>
+  <entry type="LiteralStringSingle" style="#a6e3a1"/>
+  <entry type="LiteralStringDouble" style="#a6e3a1"/>
+  <entry type="LiteralStringBacktick" style="#a6e3a1"/>
+  <entry type="LiteralStringOther" style="#a6e3a1"/>
+  <entry type="LiteralStringSymbol" style="#a6e3a1"/>
+  <entry type="LiteralStringInterpol" style="#a6e3a1"/>
+  <entry type="LiteralStringAffix" style="#f38ba8"/>
+  <entry type="LiteralStringDelimiter" style="#89b4fa"/>
+  <entry type="LiteralStringEscape" style="#89b4fa"/>
+  <entry type="LiteralStringRegex" style="#94e2d5"/>
+  <entry type="LiteralStringDoc" style="#6c7086"/>
+  <entry type="LiteralStringHeredoc" style="#6c7086"/>
+  <entry type="LiteralNumber" style="#fab387"/>
+  <entry type="LiteralNumberBin" style="#fab387"/>
+  <entry type="LiteralNumberHex" style="#fab387"/>
+  <entry type="LiteralNumberInteger" style="#fab387"/>
+  <entry type="LiteralNumberFloat" style="#fab387"/>
+  <entry type="LiteralNumberIntegerLong" style="#fab387"/>
+  <entry type="LiteralNumberOct" style="#fab387"/>
+  <entry type="Operator" style="bold #89dceb"/>
+  <entry type="OperatorWord" style="bold #89dceb"/>
+  <entry type="Comment" style="italic #6c7086"/>
+  <entry type="CommentSingle" style="italic #6c7086"/>
+  <entry type="CommentMultiline" style="italic #6c7086"/>
+  <entry type="CommentSpecial" style="italic #6c7086"/>
+  <entry type="CommentHashbang" style="italic #6c7086"/>
+  <entry type="CommentPreproc" style="italic #6c7086"/>
+  <entry type="CommentPreprocFile" style="bold #6c7086"/>
+  <entry type="Generic" style="#cdd6f4"/>
+  <entry type="GenericInserted" style="bg:#313244 #a6e3a1"/>
+  <entry type="GenericDeleted" style="#f38ba8 bg:#313244"/>
+  <entry type="GenericEmph" style="italic #cdd6f4"/>
+  <entry type="GenericStrong" style="bold #cdd6f4"/>
+  <entry type="GenericUnderline" style="underline #cdd6f4"/>
+  <entry type="GenericHeading" style="bold #fab387"/>
+  <entry type="GenericSubheading" style="bold #fab387"/>
+  <entry type="GenericOutput" style="#cdd6f4"/>
+  <entry type="GenericPrompt" style="#cdd6f4"/>
+  <entry type="GenericError" style="#f38ba8"/>
+  <entry type="GenericTraceback" style="#f38ba8"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/colorful.xml b/styles/embedded/colorful.xml
new file mode 100644
index 0000000..dc74e09
--- /dev/null
+++ b/styles/embedded/colorful.xml
@@ -0,0 +1,52 @@
+<style name="colorful" theme="light">
+  <entry type="Error" style="#ff0000 bg:#ffaaaa"/>
+  <entry type="Background" style="bg:#ffffff"/>
+  <entry type="Keyword" style="bold #008800"/>
+  <entry type="KeywordPseudo" style="#003388"/>
+  <entry type="KeywordType" style="#333399"/>
+  <entry type="NameAttribute" style="#0000cc"/>
+  <entry type="NameBuiltin" style="#007020"/>
+  <entry type="NameClass" style="bold #bb0066"/>
+  <entry type="NameConstant" style="bold #003366"/>
+  <entry type="NameDecorator" style="bold #555555"/>
+  <entry type="NameEntity" style="bold #880000"/>
+  <entry type="NameException" style="bold #ff0000"/>
+  <entry type="NameFunction" style="bold #0066bb"/>
+  <entry type="NameLabel" style="bold #997700"/>
+  <entry type="NameNamespace" style="bold #0e84b5"/>
+  <entry type="NameTag" style="#007700"/>
+  <entry type="NameVariable" style="#996633"/>
+  <entry type="NameVariableClass" style="#336699"/>
+  <entry type="NameVariableGlobal" style="bold #dd7700"/>
+  <entry type="NameVariableInstance" style="#3333bb"/>
+  <entry type="LiteralString" style="bg:#fff0f0"/>
+  <entry type="LiteralStringChar" style="#0044dd"/>
+  <entry type="LiteralStringDoc" style="#dd4422"/>
+  <entry type="LiteralStringEscape" style="bold #666666"/>
+  <entry type="LiteralStringInterpol" style="bg:#eeeeee"/>
+  <entry type="LiteralStringOther" style="#dd2200"/>
+  <entry type="LiteralStringRegex" style="#000000 bg:#fff0ff"/>
+  <entry type="LiteralStringSymbol" style="#aa6600"/>
+  <entry type="LiteralNumber" style="bold #6600ee"/>
+  <entry type="LiteralNumberFloat" style="bold #6600ee"/>
+  <entry type="LiteralNumberHex" style="bold #005588"/>
+  <entry type="LiteralNumberInteger" style="bold #0000dd"/>
+  <entry type="LiteralNumberOct" style="bold #4400ee"/>
+  <entry type="Operator" style="#333333"/>
+  <entry type="OperatorWord" style="bold #000000"/>
+  <entry type="Comment" style="#888888"/>
+  <entry type="CommentSpecial" style="bold #cc0000"/>
+  <entry type="CommentPreproc" style="#557799"/>
+  <entry type="GenericDeleted" style="#a00000"/>
+  <entry type="GenericEmph" style="italic"/>
+  <entry type="GenericError" style="#ff0000"/>
+  <entry type="GenericHeading" style="bold #000080"/>
+  <entry type="GenericInserted" style="#00a000"/>
+  <entry type="GenericOutput" style="#888888"/>
+  <entry type="GenericPrompt" style="bold #c65d09"/>
+  <entry type="GenericStrong" style="bold"/>
+  <entry type="GenericSubheading" style="bold #800080"/>
+  <entry type="GenericTraceback" style="#0044dd"/>
+  <entry type="GenericUnderline" style="underline"/>
+  <entry type="TextWhitespace" style="#bbbbbb"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/doom-one.xml b/styles/embedded/doom-one.xml
new file mode 100644
index 0000000..f5a910a
--- /dev/null
+++ b/styles/embedded/doom-one.xml
@@ -0,0 +1,51 @@
+<style name="doom-one" theme="dark">
+  <entry type="Error" style="#b0c4de"/>
+  <entry type="Background" style="#b0c4de bg:#282c34"/>
+  <entry type="Keyword" style="#c678dd"/>
+  <entry type="KeywordConstant" style="bold #b756ff"/>
+  <entry type="KeywordType" style="#ef8383"/>
+  <entry type="Name" style="#c1abea"/>
+  <entry type="NameAttribute" style="#b3d23c"/>
+  <entry type="NameBuiltin" style="#ef8383"/>
+  <entry type="NameClass" style="#76a9f9"/>
+  <entry type="NameConstant" style="bold #b756ff"/>
+  <entry type="NameDecorator" style="#e5c07b"/>
+  <entry type="NameEntity" style="#bda26f"/>
+  <entry type="NameException" style="bold #fd7474"/>
+  <entry type="NameFunction" style="#00b1f7"/>
+  <entry type="NameLabel" style="#f5a40d"/>
+  <entry type="NameNamespace" style="#76a9f9"/>
+  <entry type="NameProperty" style="#cebc3a"/>
+  <entry type="NameTag" style="#e06c75"/>
+  <entry type="NameVariable" style="#dcaeea"/>
+  <entry type="NameVariableGlobal" style="bold #dcaeea"/>
+  <entry type="NameVariableInstance" style="#e06c75"/>
+  <entry type="Literal" style="#98c379"/>
+  <entry type="LiteralString" style="#98c379"/>
+  <entry type="LiteralStringDoc" style="#7e97c3"/>
+  <entry type="LiteralStringDouble" style="#63c381"/>
+  <entry type="LiteralStringEscape" style="bold #d26464"/>
+  <entry type="LiteralStringHeredoc" style="#98c379"/>
+  <entry type="LiteralStringInterpol" style="#98c379"/>
+  <entry type="LiteralStringOther" style="#70b33f"/>
+  <entry type="LiteralStringRegex" style="#56b6c2"/>
+  <entry type="LiteralStringSingle" style="#98c379"/>
+  <entry type="LiteralStringSymbol" style="#56b6c2"/>
+  <entry type="LiteralNumber" style="#d19a66"/>
+  <entry type="Operator" style="#c7bf54"/>
+  <entry type="OperatorWord" style="bold #b756ff"/>
+  <entry type="Punctuation" style="#b0c4de"/>
+  <entry type="Comment" style="italic #8a93a5"/>
+  <entry type="CommentHashbang" style="bold"/>
+  <entry type="Generic" style="#b0c4de"/>
+  <entry type="GenericEmph" style="italic"/>
+  <entry type="GenericHeading" style="bold #a2cbff"/>
+  <entry type="GenericInserted" style="#a6e22e"/>
+  <entry type="GenericOutput" style="#a6e22e"/>
+  <entry type="GenericPrompt" style="#a6e22e"/>
+  <entry type="GenericStrong" style="bold"/>
+  <entry type="GenericSubheading" style="#a2cbff"/>
+  <entry type="GenericTraceback" style="#a2cbff"/>
+  <entry type="GenericUnderline" style="underline"/>
+  <entry type="Text" style="#b0c4de"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/doom-one2.xml b/styles/embedded/doom-one2.xml
new file mode 100644
index 0000000..d6863f3
--- /dev/null
+++ b/styles/embedded/doom-one2.xml
@@ -0,0 +1,64 @@
+<style name="doom-one2" theme="dark">
+  <entry type="Error" style="#b0c4de"/>
+  <entry type="Background" style="#b0c4de bg:#282c34"/>
+  <entry type="Keyword" style="#76a9f9"/>
+  <entry type="KeywordConstant" style="#e5c07b"/>
+  <entry type="KeywordType" style="#e5c07b"/>
+  <entry type="Name" style="#aa89ea"/>
+  <entry type="NameAttribute" style="#cebc3a"/>
+  <entry type="NameBuiltin" style="#e5c07b"/>
+  <entry type="NameClass" style="#ca72ff"/>
+  <entry type="NameConstant" style="bold"/>
+  <entry type="NameDecorator" style="#e5c07b"/>
+  <entry type="NameEntity" style="#bda26f"/>
+  <entry type="NameException" style="bold #fd7474"/>
+  <entry type="NameFunction" style="#00b1f7"/>
+  <entry type="NameLabel" style="#f5a40d"/>
+  <entry type="NameNamespace" style="#ca72ff"/>
+  <entry type="NameProperty" style="#cebc3a"/>
+  <entry type="NameTag" style="#76a9f9"/>
+  <entry type="NameVariable" style="#dcaeea"/>
+  <entry type="NameVariableClass" style="#dcaeea"/>
+  <entry type="NameVariableGlobal" style="bold #dcaeea"/>
+  <entry type="NameVariableInstance" style="#e06c75"/>
+  <entry type="NameVariableMagic" style="#dcaeea"/>
+  <entry type="Literal" style="#98c379"/>
+  <entry type="LiteralDate" style="#98c379"/>
+  <entry type="LiteralString" style="#98c379"/>
+  <entry type="LiteralStringAffix" style="#98c379"/>
+  <entry type="LiteralStringBacktick" style="#98c379"/>
+  <entry type="LiteralStringDelimiter" style="#98c379"/>
+  <entry type="LiteralStringDoc" style="#7e97c3"/>
+  <entry type="LiteralStringDouble" style="#63c381"/>
+  <entry type="LiteralStringEscape" style="bold #d26464"/>
+  <entry type="LiteralStringHeredoc" style="#98c379"/>
+  <entry type="LiteralStringInterpol" style="#98c379"/>
+  <entry type="LiteralStringOther" style="#70b33f"/>
+  <entry type="LiteralStringRegex" style="#56b6c2"/>
+  <entry type="LiteralStringSingle" style="#98c379"/>
+  <entry type="LiteralStringSymbol" style="#56b6c2"/>
+  <entry type="LiteralNumber" style="#d19a66"/>
+  <entry type="LiteralNumberBin" style="#d19a66"/>
+  <entry type="LiteralNumberFloat" style="#d19a66"/>
+  <entry type="LiteralNumberHex" style="#d19a66"/>
+  <entry type="LiteralNumberInteger" style="#d19a66"/>
+  <entry type="LiteralNumberIntegerLong" style="#d19a66"/>
+  <entry type="LiteralNumberOct" style="#d19a66"/>
+  <entry type="Operator" style="#54b1c7"/>
+  <entry type="OperatorWord" style="bold #b756ff"/>
+  <entry type="Punctuation" style="#abb2bf"/>
+  <entry type="Comment" style="italic #8a93a5"/>
+  <entry type="CommentHashbang" style="bold"/>
+  <entry type="Generic" style="#b0c4de"/>
+  <entry type="GenericDeleted" style="#b0c4de"/>
+  <entry type="GenericEmph" style="italic"/>
+  <entry type="GenericHeading" style="bold #a2cbff"/>
+  <entry type="GenericInserted" style="#a6e22e"/>
+  <entry type="GenericOutput" style="#a6e22e"/>
+  <entry type="GenericPrompt" style="#a6e22e"/>
+  <entry type="GenericStrong" style="bold"/>
+  <entry type="GenericSubheading" style="#a2cbff"/>
+  <entry type="GenericTraceback" style="#a2cbff"/>
+  <entry type="GenericUnderline" style="underline"/>
+  <entry type="Text" style="#b0c4de"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/dracula.xml b/styles/embedded/dracula.xml
new file mode 100644
index 0000000..da436b3
--- /dev/null
+++ b/styles/embedded/dracula.xml
@@ -0,0 +1,74 @@
+<style name="dracula" theme="dark">
+  <entry type="Other" style="#f8f8f2"/>
+  <entry type="Error" style="#f8f8f2"/>
+  <entry type="Background" style="bg:#282a36"/>
+  <entry type="Keyword" style="#ff79c6"/>
+  <entry type="KeywordConstant" style="#ff79c6"/>
+  <entry type="KeywordDeclaration" style="italic #8be9fd"/>
+  <entry type="KeywordNamespace" style="#ff79c6"/>
+  <entry type="KeywordPseudo" style="#ff79c6"/>
+  <entry type="KeywordReserved" style="#ff79c6"/>
+  <entry type="KeywordType" style="#8be9fd"/>
+  <entry type="Name" style="#f8f8f2"/>
+  <entry type="NameAttribute" style="#50fa7b"/>
+  <entry type="NameBuiltin" style="italic #8be9fd"/>
+  <entry type="NameBuiltinPseudo" style="#f8f8f2"/>
+  <entry type="NameClass" style="#50fa7b"/>
+  <entry type="NameConstant" style="#f8f8f2"/>
+  <entry type="NameDecorator" style="#f8f8f2"/>
+  <entry type="NameEntity" style="#f8f8f2"/>
+  <entry type="NameException" style="#f8f8f2"/>
+  <entry type="NameFunction" style="#50fa7b"/>
+  <entry type="NameLabel" style="italic #8be9fd"/>
+  <entry type="NameNamespace" style="#f8f8f2"/>
+  <entry type="NameOther" style="#f8f8f2"/>
+  <entry type="NameTag" style="#ff79c6"/>
+  <entry type="NameVariable" style="italic #8be9fd"/>
+  <entry type="NameVariableClass" style="italic #8be9fd"/>
+  <entry type="NameVariableGlobal" style="italic #8be9fd"/>
+  <entry type="NameVariableInstance" style="italic #8be9fd"/>
+  <entry type="Literal" style="#f8f8f2"/>
+  <entry type="LiteralDate" style="#f8f8f2"/>
+  <entry type="LiteralString" style="#f1fa8c"/>
+  <entry type="LiteralStringBacktick" style="#f1fa8c"/>
+  <entry type="LiteralStringChar" style="#f1fa8c"/>
+  <entry type="LiteralStringDoc" style="#f1fa8c"/>
+  <entry type="LiteralStringDouble" style="#f1fa8c"/>
+  <entry type="LiteralStringEscape" style="#f1fa8c"/>
+  <entry type="LiteralStringHeredoc" style="#f1fa8c"/>
+  <entry type="LiteralStringInterpol" style="#f1fa8c"/>
+  <entry type="LiteralStringOther" style="#f1fa8c"/>
+  <entry type="LiteralStringRegex" style="#f1fa8c"/>
+  <entry type="LiteralStringSingle" style="#f1fa8c"/>
+  <entry type="LiteralStringSymbol" style="#f1fa8c"/>
+  <entry type="LiteralNumber" style="#bd93f9"/>
+  <entry type="LiteralNumberBin" style="#bd93f9"/>
+  <entry type="LiteralNumberFloat" style="#bd93f9"/>
+  <entry type="LiteralNumberHex" style="#bd93f9"/>
+  <entry type="LiteralNumberInteger" style="#bd93f9"/>
+  <entry type="LiteralNumberIntegerLong" style="#bd93f9"/>
+  <entry type="LiteralNumberOct" style="#bd93f9"/>
+  <entry type="Operator" style="#ff79c6"/>
+  <entry type="OperatorWord" style="#ff79c6"/>
+  <entry type="Punctuation" style="#f8f8f2"/>
+  <entry type="Comment" style="#6272a4"/>
+  <entry type="CommentHashbang" style="#6272a4"/>
+  <entry type="CommentMultiline" style="#6272a4"/>
+  <entry type="CommentSingle" style="#6272a4"/>
+  <entry type="CommentSpecial" style="#6272a4"/>
+  <entry type="CommentPreproc" style="#ff79c6"/>
+  <entry type="Generic" style="#f8f8f2"/>
+  <entry type="GenericDeleted" style="#ff5555"/>
+  <entry type="GenericEmph" style="underline #f8f8f2"/>
+  <entry type="GenericError" style="#f8f8f2"/>
+  <entry type="GenericHeading" style="bold #f8f8f2"/>
+  <entry type="GenericInserted" style="bold #50fa7b"/>
+  <entry type="GenericOutput" style="#44475a"/>
+  <entry type="GenericPrompt" style="#f8f8f2"/>
+  <entry type="GenericStrong" style="#f8f8f2"/>
+  <entry type="GenericSubheading" style="bold #f8f8f2"/>
+  <entry type="GenericTraceback" style="#f8f8f2"/>
+  <entry type="GenericUnderline" style="underline"/>
+  <entry type="Text" style="#f8f8f2"/>
+  <entry type="TextWhitespace" style="#f8f8f2"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/emacs.xml b/styles/embedded/emacs.xml
new file mode 100644
index 0000000..dd276f2
--- /dev/null
+++ b/styles/embedded/emacs.xml
@@ -0,0 +1,44 @@
+<style name="emacs" theme="light">
+  <entry type="Error" style="border:#ff0000"/>
+  <entry type="Background" style="bg:#f8f8f8"/>
+  <entry type="Keyword" style="bold #aa22ff"/>
+  <entry type="KeywordPseudo" style="nobold"/>
+  <entry type="KeywordType" style="bold #00bb00"/>
+  <entry type="NameAttribute" style="#bb4444"/>
+  <entry type="NameBuiltin" style="#aa22ff"/>
+  <entry type="NameClass" style="#0000ff"/>
+  <entry type="NameConstant" style="#880000"/>
+  <entry type="NameDecorator" style="#aa22ff"/>
+  <entry type="NameEntity" style="bold #999999"/>
+  <entry type="NameException" style="bold #d2413a"/>
+  <entry type="NameFunction" style="#00a000"/>
+  <entry type="NameLabel" style="#a0a000"/>
+  <entry type="NameNamespace" style="bold #0000ff"/>
+  <entry type="NameTag" style="bold #008000"/>
+  <entry type="NameVariable" style="#b8860b"/>
+  <entry type="LiteralString" style="#bb4444"/>
+  <entry type="LiteralStringDoc" style="italic"/>
+  <entry type="LiteralStringEscape" style="bold #bb6622"/>
+  <entry type="LiteralStringInterpol" style="bold #bb6688"/>
+  <entry type="LiteralStringOther" style="#008000"/>
+  <entry type="LiteralStringRegex" style="#bb6688"/>
+  <entry type="LiteralStringSymbol" style="#b8860b"/>
+  <entry type="LiteralNumber" style="#666666"/>
+  <entry type="Operator" style="#666666"/>
+  <entry type="OperatorWord" style="bold #aa22ff"/>
+  <entry type="Comment" style="italic #008800"/>
+  <entry type="CommentSpecial" style="bold noitalic"/>
+  <entry type="CommentPreproc" style="noitalic"/>
+  <entry type="GenericDeleted" style="#a00000"/>
+  <entry type="GenericEmph" style="italic"/>
+  <entry type="GenericError" style="#ff0000"/>
+  <entry type="GenericHeading" style="bold #000080"/>
+  <entry type="GenericInserted" style="#00a000"/>
+  <entry type="GenericOutput" style="#888888"/>
+  <entry type="GenericPrompt" style="bold #000080"/>
+  <entry type="GenericStrong" style="bold"/>
+  <entry type="GenericSubheading" style="bold #800080"/>
+  <entry type="GenericTraceback" style="#0044dd"/>
+  <entry type="GenericUnderline" style="underline"/>
+  <entry type="TextWhitespace" style="#bbbbbb"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/evergarden.xml b/styles/embedded/evergarden.xml
new file mode 100644
index 0000000..826435d
--- /dev/null
+++ b/styles/embedded/evergarden.xml
@@ -0,0 +1,33 @@
+<style name="evergarden" theme="dark">
+  <entry type="Background" style="noinherit #D6CBB4 bg:#252B2E"/>
+  <entry type="Keyword" style="noinherit #E67E80"/>
+  <entry type="KeywordType" style="noinherit #DBBC7F"/>
+  <entry type="Name" style="#D6CBB4"/>
+  <entry type="NameAttribute" style="bold #D699B6"/>
+  <entry type="NameBuiltin" style="#D699B6"/>
+  <entry type="NameConstant" style="noinherit #D699B6"/>
+  <entry type="NameEntity" style="noinherit #DBBC7F"/>
+  <entry type="NameException" style="noinherit #E67E80"/>
+  <entry type="NameFunction" style="#B2C98F"/>
+  <entry type="NameLabel" style="noinherit #E67E80"/>
+  <entry type="NameTag" style="noinherit #7a8478"/>
+  <entry type="NameVariable" style="noinherit #D6CBB4"/>
+  <entry type="LiteralString" style="noinherit #B2C98F"/>
+  <entry type="LiteralStringSymbol" style="#E69875"/>
+  <entry type="LiteralNumber" style="noinherit #D699B6"/>
+  <entry type="LiteralNumberFloat" style="noinherit #D699B6"/>
+  <entry type="Operator" style="#7a8478"/>
+  <entry type="Comment" style="italic #859289"/>
+  <entry type="CommentPreproc" style="noinherit #E67E80"/>
+  <entry type="Generic" style="#D6CBB4"/>
+  <entry type="GenericDeleted" style="noinherit #252B2E bg:#E67E80"/>
+  <entry type="GenericEmph" style="#6E8585"/>
+  <entry type="GenericError" style="bold bg:#E67E80"/>
+  <entry type="GenericHeading" style="bold #D699B6"/>
+  <entry type="GenericInserted" style="noinherit #252B2E bg:#B2C98F"/>
+  <entry type="GenericOutput" style="noinherit #6E8585"/>
+  <entry type="GenericPrompt" style="#D6CBB4"/>
+  <entry type="GenericStrong" style="#D6CBB4"/>
+  <entry type="GenericSubheading" style="bold #B2C98F"/>
+  <entry type="GenericTraceback" style="bold bg:#E67E80"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/friendly.xml b/styles/embedded/friendly.xml
new file mode 100644
index 0000000..cd583c2
--- /dev/null
+++ b/styles/embedded/friendly.xml
@@ -0,0 +1,44 @@
+<style name="friendly" theme="light">
+  <entry type="Error" style="border:#ff0000"/>
+  <entry type="Background" style="bg:#f0f0f0"/>
+  <entry type="Keyword" style="bold #007020"/>
+  <entry type="KeywordPseudo" style="nobold"/>
+  <entry type="KeywordType" style="nobold #902000"/>
+  <entry type="NameAttribute" style="#4070a0"/>
+  <entry type="NameBuiltin" style="#007020"/>
+  <entry type="NameClass" style="bold #0e84b5"/>
+  <entry type="NameConstant" style="#60add5"/>
+  <entry type="NameDecorator" style="bold #555555"/>
+  <entry type="NameEntity" style="bold #d55537"/>
+  <entry type="NameException" style="#007020"/>
+  <entry type="NameFunction" style="#06287e"/>
+  <entry type="NameLabel" style="bold #002070"/>
+  <entry type="NameNamespace" style="bold #0e84b5"/>
+  <entry type="NameTag" style="bold #062873"/>
+  <entry type="NameVariable" style="#bb60d5"/>
+  <entry type="LiteralString" style="#4070a0"/>
+  <entry type="LiteralStringDoc" style="italic"/>
+  <entry type="LiteralStringEscape" style="bold #4070a0"/>
+  <entry type="LiteralStringInterpol" style="#70a0d0"/>
+  <entry type="LiteralStringOther" style="#c65d09"/>
+  <entry type="LiteralStringRegex" style="#235388"/>
+  <entry type="LiteralStringSymbol" style="#517918"/>
+  <entry type="LiteralNumber" style="#40a070"/>
+  <entry type="Operator" style="#666666"/>
+  <entry type="OperatorWord" style="bold #007020"/>
+  <entry type="Comment" style="italic #60a0b0"/>
+  <entry type="CommentSpecial" style="noitalic bg:#fff0f0"/>
+  <entry type="CommentPreproc" style="noitalic #007020"/>
+  <entry type="GenericDeleted" style="#a00000"/>
+  <entry type="GenericEmph" style="italic"/>
+  <entry type="GenericError" style="#ff0000"/>
+  <entry type="GenericHeading" style="bold #000080"/>
+  <entry type="GenericInserted" style="#00a000"/>
+  <entry type="GenericOutput" style="#888888"/>
+  <entry type="GenericPrompt" style="bold #c65d09"/>
+  <entry type="GenericStrong" style="bold"/>
+  <entry type="GenericSubheading" style="bold #800080"/>
+  <entry type="GenericTraceback" style="#0044dd"/>
+  <entry type="GenericUnderline" style="underline"/>
+  <entry type="TextWhitespace" style="#bbbbbb"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/fruity.xml b/styles/embedded/fruity.xml
new file mode 100644
index 0000000..00b048d
--- /dev/null
+++ b/styles/embedded/fruity.xml
@@ -0,0 +1,19 @@
+<style name="fruity" theme="dark">
+  <entry type="Background" style="#ffffff bg:#111111"/>
+  <entry type="Keyword" style="bold #fb660a"/>
+  <entry type="KeywordPseudo" style="nobold"/>
+  <entry type="KeywordType" style="bold #cdcaa9"/>
+  <entry type="NameAttribute" style="bold #ff0086"/>
+  <entry type="NameConstant" style="#0086d2"/>
+  <entry type="NameFunction" style="bold #ff0086"/>
+  <entry type="NameTag" style="bold #fb660a"/>
+  <entry type="NameVariable" style="#fb660a"/>
+  <entry type="LiteralString" style="#0086d2"/>
+  <entry type="LiteralNumber" style="bold #0086f7"/>
+  <entry type="Comment" style="italic #008800 bg:#0f140f"/>
+  <entry type="CommentPreproc" style="bold #ff0007"/>
+  <entry type="GenericHeading" style="bold #ffffff"/>
+  <entry type="GenericOutput" style="#444444 bg:#222222"/>
+  <entry type="GenericSubheading" style="bold #ffffff"/>
+  <entry type="TextWhitespace" style="#888888"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/github-dark.xml b/styles/embedded/github-dark.xml
new file mode 100644
index 0000000..85b3fc9
--- /dev/null
+++ b/styles/embedded/github-dark.xml
@@ -0,0 +1,45 @@
+<style name="github-dark" theme="dark">
+  <entry type="Error" style="#f85149"/>
+  <entry type="LineHighlight" style="bg:#6e7681"/>
+  <entry type="LineNumbers" style="#6e7681"/>
+  <entry type="Background" style="#e6edf3 bg:#0d1117"/>
+  <entry type="Keyword" style="#ff7b72"/>
+  <entry type="KeywordConstant" style="#79c0ff"/>
+  <entry type="KeywordPseudo" style="#79c0ff"/>
+  <entry type="Name" style="#e6edf3"/>
+  <entry type="NameClass" style="bold #f0883e"/>
+  <entry type="NameConstant" style="bold #79c0ff"/>
+  <entry type="NameDecorator" style="bold #d2a8ff"/>
+  <entry type="NameEntity" style="#ffa657"/>
+  <entry type="NameException" style="bold #f0883e"/>
+  <entry type="NameFunction" style="bold #d2a8ff"/>
+  <entry type="NameLabel" style="bold #79c0ff"/>
+  <entry type="NameNamespace" style="#ff7b72"/>
+  <entry type="NameProperty" style="#79c0ff"/>
+  <entry type="NameTag" style="#7ee787"/>
+  <entry type="NameVariable" style="#79c0ff"/>
+  <entry type="Literal" style="#a5d6ff"/>
+  <entry type="LiteralDate" style="#79c0ff"/>
+  <entry type="LiteralStringAffix" style="#79c0ff"/>
+  <entry type="LiteralStringDelimiter" style="#79c0ff"/>
+  <entry type="LiteralStringEscape" style="#79c0ff"/>
+  <entry type="LiteralStringHeredoc" style="#79c0ff"/>
+  <entry type="LiteralStringRegex" style="#79c0ff"/>
+  <entry type="Operator" style="bold #ff7b72"/>
+  <entry type="Comment" style="italic #8b949e"/>
+  <entry type="CommentSpecial" style="bold italic #8b949e"/>
+  <entry type="CommentPreproc" style="bold #8b949e"/>
+  <entry type="Generic" style="#e6edf3"/>
+  <entry type="GenericDeleted" style="#ffa198 bg:#490202"/>
+  <entry type="GenericEmph" style="italic"/>
+  <entry type="GenericError" style="#ffa198"/>
+  <entry type="GenericHeading" style="bold #79c0ff"/>
+  <entry type="GenericInserted" style="#56d364 bg:#0f5323"/>
+  <entry type="GenericOutput" style="#8b949e"/>
+  <entry type="GenericPrompt" style="#8b949e"/>
+  <entry type="GenericStrong" style="bold"/>
+  <entry type="GenericSubheading" style="#79c0ff"/>
+  <entry type="GenericTraceback" style="#ff7b72"/>
+  <entry type="GenericUnderline" style="underline"/>
+  <entry type="TextWhitespace" style="#6e7681"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/github.xml b/styles/embedded/github.xml
new file mode 100644
index 0000000..06e043a
--- /dev/null
+++ b/styles/embedded/github.xml
@@ -0,0 +1,44 @@
+<style name="github" theme="light">
+  <entry type="Error" style="#a61717 bg:#e3d2d2"/>
+  <entry type="Background" style="bg:#ffffff"/>
+  <entry type="Keyword" style="bold #000000"/>
+  <entry type="KeywordType" style="bold #445588"/>
+  <entry type="NameAttribute" style="#008080"/>
+  <entry type="NameBuiltin" style="#0086b3"/>
+  <entry type="NameBuiltinPseudo" style="#999999"/>
+  <entry type="NameClass" style="bold #445588"/>
+  <entry type="NameConstant" style="#008080"/>
+  <entry type="NameDecorator" style="bold #3c5d5d"/>
+  <entry type="NameEntity" style="#800080"/>
+  <entry type="NameException" style="bold #990000"/>
+  <entry type="NameFunction" style="bold #990000"/>
+  <entry type="NameLabel" style="bold #990000"/>
+  <entry type="NameNamespace" style="#555555"/>
+  <entry type="NameTag" style="#000080"/>
+  <entry type="NameVariable" style="#008080"/>
+  <entry type="NameVariableClass" style="#008080"/>
+  <entry type="NameVariableGlobal" style="#008080"/>
+  <entry type="NameVariableInstance" style="#008080"/>
+  <entry type="LiteralString" style="#dd1144"/>
+  <entry type="LiteralStringRegex" style="#009926"/>
+  <entry type="LiteralStringSymbol" style="#990073"/>
+  <entry type="LiteralNumber" style="#009999"/>
+  <entry type="Operator" style="bold #000000"/>
+  <entry type="Comment" style="italic #999988"/>
+  <entry type="CommentMultiline" style="italic #999988"/>
+  <entry type="CommentSingle" style="italic #999988"/>
+  <entry type="CommentSpecial" style="bold italic #999999"/>
+  <entry type="CommentPreproc" style="bold #999999"/>
+  <entry type="GenericDeleted" style="#000000 bg:#ffdddd"/>
+  <entry type="GenericEmph" style="italic #000000"/>
+  <entry type="GenericError" style="#aa0000"/>
+  <entry type="GenericHeading" style="#999999"/>
+  <entry type="GenericInserted" style="#000000 bg:#ddffdd"/>
+  <entry type="GenericOutput" style="#888888"/>
+  <entry type="GenericPrompt" style="#555555"/>
+  <entry type="GenericStrong" style="bold"/>
+  <entry type="GenericSubheading" style="#aaaaaa"/>
+  <entry type="GenericTraceback" style="#aa0000"/>
+  <entry type="GenericUnderline" style="underline"/>
+  <entry type="TextWhitespace" style="#bbbbbb"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/gruvbox-light.xml b/styles/embedded/gruvbox-light.xml
new file mode 100644
index 0000000..c1293c8
--- /dev/null
+++ b/styles/embedded/gruvbox-light.xml
@@ -0,0 +1,33 @@
+<style name="gruvbox-light" theme="light">
+  <entry type="Background" style="noinherit #3c3836 bg:#fbf1c7"/>
+  <entry type="Keyword" style="noinherit #af3a03"/>
+  <entry type="KeywordType" style="noinherit #b57614"/>
+  <entry type="Name" style="#3c3836"/>
+  <entry type="NameAttribute" style="bold #79740e"/>
+  <entry type="NameBuiltin" style="#b57614"/>
+  <entry type="NameConstant" style="noinherit #d3869b"/>
+  <entry type="NameEntity" style="noinherit #b57614"/>
+  <entry type="NameException" style="noinherit #fb4934"/>
+  <entry type="NameFunction" style="#b57614"/>
+  <entry type="NameLabel" style="noinherit #9d0006"/>
+  <entry type="NameTag" style="noinherit #9d0006"/>
+  <entry type="NameVariable" style="noinherit #3c3836"/>
+  <entry type="LiteralString" style="noinherit #79740e"/>
+  <entry type="LiteralStringSymbol" style="#076678"/>
+  <entry type="LiteralNumber" style="noinherit #8f3f71"/>
+  <entry type="LiteralNumberFloat" style="noinherit #8f3f71"/>
+  <entry type="Operator" style="#af3a03"/>
+  <entry type="Comment" style="italic #928374"/>
+  <entry type="CommentPreproc" style="noinherit #427b58"/>
+  <entry type="Generic" style="#3c3836"/>
+  <entry type="GenericDeleted" style="noinherit #282828 bg:#9d0006"/>
+  <entry type="GenericEmph" style="underline #076678"/>
+  <entry type="GenericError" style="bold bg:#9d0006"/>
+  <entry type="GenericHeading" style="bold #79740e"/>
+  <entry type="GenericInserted" style="noinherit #282828 bg:#79740e"/>
+  <entry type="GenericOutput" style="noinherit #504945"/>
+  <entry type="GenericPrompt" style="#3c3836"/>
+  <entry type="GenericStrong" style="#3c3836"/>
+  <entry type="GenericSubheading" style="bold #79740e"/>
+  <entry type="GenericTraceback" style="bold bg:#3c3836"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/gruvbox.xml b/styles/embedded/gruvbox.xml
new file mode 100644
index 0000000..9cb974d
--- /dev/null
+++ b/styles/embedded/gruvbox.xml
@@ -0,0 +1,33 @@
+<style name="gruvbox" theme="dark">
+  <entry type="Background" style="noinherit #ebdbb2 bg:#282828"/>
+  <entry type="Keyword" style="noinherit #fe8019"/>
+  <entry type="KeywordType" style="noinherit #fabd2f"/>
+  <entry type="Name" style="#ebdbb2"/>
+  <entry type="NameAttribute" style="bold #b8bb26"/>
+  <entry type="NameBuiltin" style="#fabd2f"/>
+  <entry type="NameConstant" style="noinherit #d3869b"/>
+  <entry type="NameEntity" style="noinherit #fabd2f"/>
+  <entry type="NameException" style="noinherit #fb4934"/>
+  <entry type="NameFunction" style="#fabd2f"/>
+  <entry type="NameLabel" style="noinherit #fb4934"/>
+  <entry type="NameTag" style="noinherit #fb4934"/>
+  <entry type="NameVariable" style="noinherit #ebdbb2"/>
+  <entry type="LiteralString" style="noinherit #b8bb26"/>
+  <entry type="LiteralStringSymbol" style="#83a598"/>
+  <entry type="LiteralNumber" style="noinherit #d3869b"/>
+  <entry type="LiteralNumberFloat" style="noinherit #d3869b"/>
+  <entry type="Operator" style="#fe8019"/>
+  <entry type="Comment" style="italic #928374"/>
+  <entry type="CommentPreproc" style="noinherit #8ec07c"/>
+  <entry type="Generic" style="#ebdbb2"/>
+  <entry type="GenericDeleted" style="noinherit #282828 bg:#fb4934"/>
+  <entry type="GenericEmph" style="underline #83a598"/>
+  <entry type="GenericError" style="bold bg:#fb4934"/>
+  <entry type="GenericHeading" style="bold #b8bb26"/>
+  <entry type="GenericInserted" style="noinherit #282828 bg:#b8bb26"/>
+  <entry type="GenericOutput" style="noinherit #504945"/>
+  <entry type="GenericPrompt" style="#ebdbb2"/>
+  <entry type="GenericStrong" style="#ebdbb2"/>
+  <entry type="GenericSubheading" style="bold #b8bb26"/>
+  <entry type="GenericTraceback" style="bold bg:#fb4934"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/hr_high_contrast.xml b/styles/embedded/hr_high_contrast.xml
new file mode 100644
index 0000000..811d5eb
--- /dev/null
+++ b/styles/embedded/hr_high_contrast.xml
@@ -0,0 +1,12 @@
+<style name="hr_high_contrast" theme="light">
+  <entry type="Other" style="#d5d500"/>
+  <entry type="Background" style="#000000"/>
+  <entry type="Keyword" style="#467faf"/>
+  <entry type="Name" style="#ffffff"/>
+  <entry type="LiteralString" style="#a87662"/>
+  <entry type="LiteralStringBoolean" style="#467faf"/>
+  <entry type="LiteralNumber" style="#ffffff"/>
+  <entry type="Operator" style="#e4e400"/>
+  <entry type="OperatorWord" style="#467faf"/>
+  <entry type="Comment" style="#5a8349"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/hrdark.xml b/styles/embedded/hrdark.xml
new file mode 100644
index 0000000..418e713
--- /dev/null
+++ b/styles/embedded/hrdark.xml
@@ -0,0 +1,10 @@
+<style name="hrdark" theme="light">
+  <entry type="Other" style="#ffffff"/>
+  <entry type="Background" style="#1d2432"/>
+  <entry type="Keyword" style="#ff636f"/>
+  <entry type="Name" style="#58a1dd"/>
+  <entry type="Literal" style="#a6be9d"/>
+  <entry type="Operator" style="#ff636f"/>
+  <entry type="OperatorWord" style="#ff636f"/>
+  <entry type="Comment" style="italic #828b96"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/igor.xml b/styles/embedded/igor.xml
new file mode 100644
index 0000000..6957562
--- /dev/null
+++ b/styles/embedded/igor.xml
@@ -0,0 +1,9 @@
+<style name="igor" theme="light">
+  <entry type="Background" style="bg:#ffffff"/>
+  <entry type="Keyword" style="#0000ff"/>
+  <entry type="NameClass" style="#007575"/>
+  <entry type="NameDecorator" style="#cc00a3"/>
+  <entry type="NameFunction" style="#c34e00"/>
+  <entry type="LiteralString" style="#009c00"/>
+  <entry type="Comment" style="italic #ff0000"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/lovelace.xml b/styles/embedded/lovelace.xml
new file mode 100644
index 0000000..d4f9954
--- /dev/null
+++ b/styles/embedded/lovelace.xml
@@ -0,0 +1,53 @@
+<style name="lovelace" theme="light">
+  <entry type="Error" style="bg:#a848a8"/>
+  <entry type="Background" style="bg:#ffffff"/>
+  <entry type="Keyword" style="#2838b0"/>
+  <entry type="KeywordConstant" style="italic #444444"/>
+  <entry type="KeywordDeclaration" style="italic"/>
+  <entry type="KeywordType" style="italic"/>
+  <entry type="NameAttribute" style="#388038"/>
+  <entry type="NameBuiltin" style="#388038"/>
+  <entry type="NameBuiltinPseudo" style="italic"/>
+  <entry type="NameClass" style="#287088"/>
+  <entry type="NameConstant" style="#b85820"/>
+  <entry type="NameDecorator" style="#287088"/>
+  <entry type="NameEntity" style="#709030"/>
+  <entry type="NameException" style="#908828"/>
+  <entry type="NameFunction" style="#785840"/>
+  <entry type="NameFunctionMagic" style="#b85820"/>
+  <entry type="NameLabel" style="#289870"/>
+  <entry type="NameNamespace" style="#289870"/>
+  <entry type="NameTag" style="#2838b0"/>
+  <entry type="NameVariable" style="#b04040"/>
+  <entry type="NameVariableGlobal" style="#908828"/>
+  <entry type="NameVariableMagic" style="#b85820"/>
+  <entry type="LiteralString" style="#b83838"/>
+  <entry type="LiteralStringAffix" style="#444444"/>
+  <entry type="LiteralStringChar" style="#a848a8"/>
+  <entry type="LiteralStringDelimiter" style="#b85820"/>
+  <entry type="LiteralStringDoc" style="italic #b85820"/>
+  <entry type="LiteralStringEscape" style="#709030"/>
+  <entry type="LiteralStringInterpol" style="underline"/>
+  <entry type="LiteralStringOther" style="#a848a8"/>
+  <entry type="LiteralStringRegex" style="#a848a8"/>
+  <entry type="LiteralNumber" style="#444444"/>
+  <entry type="Operator" style="#666666"/>
+  <entry type="OperatorWord" style="#a848a8"/>
+  <entry type="Punctuation" style="#888888"/>
+  <entry type="Comment" style="italic #888888"/>
+  <entry type="CommentHashbang" style="#287088"/>
+  <entry type="CommentMultiline" style="#888888"/>
+  <entry type="CommentPreproc" style="noitalic #289870"/>
+  <entry type="GenericDeleted" style="#c02828"/>
+  <entry type="GenericEmph" style="italic"/>
+  <entry type="GenericError" style="#c02828"/>
+  <entry type="GenericHeading" style="#666666"/>
+  <entry type="GenericInserted" style="#388038"/>
+  <entry type="GenericOutput" style="#666666"/>
+  <entry type="GenericPrompt" style="#444444"/>
+  <entry type="GenericStrong" style="bold"/>
+  <entry type="GenericSubheading" style="#444444"/>
+  <entry type="GenericTraceback" style="#2838b0"/>
+  <entry type="GenericUnderline" style="underline"/>
+  <entry type="TextWhitespace" style="#a89028"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/manni.xml b/styles/embedded/manni.xml
new file mode 100644
index 0000000..b1c5f88
--- /dev/null
+++ b/styles/embedded/manni.xml
@@ -0,0 +1,44 @@
+<style name="manni" theme="light">
+  <entry type="Error" style="#aa0000 bg:#ffaaaa"/>
+  <entry type="Background" style="bg:#f0f3f3"/>
+  <entry type="Keyword" style="bold #006699"/>
+  <entry type="KeywordPseudo" style="nobold"/>
+  <entry type="KeywordType" style="#007788"/>
+  <entry type="NameAttribute" style="#330099"/>
+  <entry type="NameBuiltin" style="#336666"/>
+  <entry type="NameClass" style="bold #00aa88"/>
+  <entry type="NameConstant" style="#336600"/>
+  <entry type="NameDecorator" style="#9999ff"/>
+  <entry type="NameEntity" style="bold #999999"/>
+  <entry type="NameException" style="bold #cc0000"/>
+  <entry type="NameFunction" style="#cc00ff"/>
+  <entry type="NameLabel" style="#9999ff"/>
+  <entry type="NameNamespace" style="bold #00ccff"/>
+  <entry type="NameTag" style="bold #330099"/>
+  <entry type="NameVariable" style="#003333"/>
+  <entry type="LiteralString" style="#cc3300"/>
+  <entry type="LiteralStringDoc" style="italic"/>
+  <entry type="LiteralStringEscape" style="bold #cc3300"/>
+  <entry type="LiteralStringInterpol" style="#aa0000"/>
+  <entry type="LiteralStringOther" style="#cc3300"/>
+  <entry type="LiteralStringRegex" style="#33aaaa"/>
+  <entry type="LiteralStringSymbol" style="#ffcc33"/>
+  <entry type="LiteralNumber" style="#ff6600"/>
+  <entry type="Operator" style="#555555"/>
+  <entry type="OperatorWord" style="bold #000000"/>
+  <entry type="Comment" style="italic #0099ff"/>
+  <entry type="CommentSpecial" style="bold"/>
+  <entry type="CommentPreproc" style="noitalic #009999"/>
+  <entry type="GenericDeleted" style="bg:#ffcccc border:#cc0000"/>
+  <entry type="GenericEmph" style="italic"/>
+  <entry type="GenericError" style="#ff0000"/>
+  <entry type="GenericHeading" style="bold #003300"/>
+  <entry type="GenericInserted" style="bg:#ccffcc border:#00cc00"/>
+  <entry type="GenericOutput" style="#aaaaaa"/>
+  <entry type="GenericPrompt" style="bold #000099"/>
+  <entry type="GenericStrong" style="bold"/>
+  <entry type="GenericSubheading" style="bold #003300"/>
+  <entry type="GenericTraceback" style="#99cc66"/>
+  <entry type="GenericUnderline" style="underline"/>
+  <entry type="TextWhitespace" style="#bbbbbb"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/modus-operandi.xml b/styles/embedded/modus-operandi.xml
new file mode 100644
index 0000000..7fa72d9
--- /dev/null
+++ b/styles/embedded/modus-operandi.xml
@@ -0,0 +1,13 @@
+<style name="modus-operandi" theme="light">
+  <entry type="Background" style="#000000 bg:#ffffff"/>
+  <entry type="Keyword" style="#5317ac"/>
+  <entry type="KeywordConstant" style="#0000c0"/>
+  <entry type="KeywordType" style="#005a5f"/>
+  <entry type="NameBuiltin" style="#8f0075"/>
+  <entry type="NameFunction" style="#721045"/>
+  <entry type="NameVariable" style="#00538b"/>
+  <entry type="Literal" style="#0000c0"/>
+  <entry type="LiteralString" style="#2544bb"/>
+  <entry type="Operator" style="#00538b"/>
+  <entry type="Comment" style="#505050"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/modus-vivendi.xml b/styles/embedded/modus-vivendi.xml
new file mode 100644
index 0000000..62fff97
--- /dev/null
+++ b/styles/embedded/modus-vivendi.xml
@@ -0,0 +1,13 @@
+<style name="modus-vivendi" theme="dark">
+  <entry type="Background" style="#ffffff bg:#000000"/>
+  <entry type="Keyword" style="#b6a0ff"/>
+  <entry type="KeywordConstant" style="#00bcff"/>
+  <entry type="KeywordType" style="#6ae4b9"/>
+  <entry type="NameBuiltin" style="#f78fe7"/>
+  <entry type="NameFunction" style="#feacd0"/>
+  <entry type="NameVariable" style="#00d3d0"/>
+  <entry type="Literal" style="#00bcff"/>
+  <entry type="LiteralString" style="#79a8ff"/>
+  <entry type="Operator" style="#00d3d0"/>
+  <entry type="Comment" style="#a8a8a8"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/monokai.xml b/styles/embedded/monokai.xml
new file mode 100644
index 0000000..e5ce083
--- /dev/null
+++ b/styles/embedded/monokai.xml
@@ -0,0 +1,29 @@
+<style name="monokai" theme="dark">
+  <entry type="Error" style="#960050 bg:#1e0010"/>
+  <entry type="Background" style="bg:#272822"/>
+  <entry type="Keyword" style="#66d9ef"/>
+  <entry type="KeywordNamespace" style="#f92672"/>
+  <entry type="Name" style="#f8f8f2"/>
+  <entry type="NameAttribute" style="#a6e22e"/>
+  <entry type="NameClass" style="#a6e22e"/>
+  <entry type="NameConstant" style="#66d9ef"/>
+  <entry type="NameDecorator" style="#a6e22e"/>
+  <entry type="NameException" style="#a6e22e"/>
+  <entry type="NameFunction" style="#a6e22e"/>
+  <entry type="NameOther" style="#a6e22e"/>
+  <entry type="NameTag" style="#f92672"/>
+  <entry type="Literal" style="#ae81ff"/>
+  <entry type="LiteralDate" style="#e6db74"/>
+  <entry type="LiteralString" style="#e6db74"/>
+  <entry type="LiteralStringEscape" style="#ae81ff"/>
+  <entry type="LiteralNumber" style="#ae81ff"/>
+  <entry type="Operator" style="#f92672"/>
+  <entry type="Punctuation" style="#f8f8f2"/>
+  <entry type="Comment" style="#75715e"/>
+  <entry type="GenericDeleted" style="#f92672"/>
+  <entry type="GenericEmph" style="italic"/>
+  <entry type="GenericInserted" style="#a6e22e"/>
+  <entry type="GenericStrong" style="bold"/>
+  <entry type="GenericSubheading" style="#75715e"/>
+  <entry type="Text" style="#f8f8f2"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/monokailight.xml b/styles/embedded/monokailight.xml
new file mode 100644
index 0000000..27bb8f0
--- /dev/null
+++ b/styles/embedded/monokailight.xml
@@ -0,0 +1,26 @@
+<style name="monokailight" theme="light">
+  <entry type="Error" style="#960050 bg:#1e0010"/>
+  <entry type="Background" style="bg:#fafafa"/>
+  <entry type="Keyword" style="#00a8c8"/>
+  <entry type="KeywordNamespace" style="#f92672"/>
+  <entry type="Name" style="#111111"/>
+  <entry type="NameAttribute" style="#75af00"/>
+  <entry type="NameClass" style="#75af00"/>
+  <entry type="NameConstant" style="#00a8c8"/>
+  <entry type="NameDecorator" style="#75af00"/>
+  <entry type="NameException" style="#75af00"/>
+  <entry type="NameFunction" style="#75af00"/>
+  <entry type="NameOther" style="#75af00"/>
+  <entry type="NameTag" style="#f92672"/>
+  <entry type="Literal" style="#ae81ff"/>
+  <entry type="LiteralDate" style="#d88200"/>
+  <entry type="LiteralString" style="#d88200"/>
+  <entry type="LiteralStringEscape" style="#8045ff"/>
+  <entry type="LiteralNumber" style="#ae81ff"/>
+  <entry type="Operator" style="#f92672"/>
+  <entry type="Punctuation" style="#111111"/>
+  <entry type="Comment" style="#75715e"/>
+  <entry type="GenericEmph" style="italic"/>
+  <entry type="GenericStrong" style="bold"/>
+  <entry type="Text" style="#272822"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/murphy.xml b/styles/embedded/murphy.xml
new file mode 100644
index 0000000..867d9ee
--- /dev/null
+++ b/styles/embedded/murphy.xml
@@ -0,0 +1,52 @@
+<style name="murphy" theme="light">
+  <entry type="Error" style="#ff0000 bg:#ffaaaa"/>
+  <entry type="Background" style="bg:#ffffff"/>
+  <entry type="Keyword" style="bold #228899"/>
+  <entry type="KeywordPseudo" style="#0088ff"/>
+  <entry type="KeywordType" style="#6666ff"/>
+  <entry type="NameAttribute" style="#000077"/>
+  <entry type="NameBuiltin" style="#007722"/>
+  <entry type="NameClass" style="bold #ee99ee"/>
+  <entry type="NameConstant" style="bold #55eedd"/>
+  <entry type="NameDecorator" style="bold #555555"/>
+  <entry type="NameEntity" style="#880000"/>
+  <entry type="NameException" style="bold #ff0000"/>
+  <entry type="NameFunction" style="bold #55eedd"/>
+  <entry type="NameLabel" style="bold #997700"/>
+  <entry type="NameNamespace" style="bold #0e84b5"/>
+  <entry type="NameTag" style="#007700"/>
+  <entry type="NameVariable" style="#003366"/>
+  <entry type="NameVariableClass" style="#ccccff"/>
+  <entry type="NameVariableGlobal" style="#ff8844"/>
+  <entry type="NameVariableInstance" style="#aaaaff"/>
+  <entry type="LiteralString" style="bg:#e0e0ff"/>
+  <entry type="LiteralStringChar" style="#8888ff"/>
+  <entry type="LiteralStringDoc" style="#dd4422"/>
+  <entry type="LiteralStringEscape" style="bold #666666"/>
+  <entry type="LiteralStringInterpol" style="bg:#eeeeee"/>
+  <entry type="LiteralStringOther" style="#ff8888"/>
+  <entry type="LiteralStringRegex" style="#000000 bg:#e0e0ff"/>
+  <entry type="LiteralStringSymbol" style="#ffcc88"/>
+  <entry type="LiteralNumber" style="bold #6600ee"/>
+  <entry type="LiteralNumberFloat" style="bold #6600ee"/>
+  <entry type="LiteralNumberHex" style="bold #005588"/>
+  <entry type="LiteralNumberInteger" style="bold #6666ff"/>
+  <entry type="LiteralNumberOct" style="bold #4400ee"/>
+  <entry type="Operator" style="#333333"/>
+  <entry type="OperatorWord" style="bold #000000"/>
+  <entry type="Comment" style="italic #666666"/>
+  <entry type="CommentSpecial" style="bold #cc0000"/>
+  <entry type="CommentPreproc" style="noitalic #557799"/>
+  <entry type="GenericDeleted" style="#a00000"/>
+  <entry type="GenericEmph" style="italic"/>
+  <entry type="GenericError" style="#ff0000"/>
+  <entry type="GenericHeading" style="bold #000080"/>
+  <entry type="GenericInserted" style="#00a000"/>
+  <entry type="GenericOutput" style="#888888"/>
+  <entry type="GenericPrompt" style="bold #c65d09"/>
+  <entry type="GenericStrong" style="bold"/>
+  <entry type="GenericSubheading" style="bold #800080"/>
+  <entry type="GenericTraceback" style="#0044dd"/>
+  <entry type="GenericUnderline" style="underline"/>
+  <entry type="TextWhitespace" style="#bbbbbb"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/native.xml b/styles/embedded/native.xml
new file mode 100644
index 0000000..e60fb3a
--- /dev/null
+++ b/styles/embedded/native.xml
@@ -0,0 +1,35 @@
+<style name="native" theme="dark">
+  <entry type="Error" style="#a61717 bg:#e3d2d2"/>
+  <entry type="Background" style="#d0d0d0 bg:#202020"/>
+  <entry type="Keyword" style="bold #6ab825"/>
+  <entry type="KeywordPseudo" style="nobold"/>
+  <entry type="NameAttribute" style="#bbbbbb"/>
+  <entry type="NameBuiltin" style="#24909d"/>
+  <entry type="NameClass" style="underline #447fcf"/>
+  <entry type="NameConstant" style="#40ffff"/>
+  <entry type="NameDecorator" style="#ffa500"/>
+  <entry type="NameException" style="#bbbbbb"/>
+  <entry type="NameFunction" style="#447fcf"/>
+  <entry type="NameNamespace" style="underline #447fcf"/>
+  <entry type="NameTag" style="bold #6ab825"/>
+  <entry type="NameVariable" style="#40ffff"/>
+  <entry type="LiteralString" style="#ed9d13"/>
+  <entry type="LiteralStringOther" style="#ffa500"/>
+  <entry type="LiteralNumber" style="#3677a9"/>
+  <entry type="OperatorWord" style="bold #6ab825"/>
+  <entry type="Comment" style="italic #999999"/>
+  <entry type="CommentSpecial" style="bold noitalic #e50808 bg:#520000"/>
+  <entry type="CommentPreproc" style="bold noitalic #cd2828"/>
+  <entry type="GenericDeleted" style="#d22323"/>
+  <entry type="GenericEmph" style="italic"/>
+  <entry type="GenericError" style="#d22323"/>
+  <entry type="GenericHeading" style="bold #ffffff"/>
+  <entry type="GenericInserted" style="#589819"/>
+  <entry type="GenericOutput" style="#cccccc"/>
+  <entry type="GenericPrompt" style="#aaaaaa"/>
+  <entry type="GenericStrong" style="bold"/>
+  <entry type="GenericSubheading" style="underline #ffffff"/>
+  <entry type="GenericTraceback" style="#d22323"/>
+  <entry type="GenericUnderline" style="underline"/>
+  <entry type="TextWhitespace" style="#666666"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/nord.xml b/styles/embedded/nord.xml
new file mode 100644
index 0000000..0004fd7
--- /dev/null
+++ b/styles/embedded/nord.xml
@@ -0,0 +1,46 @@
+<style name="nord" theme="dark">
+  <entry type="Error" style="#bf616a"/>
+  <entry type="Background" style="#d8dee9 bg:#2e3440"/>
+  <entry type="Keyword" style="bold #81a1c1"/>
+  <entry type="KeywordPseudo" style="nobold #81a1c1"/>
+  <entry type="KeywordType" style="nobold #81a1c1"/>
+  <entry type="Name" style="#d8dee9"/>
+  <entry type="NameAttribute" style="#8fbcbb"/>
+  <entry type="NameBuiltin" style="#81a1c1"/>
+  <entry type="NameClass" style="#8fbcbb"/>
+  <entry type="NameConstant" style="#8fbcbb"/>
+  <entry type="NameDecorator" style="#d08770"/>
+  <entry type="NameEntity" style="#d08770"/>
+  <entry type="NameException" style="#bf616a"/>
+  <entry type="NameFunction" style="#88c0d0"/>
+  <entry type="NameLabel" style="#8fbcbb"/>
+  <entry type="NameNamespace" style="#8fbcbb"/>
+  <entry type="NameOther" style="#d8dee9"/>
+  <entry type="NameTag" style="#81a1c1"/>
+  <entry type="NameVariable" style="#d8dee9"/>
+  <entry type="NameProperty" style="#8fbcbb"/>
+  <entry type="LiteralString" style="#a3be8c"/>
+  <entry type="LiteralStringDoc" style="#616e87"/>
+  <entry type="LiteralStringEscape" style="#ebcb8b"/>
+  <entry type="LiteralStringInterpol" style="#a3be8c"/>
+  <entry type="LiteralStringOther" style="#a3be8c"/>
+  <entry type="LiteralStringRegex" style="#ebcb8b"/>
+  <entry type="LiteralStringSymbol" style="#a3be8c"/>
+  <entry type="LiteralNumber" style="#b48ead"/>
+  <entry type="Operator" style="#81a1c1"/>
+  <entry type="OperatorWord" style="bold #81a1c1"/>
+  <entry type="Punctuation" style="#eceff4"/>
+  <entry type="Comment" style="italic #616e87"/>
+  <entry type="CommentPreproc" style="#5e81ac"/>
+  <entry type="GenericDeleted" style="#bf616a"/>
+  <entry type="GenericEmph" style="italic"/>
+  <entry type="GenericError" style="#bf616a"/>
+  <entry type="GenericHeading" style="bold #88c0d0"/>
+  <entry type="GenericInserted" style="#a3be8c"/>
+  <entry type="GenericOutput" style="#d8dee9"/>
+  <entry type="GenericPrompt" style="bold #4c566a"/>
+  <entry type="GenericStrong" style="bold"/>
+  <entry type="GenericSubheading" style="bold #88c0d0"/>
+  <entry type="GenericTraceback" style="#bf616a"/>
+  <entry type="TextWhitespace" style="#d8dee9"/>
+</style>
diff --git a/styles/embedded/onedark.xml b/styles/embedded/onedark.xml
new file mode 100644
index 0000000..9ce9d17
--- /dev/null
+++ b/styles/embedded/onedark.xml
@@ -0,0 +1,25 @@
+<style name="onedark" theme="dark">
+  <entry type="Background" style="#ABB2BF bg:#282C34"/>
+  <entry type="Punctuation" style="#ABB2BF"/>
+  <entry type="Keyword" style="#C678DD"/>
+  <entry type="KeywordConstant" style="#E5C07B"/>
+  <entry type="KeywordDeclaration" style="#C678DD"/>
+  <entry type="KeywordNamespace" style="#C678DD"/>
+  <entry type="KeywordReserved" style="#C678DD"/>
+  <entry type="KeywordType" style="#E5C07B"/>
+  <entry type="Name" style="#E06C75"/>
+  <entry type="NameAttribute" style="#E06C75"/>
+  <entry type="NameBuiltin" style="#E5C07B"/>
+  <entry type="NameClass" style="#E5C07B"/>
+  <entry type="NameFunction" style="bold #61AFEF"/>
+  <entry type="NameFunctionMagic" style="bold #56B6C2"/>
+  <entry type="NameOther" style="#E06C75"/>
+  <entry type="NameTag" style="#E06C75"/>
+  <entry type="NameDecorator" style="#61AFEF"/>
+  <entry type="LiteralString" style="#98C379"/>
+  <entry type="LiteralNumber" style="#D19A66"/>
+  <entry type="Operator" style="#56B6C2"/>
+  <entry type="Comment" style="#7F848E"/>
+  <entry type="GenericDeleted" style="#E06C75"/>
+  <entry type="GenericInserted" style="bold #98C379"/>
+</style>
diff --git a/styles/embedded/onesenterprise.xml b/styles/embedded/onesenterprise.xml
new file mode 100644
index 0000000..efe93b8
--- /dev/null
+++ b/styles/embedded/onesenterprise.xml
@@ -0,0 +1,10 @@
+<style name="onesenterprise" theme="light">
+  <entry type="Keyword" style="#ff0000"/>
+  <entry type="Name" style="#0000ff"/>
+  <entry type="LiteralString" style="#000000"/>
+  <entry type="Operator" style="#ff0000"/>
+  <entry type="Punctuation" style="#ff0000"/>
+  <entry type="Comment" style="#008000"/>
+  <entry type="CommentPreproc" style="#963200"/>
+  <entry type="Text" style="#000000"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/paraiso-dark.xml b/styles/embedded/paraiso-dark.xml
new file mode 100644
index 0000000..45e0aa0
--- /dev/null
+++ b/styles/embedded/paraiso-dark.xml
@@ -0,0 +1,37 @@
+<style name="paraiso-dark" theme="dark">
+  <entry type="Error" style="#ef6155"/>
+  <entry type="Background" style="bg:#2f1e2e"/>
+  <entry type="Keyword" style="#815ba4"/>
+  <entry type="KeywordNamespace" style="#5bc4bf"/>
+  <entry type="KeywordType" style="#fec418"/>
+  <entry type="Name" style="#e7e9db"/>
+  <entry type="NameAttribute" style="#06b6ef"/>
+  <entry type="NameClass" style="#fec418"/>
+  <entry type="NameConstant" style="#ef6155"/>
+  <entry type="NameDecorator" style="#5bc4bf"/>
+  <entry type="NameException" style="#ef6155"/>
+  <entry type="NameFunction" style="#06b6ef"/>
+  <entry type="NameNamespace" style="#fec418"/>
+  <entry type="NameOther" style="#06b6ef"/>
+  <entry type="NameTag" style="#5bc4bf"/>
+  <entry type="NameVariable" style="#ef6155"/>
+  <entry type="Literal" style="#f99b15"/>
+  <entry type="LiteralDate" style="#48b685"/>
+  <entry type="LiteralString" style="#48b685"/>
+  <entry type="LiteralStringChar" style="#e7e9db"/>
+  <entry type="LiteralStringDoc" style="#776e71"/>
+  <entry type="LiteralStringEscape" style="#f99b15"/>
+  <entry type="LiteralStringInterpol" style="#f99b15"/>
+  <entry type="LiteralNumber" style="#f99b15"/>
+  <entry type="Operator" style="#5bc4bf"/>
+  <entry type="Punctuation" style="#e7e9db"/>
+  <entry type="Comment" style="#776e71"/>
+  <entry type="GenericDeleted" style="#ef6155"/>
+  <entry type="GenericEmph" style="italic"/>
+  <entry type="GenericHeading" style="bold #e7e9db"/>
+  <entry type="GenericInserted" style="#48b685"/>
+  <entry type="GenericPrompt" style="bold #776e71"/>
+  <entry type="GenericStrong" style="bold"/>
+  <entry type="GenericSubheading" style="bold #5bc4bf"/>
+  <entry type="Text" style="#e7e9db"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/paraiso-light.xml b/styles/embedded/paraiso-light.xml
new file mode 100644
index 0000000..f4e7ef6
--- /dev/null
+++ b/styles/embedded/paraiso-light.xml
@@ -0,0 +1,37 @@
+<style name="paraiso-light" theme="light">
+  <entry type="Error" style="#ef6155"/>
+  <entry type="Background" style="bg:#e7e9db"/>
+  <entry type="Keyword" style="#815ba4"/>
+  <entry type="KeywordNamespace" style="#5bc4bf"/>
+  <entry type="KeywordType" style="#fec418"/>
+  <entry type="Name" style="#2f1e2e"/>
+  <entry type="NameAttribute" style="#06b6ef"/>
+  <entry type="NameClass" style="#fec418"/>
+  <entry type="NameConstant" style="#ef6155"/>
+  <entry type="NameDecorator" style="#5bc4bf"/>
+  <entry type="NameException" style="#ef6155"/>
+  <entry type="NameFunction" style="#06b6ef"/>
+  <entry type="NameNamespace" style="#fec418"/>
+  <entry type="NameOther" style="#06b6ef"/>
+  <entry type="NameTag" style="#5bc4bf"/>
+  <entry type="NameVariable" style="#ef6155"/>
+  <entry type="Literal" style="#f99b15"/>
+  <entry type="LiteralDate" style="#48b685"/>
+  <entry type="LiteralString" style="#48b685"/>
+  <entry type="LiteralStringChar" style="#2f1e2e"/>
+  <entry type="LiteralStringDoc" style="#8d8687"/>
+  <entry type="LiteralStringEscape" style="#f99b15"/>
+  <entry type="LiteralStringInterpol" style="#f99b15"/>
+  <entry type="LiteralNumber" style="#f99b15"/>
+  <entry type="Operator" style="#5bc4bf"/>
+  <entry type="Punctuation" style="#2f1e2e"/>
+  <entry type="Comment" style="#8d8687"/>
+  <entry type="GenericDeleted" style="#ef6155"/>
+  <entry type="GenericEmph" style="italic"/>
+  <entry type="GenericHeading" style="bold #2f1e2e"/>
+  <entry type="GenericInserted" style="#48b685"/>
+  <entry type="GenericPrompt" style="bold #8d8687"/>
+  <entry type="GenericStrong" style="bold"/>
+  <entry type="GenericSubheading" style="bold #5bc4bf"/>
+  <entry type="Text" style="#2f1e2e"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/pastie.xml b/styles/embedded/pastie.xml
new file mode 100644
index 0000000..56297b1
--- /dev/null
+++ b/styles/embedded/pastie.xml
@@ -0,0 +1,45 @@
+<style name="pastie" theme="light">
+  <entry type="Error" style="#a61717 bg:#e3d2d2"/>
+  <entry type="Background" style="bg:#ffffff"/>
+  <entry type="Keyword" style="bold #008800"/>
+  <entry type="KeywordPseudo" style="nobold"/>
+  <entry type="KeywordType" style="#888888"/>
+  <entry type="NameAttribute" style="#336699"/>
+  <entry type="NameBuiltin" style="#003388"/>
+  <entry type="NameClass" style="bold #bb0066"/>
+  <entry type="NameConstant" style="bold #003366"/>
+  <entry type="NameDecorator" style="#555555"/>
+  <entry type="NameException" style="bold #bb0066"/>
+  <entry type="NameFunction" style="bold #0066bb"/>
+  <entry type="NameLabel" style="italic #336699"/>
+  <entry type="NameNamespace" style="bold #bb0066"/>
+  <entry type="NameProperty" style="bold #336699"/>
+  <entry type="NameTag" style="bold #bb0066"/>
+  <entry type="NameVariable" style="#336699"/>
+  <entry type="NameVariableClass" style="#336699"/>
+  <entry type="NameVariableGlobal" style="#dd7700"/>
+  <entry type="NameVariableInstance" style="#3333bb"/>
+  <entry type="LiteralString" style="#dd2200 bg:#fff0f0"/>
+  <entry type="LiteralStringEscape" style="#0044dd"/>
+  <entry type="LiteralStringInterpol" style="#3333bb"/>
+  <entry type="LiteralStringOther" style="#22bb22 bg:#f0fff0"/>
+  <entry type="LiteralStringRegex" style="#008800 bg:#fff0ff"/>
+  <entry type="LiteralStringSymbol" style="#aa6600"/>
+  <entry type="LiteralNumber" style="bold #0000dd"/>
+  <entry type="OperatorWord" style="#008800"/>
+  <entry type="Comment" style="#888888"/>
+  <entry type="CommentSpecial" style="bold #cc0000 bg:#fff0f0"/>
+  <entry type="CommentPreproc" style="bold #cc0000"/>
+  <entry type="GenericDeleted" style="#000000 bg:#ffdddd"/>
+  <entry type="GenericEmph" style="italic"/>
+  <entry type="GenericError" style="#aa0000"/>
+  <entry type="GenericHeading" style="#333333"/>
+  <entry type="GenericInserted" style="#000000 bg:#ddffdd"/>
+  <entry type="GenericOutput" style="#888888"/>
+  <entry type="GenericPrompt" style="#555555"/>
+  <entry type="GenericStrong" style="bold"/>
+  <entry type="GenericSubheading" style="#666666"/>
+  <entry type="GenericTraceback" style="#aa0000"/>
+  <entry type="GenericUnderline" style="underline"/>
+  <entry type="TextWhitespace" style="#bbbbbb"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/perldoc.xml b/styles/embedded/perldoc.xml
new file mode 100644
index 0000000..6521246
--- /dev/null
+++ b/styles/embedded/perldoc.xml
@@ -0,0 +1,37 @@
+<style name="perldoc" theme="light">
+  <entry type="Error" style="#a61717 bg:#e3d2d2"/>
+  <entry type="Background" style="bg:#eeeedd"/>
+  <entry type="Keyword" style="bold #8b008b"/>
+  <entry type="KeywordType" style="#00688b"/>
+  <entry type="NameAttribute" style="#658b00"/>
+  <entry type="NameBuiltin" style="#658b00"/>
+  <entry type="NameClass" style="bold #008b45"/>
+  <entry type="NameConstant" style="#00688b"/>
+  <entry type="NameDecorator" style="#707a7c"/>
+  <entry type="NameException" style="bold #008b45"/>
+  <entry type="NameFunction" style="#008b45"/>
+  <entry type="NameNamespace" style="underline #008b45"/>
+  <entry type="NameTag" style="bold #8b008b"/>
+  <entry type="NameVariable" style="#00688b"/>
+  <entry type="LiteralString" style="#cd5555"/>
+  <entry type="LiteralStringHeredoc" style="italic #1c7e71"/>
+  <entry type="LiteralStringOther" style="#cb6c20"/>
+  <entry type="LiteralStringRegex" style="#1c7e71"/>
+  <entry type="LiteralNumber" style="#b452cd"/>
+  <entry type="OperatorWord" style="#8b008b"/>
+  <entry type="Comment" style="#228b22"/>
+  <entry type="CommentSpecial" style="bold #8b008b"/>
+  <entry type="CommentPreproc" style="#1e889b"/>
+  <entry type="GenericDeleted" style="#aa0000"/>
+  <entry type="GenericEmph" style="italic"/>
+  <entry type="GenericError" style="#aa0000"/>
+  <entry type="GenericHeading" style="bold #000080"/>
+  <entry type="GenericInserted" style="#00aa00"/>
+  <entry type="GenericOutput" style="#888888"/>
+  <entry type="GenericPrompt" style="#555555"/>
+  <entry type="GenericStrong" style="bold"/>
+  <entry type="GenericSubheading" style="bold #800080"/>
+  <entry type="GenericTraceback" style="#aa0000"/>
+  <entry type="GenericUnderline" style="underline"/>
+  <entry type="TextWhitespace" style="#bbbbbb"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/pygments.xml b/styles/embedded/pygments.xml
new file mode 100644
index 0000000..ffbd782
--- /dev/null
+++ b/styles/embedded/pygments.xml
@@ -0,0 +1,42 @@
+<style name="pygments" theme="light">
+  <entry type="Error" style="border:#ff0000"/>
+  <entry type="Keyword" style="bold #008000"/>
+  <entry type="KeywordPseudo" style="nobold"/>
+  <entry type="KeywordType" style="nobold #b00040"/>
+  <entry type="NameAttribute" style="#7d9029"/>
+  <entry type="NameBuiltin" style="#008000"/>
+  <entry type="NameClass" style="bold #0000ff"/>
+  <entry type="NameConstant" style="#880000"/>
+  <entry type="NameDecorator" style="#aa22ff"/>
+  <entry type="NameEntity" style="bold #999999"/>
+  <entry type="NameException" style="bold #d2413a"/>
+  <entry type="NameFunction" style="#0000ff"/>
+  <entry type="NameLabel" style="#a0a000"/>
+  <entry type="NameNamespace" style="bold #0000ff"/>
+  <entry type="NameTag" style="bold #008000"/>
+  <entry type="NameVariable" style="#19177c"/>
+  <entry type="LiteralString" style="#ba2121"/>
+  <entry type="LiteralStringDoc" style="italic"/>
+  <entry type="LiteralStringEscape" style="bold #bb6622"/>
+  <entry type="LiteralStringInterpol" style="bold #bb6688"/>
+  <entry type="LiteralStringOther" style="#008000"/>
+  <entry type="LiteralStringRegex" style="#bb6688"/>
+  <entry type="LiteralStringSymbol" style="#19177c"/>
+  <entry type="LiteralNumber" style="#666666"/>
+  <entry type="Operator" style="#666666"/>
+  <entry type="OperatorWord" style="bold #aa22ff"/>
+  <entry type="Comment" style="italic #408080"/>
+  <entry type="CommentPreproc" style="noitalic #bc7a00"/>
+  <entry type="GenericDeleted" style="#a00000"/>
+  <entry type="GenericEmph" style="italic"/>
+  <entry type="GenericError" style="#ff0000"/>
+  <entry type="GenericHeading" style="bold #000080"/>
+  <entry type="GenericInserted" style="#00a000"/>
+  <entry type="GenericOutput" style="#888888"/>
+  <entry type="GenericPrompt" style="bold #000080"/>
+  <entry type="GenericStrong" style="bold"/>
+  <entry type="GenericSubheading" style="bold #800080"/>
+  <entry type="GenericTraceback" style="#0044dd"/>
+  <entry type="GenericUnderline" style="underline"/>
+  <entry type="TextWhitespace" style="#bbbbbb"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/rainbow_dash.xml b/styles/embedded/rainbow_dash.xml
new file mode 100644
index 0000000..ffe6463
--- /dev/null
+++ b/styles/embedded/rainbow_dash.xml
@@ -0,0 +1,40 @@
+<style name="rainbow_dash" theme="light">
+  <entry type="Error" style="#ffffff bg:#cc0000"/>
+  <entry type="Background" style="bg:#ffffff"/>
+  <entry type="Keyword" style="bold #2c5dcd"/>
+  <entry type="KeywordPseudo" style="nobold"/>
+  <entry type="KeywordType" style="#5918bb"/>
+  <entry type="NameAttribute" style="italic #2c5dcd"/>
+  <entry type="NameBuiltin" style="bold #5918bb"/>
+  <entry type="NameClass" style="underline"/>
+  <entry type="NameConstant" style="#318495"/>
+  <entry type="NameDecorator" style="bold #ff8000"/>
+  <entry type="NameEntity" style="bold #5918bb"/>
+  <entry type="NameException" style="bold #5918bb"/>
+  <entry type="NameFunction" style="bold #ff8000"/>
+  <entry type="NameTag" style="bold #2c5dcd"/>
+  <entry type="LiteralString" style="#00cc66"/>
+  <entry type="LiteralStringDoc" style="italic"/>
+  <entry type="LiteralStringEscape" style="bold #c5060b"/>
+  <entry type="LiteralStringOther" style="#318495"/>
+  <entry type="LiteralStringSymbol" style="bold #c5060b"/>
+  <entry type="LiteralNumber" style="bold #5918bb"/>
+  <entry type="Operator" style="#2c5dcd"/>
+  <entry type="OperatorWord" style="bold"/>
+  <entry type="Comment" style="italic #0080ff"/>
+  <entry type="CommentSpecial" style="bold"/>
+  <entry type="CommentPreproc" style="noitalic"/>
+  <entry type="GenericDeleted" style="bg:#ffcccc border:#c5060b"/>
+  <entry type="GenericEmph" style="italic"/>
+  <entry type="GenericError" style="#ff0000"/>
+  <entry type="GenericHeading" style="bold #2c5dcd"/>
+  <entry type="GenericInserted" style="bg:#ccffcc border:#00cc00"/>
+  <entry type="GenericOutput" style="#aaaaaa"/>
+  <entry type="GenericPrompt" style="bold #2c5dcd"/>
+  <entry type="GenericStrong" style="bold"/>
+  <entry type="GenericSubheading" style="bold #2c5dcd"/>
+  <entry type="GenericTraceback" style="#c5060b"/>
+  <entry type="GenericUnderline" style="underline"/>
+  <entry type="Text" style="#4d4d4d"/>
+  <entry type="TextWhitespace" style="#cbcbcb"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/rose-pine-dawn.xml b/styles/embedded/rose-pine-dawn.xml
new file mode 100644
index 0000000..f2fa25d
--- /dev/null
+++ b/styles/embedded/rose-pine-dawn.xml
@@ -0,0 +1,29 @@
+<style name="rose-pine-dawn" theme="light">
+  <entry type="Error" style="#b4637a"/>
+  <entry type="Background" style="bg:#faf4ed"/>
+  <entry type="Keyword" style="#286983"/>
+  <entry type="KeywordNamespace" style="#907aa9"/>
+  <entry type="Name" style="#d7827e"/>
+  <entry type="NameAttribute" style="#d7827e"/>
+  <entry type="NameClass" style="#56949f"/>
+  <entry type="NameConstant" style="#ea9d34"/>
+  <entry type="NameDecorator" style="#797593"/>
+  <entry type="NameException" style="#286983"/>
+  <entry type="NameFunction" style="#d7827e"/>
+  <entry type="NameOther" style="#575279"/>
+  <entry type="NameTag" style="#d7827e"/>
+  <entry type="Literal" style="#ea9d34"/>
+  <entry type="LiteralDate" style="#ea9d34"/>
+  <entry type="LiteralString" style="#ea9d34"/>
+  <entry type="LiteralStringEscape" style="#286983"/>
+  <entry type="LiteralNumber" style="#ea9d34"/>
+  <entry type="Operator" style="#797593"/>
+  <entry type="Punctuation" style="#797593"/>
+  <entry type="Comment" style="#9893a5"/>
+  <entry type="GenericDeleted" style="#b4637a"/>
+  <entry type="GenericEmph" style="italic"/>
+  <entry type="GenericInserted" style="#56949f"/>
+  <entry type="GenericStrong" style="bold"/>
+  <entry type="GenericSubheading" style="#907aa9"/>
+  <entry type="Text" style="#575279"/>
+</style>
diff --git a/styles/embedded/rose-pine-moon.xml b/styles/embedded/rose-pine-moon.xml
new file mode 100644
index 0000000..9df4245
--- /dev/null
+++ b/styles/embedded/rose-pine-moon.xml
@@ -0,0 +1,29 @@
+<style name="rose-pine-moon" theme="dark">
+  <entry type="Error" style="#eb6f92"/>
+  <entry type="Background" style="bg:#232136"/>
+  <entry type="Keyword" style="#3e8fb0"/>
+  <entry type="KeywordNamespace" style="#c4a7e7"/>
+  <entry type="Name" style="#ea9a97"/>
+  <entry type="NameAttribute" style="#ea9a97"/>
+  <entry type="NameClass" style="#9ccfd8"/>
+  <entry type="NameConstant" style="#f6c177"/>
+  <entry type="NameDecorator" style="#908caa"/>
+  <entry type="NameException" style="#3e8fb0"/>
+  <entry type="NameFunction" style="#ea9a97"/>
+  <entry type="NameOther" style="#e0def4"/>
+  <entry type="NameTag" style="#ea9a97"/>
+  <entry type="Literal" style="#f6c177"/>
+  <entry type="LiteralDate" style="#f6c177"/>
+  <entry type="LiteralString" style="#f6c177"/>
+  <entry type="LiteralStringEscape" style="#3e8fb0"/>
+  <entry type="LiteralNumber" style="#f6c177"/>
+  <entry type="Operator" style="#908caa"/>
+  <entry type="Punctuation" style="#908caa"/>
+  <entry type="Comment" style="#6e6a86"/>
+  <entry type="GenericDeleted" style="#eb6f92"/>
+  <entry type="GenericEmph" style="italic"/>
+  <entry type="GenericInserted" style="#9ccfd8"/>
+  <entry type="GenericStrong" style="bold"/>
+  <entry type="GenericSubheading" style="#c4a7e7"/>
+  <entry type="Text" style="#e0def4"/>
+</style>
diff --git a/styles/embedded/rose-pine.xml b/styles/embedded/rose-pine.xml
new file mode 100644
index 0000000..80bb45e
--- /dev/null
+++ b/styles/embedded/rose-pine.xml
@@ -0,0 +1,29 @@
+<style name="rose-pine" theme="dark">
+  <entry type="Error" style="#eb6f92"/>
+  <entry type="Background" style="bg:#191724"/>
+  <entry type="Keyword" style="#31748f"/>
+  <entry type="KeywordNamespace" style="#c4a7e7"/>
+  <entry type="Name" style="#ebbcba"/>
+  <entry type="NameAttribute" style="#ebbcba"/>
+  <entry type="NameClass" style="#9ccfd8"/>
+  <entry type="NameConstant" style="#f6c177"/>
+  <entry type="NameDecorator" style="#908caa"/>
+  <entry type="NameException" style="#31748f"/>
+  <entry type="NameFunction" style="#ebbcba"/>
+  <entry type="NameOther" style="#e0def4"/>
+  <entry type="NameTag" style="#ebbcba"/>
+  <entry type="Literal" style="#f6c177"/>
+  <entry type="LiteralDate" style="#f6c177"/>
+  <entry type="LiteralString" style="#f6c177"/>
+  <entry type="LiteralStringEscape" style="#31748f"/>
+  <entry type="LiteralNumber" style="#f6c177"/>
+  <entry type="Operator" style="#908caa"/>
+  <entry type="Punctuation" style="#908caa"/>
+  <entry type="Comment" style="#6e6a86"/>
+  <entry type="GenericDeleted" style="#eb6f92"/>
+  <entry type="GenericEmph" style="italic"/>
+  <entry type="GenericInserted" style="#9ccfd8"/>
+  <entry type="GenericStrong" style="bold"/>
+  <entry type="GenericSubheading" style="#c4a7e7"/>
+  <entry type="Text" style="#e0def4"/>
+</style>
diff --git a/styles/embedded/rrt.xml b/styles/embedded/rrt.xml
new file mode 100644
index 0000000..063e66d
--- /dev/null
+++ b/styles/embedded/rrt.xml
@@ -0,0 +1,13 @@
+<style name="rrt" theme="dark">
+  <entry type="Background" style="#f8f8f2 bg:#000000"/>
+  <entry type="Keyword" style="#ff0000"/>
+  <entry type="KeywordType" style="#ee82ee"/>
+  <entry type="NameConstant" style="#7fffd4"/>
+  <entry type="NameFunction" style="#ffff00"/>
+  <entry type="NameVariable" style="#eedd82"/>
+  <entry type="LiteralString" style="#87ceeb"/>
+  <entry type="LiteralStringSymbol" style="#ff6600"/>
+  <entry type="LiteralNumber" style="#ff6600"/>
+  <entry type="Comment" style="#00ff00"/>
+  <entry type="CommentPreproc" style="#e5e5e5"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/solarized-dark.xml b/styles/embedded/solarized-dark.xml
new file mode 100644
index 0000000..ae157ee
--- /dev/null
+++ b/styles/embedded/solarized-dark.xml
@@ -0,0 +1,39 @@
+<style name="solarized-dark" theme="dark">
+  <entry type="Other" style="#cb4b16"/>
+  <entry type="Background" style="#93a1a1 bg:#002b36"/>
+  <entry type="Keyword" style="#719e07"/>
+  <entry type="KeywordConstant" style="#cb4b16"/>
+  <entry type="KeywordDeclaration" style="#268bd2"/>
+  <entry type="KeywordReserved" style="#268bd2"/>
+  <entry type="KeywordType" style="#dc322f"/>
+  <entry type="NameAttribute" style="#93a1a1"/>
+  <entry type="NameBuiltin" style="#b58900"/>
+  <entry type="NameBuiltinPseudo" style="#268bd2"/>
+  <entry type="NameClass" style="#268bd2"/>
+  <entry type="NameConstant" style="#cb4b16"/>
+  <entry type="NameDecorator" style="#268bd2"/>
+  <entry type="NameEntity" style="#cb4b16"/>
+  <entry type="NameException" style="#cb4b16"/>
+  <entry type="NameFunction" style="#268bd2"/>
+  <entry type="NameTag" style="#268bd2"/>
+  <entry type="NameVariable" style="#268bd2"/>
+  <entry type="LiteralString" style="#2aa198"/>
+  <entry type="LiteralStringBacktick" style="#586e75"/>
+  <entry type="LiteralStringChar" style="#2aa198"/>
+  <entry type="LiteralStringDoc" style="#93a1a1"/>
+  <entry type="LiteralStringEscape" style="#cb4b16"/>
+  <entry type="LiteralStringHeredoc" style="#93a1a1"/>
+  <entry type="LiteralStringRegex" style="#dc322f"/>
+  <entry type="LiteralNumber" style="#2aa198"/>
+  <entry type="Operator" style="#719e07"/>
+  <entry type="Comment" style="#586e75"/>
+  <entry type="CommentSpecial" style="#719e07"/>
+  <entry type="CommentPreproc" style="#719e07"/>
+  <entry type="GenericDeleted" style="#dc322f"/>
+  <entry type="GenericEmph" style="italic"/>
+  <entry type="GenericError" style="bold #dc322f"/>
+  <entry type="GenericHeading" style="#cb4b16"/>
+  <entry type="GenericInserted" style="#719e07"/>
+  <entry type="GenericStrong" style="bold"/>
+  <entry type="GenericSubheading" style="#268bd2"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/solarized-dark256.xml b/styles/embedded/solarized-dark256.xml
new file mode 100644
index 0000000..1693861
--- /dev/null
+++ b/styles/embedded/solarized-dark256.xml
@@ -0,0 +1,41 @@
+<style name="solarized-dark256" theme="dark">
+  <entry type="Other" style="#d75f00"/>
+  <entry type="Background" style="#8a8a8a bg:#1c1c1c"/>
+  <entry type="Keyword" style="#5f8700"/>
+  <entry type="KeywordConstant" style="#d75f00"/>
+  <entry type="KeywordDeclaration" style="#0087ff"/>
+  <entry type="KeywordNamespace" style="#d75f00"/>
+  <entry type="KeywordReserved" style="#0087ff"/>
+  <entry type="KeywordType" style="#af0000"/>
+  <entry type="NameAttribute" style="#8a8a8a"/>
+  <entry type="NameBuiltin" style="#0087ff"/>
+  <entry type="NameBuiltinPseudo" style="#0087ff"/>
+  <entry type="NameClass" style="#0087ff"/>
+  <entry type="NameConstant" style="#d75f00"/>
+  <entry type="NameDecorator" style="#0087ff"/>
+  <entry type="NameEntity" style="#d75f00"/>
+  <entry type="NameException" style="#af8700"/>
+  <entry type="NameFunction" style="#0087ff"/>
+  <entry type="NameTag" style="#0087ff"/>
+  <entry type="NameVariable" style="#0087ff"/>
+  <entry type="LiteralString" style="#00afaf"/>
+  <entry type="LiteralStringBacktick" style="#4e4e4e"/>
+  <entry type="LiteralStringChar" style="#00afaf"/>
+  <entry type="LiteralStringDoc" style="#00afaf"/>
+  <entry type="LiteralStringEscape" style="#af0000"/>
+  <entry type="LiteralStringHeredoc" style="#00afaf"/>
+  <entry type="LiteralStringRegex" style="#af0000"/>
+  <entry type="LiteralNumber" style="#00afaf"/>
+  <entry type="Operator" style="#8a8a8a"/>
+  <entry type="OperatorWord" style="#5f8700"/>
+  <entry type="Comment" style="#4e4e4e"/>
+  <entry type="CommentSpecial" style="#5f8700"/>
+  <entry type="CommentPreproc" style="#5f8700"/>
+  <entry type="GenericDeleted" style="#af0000"/>
+  <entry type="GenericEmph" style="italic"/>
+  <entry type="GenericError" style="bold #af0000"/>
+  <entry type="GenericHeading" style="#d75f00"/>
+  <entry type="GenericInserted" style="#5f8700"/>
+  <entry type="GenericStrong" style="bold"/>
+  <entry type="GenericSubheading" style="#0087ff"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/solarized-light.xml b/styles/embedded/solarized-light.xml
new file mode 100644
index 0000000..67f2475
--- /dev/null
+++ b/styles/embedded/solarized-light.xml
@@ -0,0 +1,17 @@
+<style name="solarized-light" theme="light">
+  <entry type="Background" style="bg:#eee8d5"/>
+  <entry type="Keyword" style="#859900"/>
+  <entry type="KeywordConstant" style="bold"/>
+  <entry type="KeywordNamespace" style="bold #dc322f"/>
+  <entry type="KeywordType" style="bold"/>
+  <entry type="Name" style="#268bd2"/>
+  <entry type="NameBuiltin" style="#cb4b16"/>
+  <entry type="NameClass" style="#cb4b16"/>
+  <entry type="NameTag" style="bold"/>
+  <entry type="Literal" style="#2aa198"/>
+  <entry type="LiteralNumber" style="bold"/>
+  <entry type="OperatorWord" style="#859900"/>
+  <entry type="Comment" style="italic #93a1a1"/>
+  <entry type="Generic" style="#d33682"/>
+  <entry type="Text" style="#586e75"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/swapoff.xml b/styles/embedded/swapoff.xml
new file mode 100644
index 0000000..c396008
--- /dev/null
+++ b/styles/embedded/swapoff.xml
@@ -0,0 +1,18 @@
+<style name="swapoff" theme="dark">
+  <entry type="Error" style="#ff0000"/>
+  <entry type="Background" style="#e5e5e5 bg:#000000"/>
+  <entry type="Keyword" style="bold #ffffff"/>
+  <entry type="NameAttribute" style="#007f7f"/>
+  <entry type="NameBuiltin" style="bold #ffffff"/>
+  <entry type="NameKeyword" style="bold #ffffff"/>
+  <entry type="NameTag" style="bold"/>
+  <entry type="LiteralDate" style="bold #ffff00"/>
+  <entry type="LiteralString" style="bold #00ffff"/>
+  <entry type="LiteralNumber" style="bold #ffff00"/>
+  <entry type="Comment" style="#007f7f"/>
+  <entry type="CommentPreproc" style="bold #00ff00"/>
+  <entry type="GenericHeading" style="bold"/>
+  <entry type="GenericStrong" style="bold"/>
+  <entry type="GenericSubheading" style="bold"/>
+  <entry type="GenericUnderline" style="underline"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/tango.xml b/styles/embedded/tango.xml
new file mode 100644
index 0000000..431fe10
--- /dev/null
+++ b/styles/embedded/tango.xml
@@ -0,0 +1,72 @@
+<style name="tango" theme="light">
+  <entry type="Other" style="#000000"/>
+  <entry type="Error" style="#a40000 border:#ef2929"/>
+  <entry type="Background" style="bg:#f8f8f8"/>
+  <entry type="Keyword" style="bold #204a87"/>
+  <entry type="KeywordConstant" style="bold #204a87"/>
+  <entry type="KeywordDeclaration" style="bold #204a87"/>
+  <entry type="KeywordNamespace" style="bold #204a87"/>
+  <entry type="KeywordPseudo" style="bold #204a87"/>
+  <entry type="KeywordReserved" style="bold #204a87"/>
+  <entry type="KeywordType" style="bold #204a87"/>
+  <entry type="Name" style="#000000"/>
+  <entry type="NameAttribute" style="#c4a000"/>
+  <entry type="NameBuiltin" style="#204a87"/>
+  <entry type="NameBuiltinPseudo" style="#3465a4"/>
+  <entry type="NameClass" style="#000000"/>
+  <entry type="NameConstant" style="#000000"/>
+  <entry type="NameDecorator" style="bold #5c35cc"/>
+  <entry type="NameEntity" style="#ce5c00"/>
+  <entry type="NameException" style="bold #cc0000"/>
+  <entry type="NameFunction" style="#000000"/>
+  <entry type="NameLabel" style="#f57900"/>
+  <entry type="NameNamespace" style="#000000"/>
+  <entry type="NameOther" style="#000000"/>
+  <entry type="NameProperty" style="#000000"/>
+  <entry type="NameTag" style="bold #204a87"/>
+  <entry type="NameVariable" style="#000000"/>
+  <entry type="NameVariableClass" style="#000000"/>
+  <entry type="NameVariableGlobal" style="#000000"/>
+  <entry type="NameVariableInstance" style="#000000"/>
+  <entry type="Literal" style="#000000"/>
+  <entry type="LiteralDate" style="#000000"/>
+  <entry type="LiteralString" style="#4e9a06"/>
+  <entry type="LiteralStringBacktick" style="#4e9a06"/>
+  <entry type="LiteralStringChar" style="#4e9a06"/>
+  <entry type="LiteralStringDoc" style="italic #8f5902"/>
+  <entry type="LiteralStringDouble" style="#4e9a06"/>
+  <entry type="LiteralStringEscape" style="#4e9a06"/>
+  <entry type="LiteralStringHeredoc" style="#4e9a06"/>
+  <entry type="LiteralStringInterpol" style="#4e9a06"/>
+  <entry type="LiteralStringOther" style="#4e9a06"/>
+  <entry type="LiteralStringRegex" style="#4e9a06"/>
+  <entry type="LiteralStringSingle" style="#4e9a06"/>
+  <entry type="LiteralStringSymbol" style="#4e9a06"/>
+  <entry type="LiteralNumber" style="bold #0000cf"/>
+  <entry type="LiteralNumberFloat" style="bold #0000cf"/>
+  <entry type="LiteralNumberHex" style="bold #0000cf"/>
+  <entry type="LiteralNumberInteger" style="bold #0000cf"/>
+  <entry type="LiteralNumberIntegerLong" style="bold #0000cf"/>
+  <entry type="LiteralNumberOct" style="bold #0000cf"/>
+  <entry type="Operator" style="bold #ce5c00"/>
+  <entry type="OperatorWord" style="bold #204a87"/>
+  <entry type="Punctuation" style="bold #000000"/>
+  <entry type="Comment" style="italic #8f5902"/>
+  <entry type="CommentMultiline" style="italic #8f5902"/>
+  <entry type="CommentSingle" style="italic #8f5902"/>
+  <entry type="CommentSpecial" style="italic #8f5902"/>
+  <entry type="CommentPreproc" style="italic #8f5902"/>
+  <entry type="Generic" style="#000000"/>
+  <entry type="GenericDeleted" style="#a40000"/>
+  <entry type="GenericEmph" style="italic #000000"/>
+  <entry type="GenericError" style="#ef2929"/>
+  <entry type="GenericHeading" style="bold #000080"/>
+  <entry type="GenericInserted" style="#00a000"/>
+  <entry type="GenericOutput" style="italic #000000"/>
+  <entry type="GenericPrompt" style="#8f5902"/>
+  <entry type="GenericStrong" style="bold #000000"/>
+  <entry type="GenericSubheading" style="bold #800080"/>
+  <entry type="GenericTraceback" style="bold #a40000"/>
+  <entry type="GenericUnderline" style="underline"/>
+  <entry type="TextWhitespace" style="underline #f8f8f8"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/tokyonight-day.xml b/styles/embedded/tokyonight-day.xml
new file mode 100644
index 0000000..a146a18
--- /dev/null
+++ b/styles/embedded/tokyonight-day.xml
@@ -0,0 +1,83 @@
+<style name="tokyonight-day" theme="light">
+  <entry type="Background" style="bg:#e1e2e7 #3760bf"/>
+  <entry type="CodeLine" style="#3760bf"/>
+  <entry type="Error" style="#c64343"/>
+  <entry type="Other" style="#3760bf"/>
+  <entry type="LineTableTD" style=""/>
+  <entry type="LineTable" style=""/>
+  <entry type="LineHighlight" style="bg:#a1a6c5"/>
+  <entry type="LineNumbersTable" style="#6172b0"/>
+  <entry type="LineNumbers" style="#6172b0"/>
+  <entry type="Keyword" style="#9854f1"/>
+  <entry type="KeywordReserved" style="#9854f1"/>
+  <entry type="KeywordPseudo" style="#9854f1"/>
+  <entry type="KeywordConstant" style="#8c6c3e"/>
+  <entry type="KeywordDeclaration" style="#9d7cd8"/>
+  <entry type="KeywordNamespace" style="#007197"/>
+  <entry type="KeywordType" style="#0db9d7"/>
+  <entry type="Name" style="#3760bf"/>
+  <entry type="NameClass" style="#b15c00"/>
+  <entry type="NameConstant" style="#b15c00"/>
+  <entry type="NameDecorator" style="bold #2e7de9"/>
+  <entry type="NameEntity" style="#007197"/>
+  <entry type="NameException" style="#8c6c3e"/>
+  <entry type="NameFunction" style="#2e7de9"/>
+  <entry type="NameFunctionMagic" style="#2e7de9"/>
+  <entry type="NameLabel" style="#587539"/>
+  <entry type="NameNamespace" style="#8c6c3e"/>
+  <entry type="NameProperty" style="#8c6c3e"/>
+  <entry type="NameTag" style="#9854f1"/>
+  <entry type="NameVariable" style="#3760bf"/>
+  <entry type="NameVariableClass" style="#3760bf"/>
+  <entry type="NameVariableGlobal" style="#3760bf"/>
+  <entry type="NameVariableInstance" style="#3760bf"/>
+  <entry type="NameVariableMagic" style="#3760bf"/>
+  <entry type="NameAttribute" style="#2e7de9"/>
+  <entry type="NameBuiltin" style="#587539"/>
+  <entry type="NameBuiltinPseudo" style="#587539"/>
+  <entry type="NameOther" style="#3760bf"/>
+  <entry type="Literal" style="#3760bf"/>
+  <entry type="LiteralDate" style="#3760bf"/>
+  <entry type="LiteralString" style="#587539"/>
+  <entry type="LiteralStringChar" style="#587539"/>
+  <entry type="LiteralStringSingle" style="#587539"/>
+  <entry type="LiteralStringDouble" style="#587539"/>
+  <entry type="LiteralStringBacktick" style="#587539"/>
+  <entry type="LiteralStringOther" style="#587539"/>
+  <entry type="LiteralStringSymbol" style="#587539"/>
+  <entry type="LiteralStringInterpol" style="#587539"/>
+  <entry type="LiteralStringAffix" style="#9d7cd8"/>
+  <entry type="LiteralStringDelimiter" style="#2e7de9"/>
+  <entry type="LiteralStringEscape" style="#2e7de9"/>
+  <entry type="LiteralStringRegex" style="#007197"/>
+  <entry type="LiteralStringDoc" style="#a1a6c5"/>
+  <entry type="LiteralStringHeredoc" style="#a1a6c5"/>
+  <entry type="LiteralNumber" style="#8c6c3e"/>
+  <entry type="LiteralNumberBin" style="#8c6c3e"/>
+  <entry type="LiteralNumberHex" style="#8c6c3e"/>
+  <entry type="LiteralNumberInteger" style="#8c6c3e"/>
+  <entry type="LiteralNumberFloat" style="#8c6c3e"/>
+  <entry type="LiteralNumberIntegerLong" style="#8c6c3e"/>
+  <entry type="LiteralNumberOct" style="#8c6c3e"/>
+  <entry type="Operator" style="bold #587539"/>
+  <entry type="OperatorWord" style="bold #587539"/>
+  <entry type="Comment" style="italic #a1a6c5"/>
+  <entry type="CommentSingle" style="italic #a1a6c5"/>
+  <entry type="CommentMultiline" style="italic #a1a6c5"/>
+  <entry type="CommentSpecial" style="italic #a1a6c5"/>
+  <entry type="CommentHashbang" style="italic #a1a6c5"/>
+  <entry type="CommentPreproc" style="italic #a1a6c5"/>
+  <entry type="CommentPreprocFile" style="bold #a1a6c5"/>
+  <entry type="Generic" style="#3760bf"/>
+  <entry type="GenericInserted" style="bg:#e9e9ed #587539"/>
+  <entry type="GenericDeleted" style="#c64343 bg:#e9e9ed"/>
+  <entry type="GenericEmph" style="italic #3760bf"/>
+  <entry type="GenericStrong" style="bold #3760bf"/>
+  <entry type="GenericUnderline" style="underline #3760bf"/>
+  <entry type="GenericHeading" style="bold #8c6c3e"/>
+  <entry type="GenericSubheading" style="bold #8c6c3e"/>
+  <entry type="GenericOutput" style="#3760bf"/>
+  <entry type="GenericPrompt" style="#3760bf"/>
+  <entry type="GenericError" style="#c64343"/>
+  <entry type="GenericTraceback" style="#c64343"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/tokyonight-moon.xml b/styles/embedded/tokyonight-moon.xml
new file mode 100644
index 0000000..0af8992
--- /dev/null
+++ b/styles/embedded/tokyonight-moon.xml
@@ -0,0 +1,83 @@
+<style name="tokyonight-moon" theme="dark">
+  <entry type="Background" style="bg:#222436 #c8d3f5"/>
+  <entry type="CodeLine" style="#c8d3f5"/>
+  <entry type="Error" style="#c53b53"/>
+  <entry type="Other" style="#c8d3f5"/>
+  <entry type="LineTableTD" style=""/>
+  <entry type="LineTable" style=""/>
+  <entry type="LineHighlight" style="bg:#444a73"/>
+  <entry type="LineNumbersTable" style="#828bb8"/>
+  <entry type="LineNumbers" style="#828bb8"/>
+  <entry type="Keyword" style="#c099ff"/>
+  <entry type="KeywordReserved" style="#c099ff"/>
+  <entry type="KeywordPseudo" style="#c099ff"/>
+  <entry type="KeywordConstant" style="#ffc777"/>
+  <entry type="KeywordDeclaration" style="#c099ff"/>
+  <entry type="KeywordNamespace" style="#86e1fc"/>
+  <entry type="KeywordType" style="#4fd6be"/>
+  <entry type="Name" style="#c8d3f5"/>
+  <entry type="NameClass" style="#ff966c"/>
+  <entry type="NameConstant" style="#ff966c"/>
+  <entry type="NameDecorator" style="bold #82aaff"/>
+  <entry type="NameEntity" style="#86e1fc"/>
+  <entry type="NameException" style="#ffc777"/>
+  <entry type="NameFunction" style="#82aaff"/>
+  <entry type="NameFunctionMagic" style="#82aaff"/>
+  <entry type="NameLabel" style="#c3e88d"/>
+  <entry type="NameNamespace" style="#ffc777"/>
+  <entry type="NameProperty" style="#ffc777"/>
+  <entry type="NameTag" style="#c099ff"/>
+  <entry type="NameVariable" style="#c8d3f5"/>
+  <entry type="NameVariableClass" style="#c8d3f5"/>
+  <entry type="NameVariableGlobal" style="#c8d3f5"/>
+  <entry type="NameVariableInstance" style="#c8d3f5"/>
+  <entry type="NameVariableMagic" style="#c8d3f5"/>
+  <entry type="NameAttribute" style="#82aaff"/>
+  <entry type="NameBuiltin" style="#c3e88d"/>
+  <entry type="NameBuiltinPseudo" style="#c3e88d"/>
+  <entry type="NameOther" style="#c8d3f5"/>
+  <entry type="Literal" style="#c8d3f5"/>
+  <entry type="LiteralDate" style="#c8d3f5"/>
+  <entry type="LiteralString" style="#c3e88d"/>
+  <entry type="LiteralStringChar" style="#c3e88d"/>
+  <entry type="LiteralStringSingle" style="#c3e88d"/>
+  <entry type="LiteralStringDouble" style="#c3e88d"/>
+  <entry type="LiteralStringBacktick" style="#c3e88d"/>
+  <entry type="LiteralStringOther" style="#c3e88d"/>
+  <entry type="LiteralStringSymbol" style="#c3e88d"/>
+  <entry type="LiteralStringInterpol" style="#c3e88d"/>
+  <entry type="LiteralStringAffix" style="#c099ff"/>
+  <entry type="LiteralStringDelimiter" style="#82aaff"/>
+  <entry type="LiteralStringEscape" style="#82aaff"/>
+  <entry type="LiteralStringRegex" style="#86e1fc"/>
+  <entry type="LiteralStringDoc" style="#444a73"/>
+  <entry type="LiteralStringHeredoc" style="#444a73"/>
+  <entry type="LiteralNumber" style="#ffc777"/>
+  <entry type="LiteralNumberBin" style="#ffc777"/>
+  <entry type="LiteralNumberHex" style="#ffc777"/>
+  <entry type="LiteralNumberInteger" style="#ffc777"/>
+  <entry type="LiteralNumberFloat" style="#ffc777"/>
+  <entry type="LiteralNumberIntegerLong" style="#ffc777"/>
+  <entry type="LiteralNumberOct" style="#ffc777"/>
+  <entry type="Operator" style="bold #c3e88d"/>
+  <entry type="OperatorWord" style="bold #c3e88d"/>
+  <entry type="Comment" style="italic #444a73"/>
+  <entry type="CommentSingle" style="italic #444a73"/>
+  <entry type="CommentMultiline" style="italic #444a73"/>
+  <entry type="CommentSpecial" style="italic #444a73"/>
+  <entry type="CommentHashbang" style="italic #444a73"/>
+  <entry type="CommentPreproc" style="italic #444a73"/>
+  <entry type="CommentPreprocFile" style="bold #444a73"/>
+  <entry type="Generic" style="#c8d3f5"/>
+  <entry type="GenericInserted" style="bg:#1b1d2b #c3e88d"/>
+  <entry type="GenericDeleted" style="#c53b53 bg:#1b1d2b"/>
+  <entry type="GenericEmph" style="italic #c8d3f5"/>
+  <entry type="GenericStrong" style="bold #c8d3f5"/>
+  <entry type="GenericUnderline" style="underline #c8d3f5"/>
+  <entry type="GenericHeading" style="bold #ffc777"/>
+  <entry type="GenericSubheading" style="bold #ffc777"/>
+  <entry type="GenericOutput" style="#c8d3f5"/>
+  <entry type="GenericPrompt" style="#c8d3f5"/>
+  <entry type="GenericError" style="#c53b53"/>
+  <entry type="GenericTraceback" style="#c53b53"/>
+</style>
diff --git a/styles/embedded/tokyonight-night.xml b/styles/embedded/tokyonight-night.xml
new file mode 100644
index 0000000..a82ed38
--- /dev/null
+++ b/styles/embedded/tokyonight-night.xml
@@ -0,0 +1,83 @@
+<style name="tokyonight-night" theme="dark">
+  <entry type="Background" style="bg:#1a1b26 #c0caf5"/>
+  <entry type="CodeLine" style="#c0caf5"/>
+  <entry type="Error" style="#db4b4b"/>
+  <entry type="Other" style="#c0caf5"/>
+  <entry type="LineTableTD" style=""/>
+  <entry type="LineTable" style=""/>
+  <entry type="LineHighlight" style="bg:#414868"/>
+  <entry type="LineNumbersTable" style="#a9b1d6"/>
+  <entry type="LineNumbers" style="#a9b1d6"/>
+  <entry type="Keyword" style="#bb9af7"/>
+  <entry type="KeywordReserved" style="#bb9af7"/>
+  <entry type="KeywordPseudo" style="#bb9af7"/>
+  <entry type="KeywordConstant" style="#e0af68"/>
+  <entry type="KeywordDeclaration" style="#9d7cd8"/>
+  <entry type="KeywordNamespace" style="#7dcfff"/>
+  <entry type="KeywordType" style="#41a6b5"/>
+  <entry type="Name" style="#c0caf5"/>
+  <entry type="NameClass" style="#ff9e64"/>
+  <entry type="NameConstant" style="#ff9e64"/>
+  <entry type="NameDecorator" style="bold #7aa2f7"/>
+  <entry type="NameEntity" style="#7dcfff"/>
+  <entry type="NameException" style="#e0af68"/>
+  <entry type="NameFunction" style="#7aa2f7"/>
+  <entry type="NameFunctionMagic" style="#7aa2f7"/>
+  <entry type="NameLabel" style="#9ece6a"/>
+  <entry type="NameNamespace" style="#e0af68"/>
+  <entry type="NameProperty" style="#e0af68"/>
+  <entry type="NameTag" style="#bb9af7"/>
+  <entry type="NameVariable" style="#c0caf5"/>
+  <entry type="NameVariableClass" style="#c0caf5"/>
+  <entry type="NameVariableGlobal" style="#c0caf5"/>
+  <entry type="NameVariableInstance" style="#c0caf5"/>
+  <entry type="NameVariableMagic" style="#c0caf5"/>
+  <entry type="NameAttribute" style="#7aa2f7"/>
+  <entry type="NameBuiltin" style="#9ece6a"/>
+  <entry type="NameBuiltinPseudo" style="#9ece6a"/>
+  <entry type="NameOther" style="#c0caf5"/>
+  <entry type="Literal" style="#c0caf5"/>
+  <entry type="LiteralDate" style="#c0caf5"/>
+  <entry type="LiteralString" style="#9ece6a"/>
+  <entry type="LiteralStringChar" style="#9ece6a"/>
+  <entry type="LiteralStringSingle" style="#9ece6a"/>
+  <entry type="LiteralStringDouble" style="#9ece6a"/>
+  <entry type="LiteralStringBacktick" style="#9ece6a"/>
+  <entry type="LiteralStringOther" style="#9ece6a"/>
+  <entry type="LiteralStringSymbol" style="#9ece6a"/>
+  <entry type="LiteralStringInterpol" style="#9ece6a"/>
+  <entry type="LiteralStringAffix" style="#9d7cd8"/>
+  <entry type="LiteralStringDelimiter" style="#7aa2f7"/>
+  <entry type="LiteralStringEscape" style="#7aa2f7"/>
+  <entry type="LiteralStringRegex" style="#7dcfff"/>
+  <entry type="LiteralStringDoc" style="#414868"/>
+  <entry type="LiteralStringHeredoc" style="#414868"/>
+  <entry type="LiteralNumber" style="#e0af68"/>
+  <entry type="LiteralNumberBin" style="#e0af68"/>
+  <entry type="LiteralNumberHex" style="#e0af68"/>
+  <entry type="LiteralNumberInteger" style="#e0af68"/>
+  <entry type="LiteralNumberFloat" style="#e0af68"/>
+  <entry type="LiteralNumberIntegerLong" style="#e0af68"/>
+  <entry type="LiteralNumberOct" style="#e0af68"/>
+  <entry type="Operator" style="bold #9ece6a"/>
+  <entry type="OperatorWord" style="bold #9ece6a"/>
+  <entry type="Comment" style="italic #414868"/>
+  <entry type="CommentSingle" style="italic #414868"/>
+  <entry type="CommentMultiline" style="italic #414868"/>
+  <entry type="CommentSpecial" style="italic #414868"/>
+  <entry type="CommentHashbang" style="italic #414868"/>
+  <entry type="CommentPreproc" style="italic #414868"/>
+  <entry type="CommentPreprocFile" style="bold #414868"/>
+  <entry type="Generic" style="#c0caf5"/>
+  <entry type="GenericInserted" style="bg:#15161e #9ece6a"/>
+  <entry type="GenericDeleted" style="#db4b4b bg:#15161e"/>
+  <entry type="GenericEmph" style="italic #c0caf5"/>
+  <entry type="GenericStrong" style="bold #c0caf5"/>
+  <entry type="GenericUnderline" style="underline #c0caf5"/>
+  <entry type="GenericHeading" style="bold #e0af68"/>
+  <entry type="GenericSubheading" style="bold #e0af68"/>
+  <entry type="GenericOutput" style="#c0caf5"/>
+  <entry type="GenericPrompt" style="#c0caf5"/>
+  <entry type="GenericError" style="#db4b4b"/>
+  <entry type="GenericTraceback" style="#db4b4b"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/tokyonight-storm.xml b/styles/embedded/tokyonight-storm.xml
new file mode 100644
index 0000000..3c3773a
--- /dev/null
+++ b/styles/embedded/tokyonight-storm.xml
@@ -0,0 +1,83 @@
+<style name="tokyonight-storm" theme="dark">
+  <entry type="Background" style="bg:#1a1b26 #c0caf5"/>
+  <entry type="CodeLine" style="#c0caf5"/>
+  <entry type="Error" style="#db4b4b"/>
+  <entry type="Other" style="#c0caf5"/>
+  <entry type="LineTableTD" style=""/>
+  <entry type="LineTable" style=""/>
+  <entry type="LineHighlight" style="bg:#414868"/>
+  <entry type="LineNumbersTable" style="#a9b1d6"/>
+  <entry type="LineNumbers" style="#a9b1d6"/>
+  <entry type="Keyword" style="#bb9af7"/>
+  <entry type="KeywordReserved" style="#bb9af7"/>
+  <entry type="KeywordPseudo" style="#bb9af7"/>
+  <entry type="KeywordConstant" style="#e0af68"/>
+  <entry type="KeywordDeclaration" style="#9d7cd8"/>
+  <entry type="KeywordNamespace" style="#7dcfff"/>
+  <entry type="KeywordType" style="#41a6b5"/>
+  <entry type="Name" style="#c0caf5"/>
+  <entry type="NameClass" style="#ff9e64"/>
+  <entry type="NameConstant" style="#ff9e64"/>
+  <entry type="NameDecorator" style="bold #7aa2f7"/>
+  <entry type="NameEntity" style="#7dcfff"/>
+  <entry type="NameException" style="#e0af68"/>
+  <entry type="NameFunction" style="#7aa2f7"/>
+  <entry type="NameFunctionMagic" style="#7aa2f7"/>
+  <entry type="NameLabel" style="#9ece6a"/>
+  <entry type="NameNamespace" style="#e0af68"/>
+  <entry type="NameProperty" style="#e0af68"/>
+  <entry type="NameTag" style="#bb9af7"/>
+  <entry type="NameVariable" style="#c0caf5"/>
+  <entry type="NameVariableClass" style="#c0caf5"/>
+  <entry type="NameVariableGlobal" style="#c0caf5"/>
+  <entry type="NameVariableInstance" style="#c0caf5"/>
+  <entry type="NameVariableMagic" style="#c0caf5"/>
+  <entry type="NameAttribute" style="#7aa2f7"/>
+  <entry type="NameBuiltin" style="#9ece6a"/>
+  <entry type="NameBuiltinPseudo" style="#9ece6a"/>
+  <entry type="NameOther" style="#c0caf5"/>
+  <entry type="Literal" style="#c0caf5"/>
+  <entry type="LiteralDate" style="#c0caf5"/>
+  <entry type="LiteralString" style="#9ece6a"/>
+  <entry type="LiteralStringChar" style="#9ece6a"/>
+  <entry type="LiteralStringSingle" style="#9ece6a"/>
+  <entry type="LiteralStringDouble" style="#9ece6a"/>
+  <entry type="LiteralStringBacktick" style="#9ece6a"/>
+  <entry type="LiteralStringOther" style="#9ece6a"/>
+  <entry type="LiteralStringSymbol" style="#9ece6a"/>
+  <entry type="LiteralStringInterpol" style="#9ece6a"/>
+  <entry type="LiteralStringAffix" style="#9d7cd8"/>
+  <entry type="LiteralStringDelimiter" style="#7aa2f7"/>
+  <entry type="LiteralStringEscape" style="#7aa2f7"/>
+  <entry type="LiteralStringRegex" style="#7dcfff"/>
+  <entry type="LiteralStringDoc" style="#414868"/>
+  <entry type="LiteralStringHeredoc" style="#414868"/>
+  <entry type="LiteralNumber" style="#e0af68"/>
+  <entry type="LiteralNumberBin" style="#e0af68"/>
+  <entry type="LiteralNumberHex" style="#e0af68"/>
+  <entry type="LiteralNumberInteger" style="#e0af68"/>
+  <entry type="LiteralNumberFloat" style="#e0af68"/>
+  <entry type="LiteralNumberIntegerLong" style="#e0af68"/>
+  <entry type="LiteralNumberOct" style="#e0af68"/>
+  <entry type="Operator" style="bold #9ece6a"/>
+  <entry type="OperatorWord" style="bold #9ece6a"/>
+  <entry type="Comment" style="italic #414868"/>
+  <entry type="CommentSingle" style="italic #414868"/>
+  <entry type="CommentMultiline" style="italic #414868"/>
+  <entry type="CommentSpecial" style="italic #414868"/>
+  <entry type="CommentHashbang" style="italic #414868"/>
+  <entry type="CommentPreproc" style="italic #414868"/>
+  <entry type="CommentPreprocFile" style="bold #414868"/>
+  <entry type="Generic" style="#c0caf5"/>
+  <entry type="GenericInserted" style="bg:#15161e #9ece6a"/>
+  <entry type="GenericDeleted" style="#db4b4b bg:#15161e"/>
+  <entry type="GenericEmph" style="italic #c0caf5"/>
+  <entry type="GenericStrong" style="bold #c0caf5"/>
+  <entry type="GenericUnderline" style="underline #c0caf5"/>
+  <entry type="GenericHeading" style="bold #e0af68"/>
+  <entry type="GenericSubheading" style="bold #e0af68"/>
+  <entry type="GenericOutput" style="#c0caf5"/>
+  <entry type="GenericPrompt" style="#c0caf5"/>
+  <entry type="GenericError" style="#db4b4b"/>
+  <entry type="GenericTraceback" style="#db4b4b"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/trac.xml b/styles/embedded/trac.xml
new file mode 100644
index 0000000..377989c
--- /dev/null
+++ b/styles/embedded/trac.xml
@@ -0,0 +1,35 @@
+<style name="trac" theme="light">
+  <entry type="Error" style="#a61717 bg:#e3d2d2"/>
+  <entry type="Background" style="bg:#ffffff"/>
+  <entry type="Keyword" style="bold"/>
+  <entry type="KeywordType" style="#445588"/>
+  <entry type="NameAttribute" style="#008080"/>
+  <entry type="NameBuiltin" style="#999999"/>
+  <entry type="NameClass" style="bold #445588"/>
+  <entry type="NameConstant" style="#008080"/>
+  <entry type="NameEntity" style="#800080"/>
+  <entry type="NameException" style="bold #990000"/>
+  <entry type="NameFunction" style="bold #990000"/>
+  <entry type="NameNamespace" style="#555555"/>
+  <entry type="NameTag" style="#000080"/>
+  <entry type="NameVariable" style="#008080"/>
+  <entry type="LiteralString" style="#bb8844"/>
+  <entry type="LiteralStringRegex" style="#808000"/>
+  <entry type="LiteralNumber" style="#009999"/>
+  <entry type="Operator" style="bold"/>
+  <entry type="Comment" style="italic #999988"/>
+  <entry type="CommentSpecial" style="bold #999999"/>
+  <entry type="CommentPreproc" style="bold noitalic #999999"/>
+  <entry type="GenericDeleted" style="#000000 bg:#ffdddd"/>
+  <entry type="GenericEmph" style="italic"/>
+  <entry type="GenericError" style="#aa0000"/>
+  <entry type="GenericHeading" style="#999999"/>
+  <entry type="GenericInserted" style="#000000 bg:#ddffdd"/>
+  <entry type="GenericOutput" style="#888888"/>
+  <entry type="GenericPrompt" style="#555555"/>
+  <entry type="GenericStrong" style="bold"/>
+  <entry type="GenericSubheading" style="#aaaaaa"/>
+  <entry type="GenericTraceback" style="#aa0000"/>
+  <entry type="GenericUnderline" style="underline"/>
+  <entry type="TextWhitespace" style="#bbbbbb"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/vim.xml b/styles/embedded/vim.xml
new file mode 100644
index 0000000..2920512
--- /dev/null
+++ b/styles/embedded/vim.xml
@@ -0,0 +1,29 @@
+<style name="vim" theme="dark">
+  <entry type="Error" style="border:#ff0000"/>
+  <entry type="Background" style="#cccccc bg:#000000"/>
+  <entry type="Keyword" style="#cdcd00"/>
+  <entry type="KeywordDeclaration" style="#00cd00"/>
+  <entry type="KeywordNamespace" style="#cd00cd"/>
+  <entry type="KeywordType" style="#00cd00"/>
+  <entry type="NameBuiltin" style="#cd00cd"/>
+  <entry type="NameClass" style="#00cdcd"/>
+  <entry type="NameException" style="bold #666699"/>
+  <entry type="NameVariable" style="#00cdcd"/>
+  <entry type="LiteralString" style="#cd0000"/>
+  <entry type="LiteralNumber" style="#cd00cd"/>
+  <entry type="Operator" style="#3399cc"/>
+  <entry type="OperatorWord" style="#cdcd00"/>
+  <entry type="Comment" style="#000080"/>
+  <entry type="CommentSpecial" style="bold #cd0000"/>
+  <entry type="GenericDeleted" style="#cd0000"/>
+  <entry type="GenericEmph" style="italic"/>
+  <entry type="GenericError" style="#ff0000"/>
+  <entry type="GenericHeading" style="bold #000080"/>
+  <entry type="GenericInserted" style="#00cd00"/>
+  <entry type="GenericOutput" style="#888888"/>
+  <entry type="GenericPrompt" style="bold #000080"/>
+  <entry type="GenericStrong" style="bold"/>
+  <entry type="GenericSubheading" style="bold #800080"/>
+  <entry type="GenericTraceback" style="#0044dd"/>
+  <entry type="GenericUnderline" style="underline"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/vs.xml b/styles/embedded/vs.xml
new file mode 100644
index 0000000..b9fa734
--- /dev/null
+++ b/styles/embedded/vs.xml
@@ -0,0 +1,16 @@
+<style name="vs" theme="light">
+  <entry type="Error" style="border:#ff0000"/>
+  <entry type="Background" style="bg:#ffffff"/>
+  <entry type="Keyword" style="#0000ff"/>
+  <entry type="KeywordType" style="#2b91af"/>
+  <entry type="NameClass" style="#2b91af"/>
+  <entry type="LiteralString" style="#a31515"/>
+  <entry type="OperatorWord" style="#0000ff"/>
+  <entry type="Comment" style="#008000"/>
+  <entry type="CommentPreproc" style="#0000ff"/>
+  <entry type="GenericEmph" style="italic"/>
+  <entry type="GenericHeading" style="bold"/>
+  <entry type="GenericPrompt" style="bold"/>
+  <entry type="GenericStrong" style="bold"/>
+  <entry type="GenericSubheading" style="bold"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/vulcan.xml b/styles/embedded/vulcan.xml
new file mode 100644
index 0000000..717ffd2
--- /dev/null
+++ b/styles/embedded/vulcan.xml
@@ -0,0 +1,74 @@
+<style name="vulcan" theme="dark">
+  <entry type="Other" style="#c9c9c9"/>
+  <entry type="Error" style="#cf5967"/>
+  <entry type="Background" style="bg:#282c34"/>
+  <entry type="Keyword" style="#7fbaf5"/>
+  <entry type="KeywordConstant" style="#cf5967 bg:#43454f"/>
+  <entry type="KeywordDeclaration" style="#7fbaf5"/>
+  <entry type="KeywordNamespace" style="#bc74c4"/>
+  <entry type="KeywordPseudo" style="#bc74c4"/>
+  <entry type="KeywordReserved" style="#7fbaf5"/>
+  <entry type="KeywordType" style="bold #57c7ff"/>
+  <entry type="Name" style="#c9c9c9"/>
+  <entry type="NameAttribute" style="#bc74c4"/>
+  <entry type="NameBuiltin" style="#7fbaf5"/>
+  <entry type="NameBuiltinPseudo" style="#7fbaf5"/>
+  <entry type="NameClass" style="#ecbe7b"/>
+  <entry type="NameConstant" style="#ecbe7b"/>
+  <entry type="NameDecorator" style="#ecbe7b"/>
+  <entry type="NameEntity" style="#c9c9c9"/>
+  <entry type="NameException" style="#cf5967"/>
+  <entry type="NameFunction" style="#57c7ff"/>
+  <entry type="NameLabel" style="#cf5967"/>
+  <entry type="NameNamespace" style="#c9c9c9"/>
+  <entry type="NameOther" style="#c9c9c9"/>
+  <entry type="NameTag" style="#bc74c4"/>
+  <entry type="NameVariable" style="italic #bc74c4"/>
+  <entry type="NameVariableClass" style="bold #57c7ff"/>
+  <entry type="NameVariableGlobal" style="#ecbe7b"/>
+  <entry type="NameVariableInstance" style="#57c7ff"/>
+  <entry type="Literal" style="#c9c9c9"/>
+  <entry type="LiteralDate" style="#57c7ff"/>
+  <entry type="LiteralString" style="#82cc6a"/>
+  <entry type="LiteralStringBacktick" style="#57c7ff"/>
+  <entry type="LiteralStringChar" style="#57c7ff"/>
+  <entry type="LiteralStringDoc" style="#82cc6a"/>
+  <entry type="LiteralStringDouble" style="#82cc6a"/>
+  <entry type="LiteralStringEscape" style="#56b6c2"/>
+  <entry type="LiteralStringHeredoc" style="#56b6c2"/>
+  <entry type="LiteralStringInterpol" style="#82cc6a"/>
+  <entry type="LiteralStringOther" style="#82cc6a"/>
+  <entry type="LiteralStringRegex" style="#57c7ff"/>
+  <entry type="LiteralStringSingle" style="#82cc6a"/>
+  <entry type="LiteralStringSymbol" style="#82cc6a"/>
+  <entry type="LiteralNumber" style="#56b6c2"/>
+  <entry type="LiteralNumberBin" style="#57c7ff"/>
+  <entry type="LiteralNumberFloat" style="#56b6c2"/>
+  <entry type="LiteralNumberHex" style="#57c7ff"/>
+  <entry type="LiteralNumberInteger" style="#56b6c2"/>
+  <entry type="LiteralNumberIntegerLong" style="#56b6c2"/>
+  <entry type="LiteralNumberOct" style="#57c7ff"/>
+  <entry type="Operator" style="#bc74c4"/>
+  <entry type="OperatorWord" style="#bc74c4"/>
+  <entry type="Punctuation" style="#56b6c2"/>
+  <entry type="Comment" style="#3e4460"/>
+  <entry type="CommentHashbang" style="italic #3e4460"/>
+  <entry type="CommentMultiline" style="#3e4460"/>
+  <entry type="CommentSingle" style="#3e4460"/>
+  <entry type="CommentSpecial" style="italic #bc74c4"/>
+  <entry type="CommentPreproc" style="#7fbaf5"/>
+  <entry type="Generic" style="#c9c9c9"/>
+  <entry type="GenericDeleted" style="#cf5967"/>
+  <entry type="GenericEmph" style="underline #c9c9c9"/>
+  <entry type="GenericError" style="bold #cf5967"/>
+  <entry type="GenericHeading" style="bold #ecbe7b"/>
+  <entry type="GenericInserted" style="#ecbe7b"/>
+  <entry type="GenericOutput" style="#43454f"/>
+  <entry type="GenericPrompt" style="#c9c9c9"/>
+  <entry type="GenericStrong" style="bold #cf5967"/>
+  <entry type="GenericSubheading" style="italic #cf5967"/>
+  <entry type="GenericTraceback" style="#c9c9c9"/>
+  <entry type="GenericUnderline" style="underline"/>
+  <entry type="Text" style="#c9c9c9"/>
+  <entry type="TextWhitespace" style="#c9c9c9"/>
+</style>
diff --git a/styles/embedded/witchhazel.xml b/styles/embedded/witchhazel.xml
new file mode 100644
index 0000000..4c175c9
--- /dev/null
+++ b/styles/embedded/witchhazel.xml
@@ -0,0 +1,31 @@
+<style name="witchhazel" theme="dark">
+  <entry type="Error" style="#960050 bg:#1e0010"/>
+  <entry type="Background" style="bg:#433e56"/>
+  <entry type="Keyword" style="#c2ffdf"/>
+  <entry type="KeywordNamespace" style="#ffb8d1"/>
+  <entry type="Name" style="#f8f8f2"/>
+  <entry type="NameAttribute" style="#ceb1ff"/>
+  <entry type="NameBuiltinPseudo" style="#80cbc4"/>
+  <entry type="NameClass" style="#ceb1ff"/>
+  <entry type="NameConstant" style="#c5a3ff"/>
+  <entry type="NameDecorator" style="#ceb1ff"/>
+  <entry type="NameException" style="#ceb1ff"/>
+  <entry type="NameFunction" style="#ceb1ff"/>
+  <entry type="NameProperty" style="#f8f8f2"/>
+  <entry type="NameTag" style="#ffb8d1"/>
+  <entry type="NameVariable" style="#f8f8f2"/>
+  <entry type="Literal" style="#ae81ff"/>
+  <entry type="LiteralDate" style="#e6db74"/>
+  <entry type="LiteralString" style="#1bc5e0"/>
+  <entry type="LiteralNumber" style="#c5a3ff"/>
+  <entry type="Operator" style="#ffb8d1"/>
+  <entry type="Punctuation" style="#f8f8f2"/>
+  <entry type="Comment" style="#b0bec5"/>
+  <entry type="GenericDeleted" style="#f92672"/>
+  <entry type="GenericEmph" style="italic"/>
+  <entry type="GenericInserted" style="#a6e22e"/>
+  <entry type="GenericStrong" style="bold"/>
+  <entry type="GenericSubheading" style="#75715e"/>
+  <entry type="Text" style="#f8f8f2"/>
+  <entry type="TextWhitespace" style="#a8757b"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/xcode-dark.xml b/styles/embedded/xcode-dark.xml
new file mode 100644
index 0000000..d2ba679
--- /dev/null
+++ b/styles/embedded/xcode-dark.xml
@@ -0,0 +1,31 @@
+<style name="xcode-dark" theme="dark">
+  <entry type="Error" style="#960050"/>
+  <entry type="Background" style="#ffffff bg:#1f1f24"/>
+  <entry type="Keyword" style="#fc5fa3"/>
+  <entry type="KeywordConstant" style="#fc5fa3"/>
+  <entry type="KeywordDeclaration" style="#fc5fa3"/>
+  <entry type="KeywordReserved" style="#fc5fa3"/>
+  <entry type="Name" style="#ffffff"/>
+  <entry type="NameBuiltin" style="#d0a8ff"/>
+  <entry type="NameBuiltinPseudo" style="#a167e6"/>
+  <entry type="NameClass" style="#5dd8ff"/>
+  <entry type="NameFunction" style="#41a1c0"/>
+  <entry type="NameVariable" style="#41a1c0"/>
+  <entry type="LiteralString" style="#fc6a5d"/>
+  <entry type="LiteralStringEscape" style="#fc6a5d"/>
+  <entry type="LiteralStringInterpol" style="#ffffff"/>
+  <entry type="LiteralNumber" style="#d0bf69"/>
+  <entry type="LiteralNumberBin" style="#d0bf69"/>
+  <entry type="LiteralNumberFloat" style="#d0bf69"/>
+  <entry type="LiteralNumberHex" style="#d0bf69"/>
+  <entry type="LiteralNumberInteger" style="#d0bf69"/>
+  <entry type="LiteralNumberOct" style="#d0bf69"/>
+  <entry type="Operator" style="#ffffff"/>
+  <entry type="Punctuation" style="#ffffff"/>
+  <entry type="Comment" style="#6c7986"/>
+  <entry type="CommentMultiline" style="#6c7986"/>
+  <entry type="CommentSingle" style="#6c7986"/>
+  <entry type="CommentSpecial" style="italic #6c7986"/>
+  <entry type="CommentPreproc" style="#fd8f3f"/>
+  <entry type="Text" style="#ffffff"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/xcode.xml b/styles/embedded/xcode.xml
new file mode 100644
index 0000000..9bfa0d1
--- /dev/null
+++ b/styles/embedded/xcode.xml
@@ -0,0 +1,22 @@
+<style name="xcode" theme="light">
+  <entry type="Error" style="#000000"/>
+  <entry type="Background" style="bg:#ffffff"/>
+  <entry type="Keyword" style="#a90d91"/>
+  <entry type="Name" style="#000000"/>
+  <entry type="NameAttribute" style="#836c28"/>
+  <entry type="NameBuiltin" style="#a90d91"/>
+  <entry type="NameBuiltinPseudo" style="#5b269a"/>
+  <entry type="NameClass" style="#3f6e75"/>
+  <entry type="NameDecorator" style="#000000"/>
+  <entry type="NameFunction" style="#000000"/>
+  <entry type="NameLabel" style="#000000"/>
+  <entry type="NameTag" style="#000000"/>
+  <entry type="NameVariable" style="#000000"/>
+  <entry type="Literal" style="#1c01ce"/>
+  <entry type="LiteralString" style="#c41a16"/>
+  <entry type="LiteralStringChar" style="#2300ce"/>
+  <entry type="LiteralNumber" style="#1c01ce"/>
+  <entry type="Operator" style="#000000"/>
+  <entry type="Comment" style="#177500"/>
+  <entry type="CommentPreproc" style="#633820"/>
+</style>
\ No newline at end of file
diff --git a/tokentype_enumer.go b/tokentype_enumer.go
new file mode 100644
index 0000000..696e9ce
--- /dev/null
+++ b/tokentype_enumer.go
@@ -0,0 +1,573 @@
+// Code generated by "enumer -text -type TokenType"; DO NOT EDIT.
+
+package chroma
+
+import (
+	"fmt"
+	"strings"
+)
+
+const _TokenTypeName = "NoneOtherErrorCodeLineLineLinkLineTableTDLineTableLineHighlightLineNumbersTableLineNumbersLinePreWrapperBackgroundEOFTypeKeywordKeywordConstantKeywordDeclarationKeywordNamespaceKeywordPseudoKeywordReservedKeywordTypeNameNameAttributeNameBuiltinNameBuiltinPseudoNameClassNameConstantNameDecoratorNameEntityNameExceptionNameFunctionNameFunctionMagicNameKeywordNameLabelNameNamespaceNameOperatorNameOtherNamePseudoNamePropertyNameTagNameVariableNameVariableAnonymousNameVariableClassNameVariableGlobalNameVariableInstanceNameVariableMagicLiteralLiteralDateLiteralOtherLiteralStringLiteralStringAffixLiteralStringAtomLiteralStringBacktickLiteralStringBooleanLiteralStringCharLiteralStringDelimiterLiteralStringDocLiteralStringDoubleLiteralStringEscapeLiteralStringHeredocLiteralStringInterpolLiteralStringNameLiteralStringOtherLiteralStringRegexLiteralStringSingleLiteralStringSymbolLiteralNumberLiteralNumberBinLiteralNumberFloatLiteralNumberHexLiteralNumberIntegerLiteralNumberIntegerLongLiteralNumberOctOperatorOperatorWordPunctuationCommentCommentHashbangCommentMultilineCommentSingleCommentSpecialCommentPreprocCommentPreprocFileGenericGenericDeletedGenericEmphGenericErrorGenericHeadingGenericInsertedGenericOutputGenericPromptGenericStrongGenericSubheadingGenericTracebackGenericUnderlineTextTextWhitespaceTextSymbolTextPunctuation"
+const _TokenTypeLowerName = "noneothererrorcodelinelinelinklinetabletdlinetablelinehighlightlinenumberstablelinenumberslineprewrapperbackgroundeoftypekeywordkeywordconstantkeyworddeclarationkeywordnamespacekeywordpseudokeywordreservedkeywordtypenamenameattributenamebuiltinnamebuiltinpseudonameclassnameconstantnamedecoratornameentitynameexceptionnamefunctionnamefunctionmagicnamekeywordnamelabelnamenamespacenameoperatornameothernamepseudonamepropertynametagnamevariablenamevariableanonymousnamevariableclassnamevariableglobalnamevariableinstancenamevariablemagicliteralliteraldateliteralotherliteralstringliteralstringaffixliteralstringatomliteralstringbacktickliteralstringbooleanliteralstringcharliteralstringdelimiterliteralstringdocliteralstringdoubleliteralstringescapeliteralstringheredocliteralstringinterpolliteralstringnameliteralstringotherliteralstringregexliteralstringsingleliteralstringsymbolliteralnumberliteralnumberbinliteralnumberfloatliteralnumberhexliteralnumberintegerliteralnumberintegerlongliteralnumberoctoperatoroperatorwordpunctuationcommentcommenthashbangcommentmultilinecommentsinglecommentspecialcommentpreproccommentpreprocfilegenericgenericdeletedgenericemphgenericerrorgenericheadinggenericinsertedgenericoutputgenericpromptgenericstronggenericsubheadinggenerictracebackgenericunderlinetexttextwhitespacetextsymboltextpunctuation"
+
+var _TokenTypeMap = map[TokenType]string{
+	-13:  _TokenTypeName[0:4],
+	-12:  _TokenTypeName[4:9],
+	-11:  _TokenTypeName[9:14],
+	-10:  _TokenTypeName[14:22],
+	-9:   _TokenTypeName[22:30],
+	-8:   _TokenTypeName[30:41],
+	-7:   _TokenTypeName[41:50],
+	-6:   _TokenTypeName[50:63],
+	-5:   _TokenTypeName[63:79],
+	-4:   _TokenTypeName[79:90],
+	-3:   _TokenTypeName[90:94],
+	-2:   _TokenTypeName[94:104],
+	-1:   _TokenTypeName[104:114],
+	0:    _TokenTypeName[114:121],
+	1000: _TokenTypeName[121:128],
+	1001: _TokenTypeName[128:143],
+	1002: _TokenTypeName[143:161],
+	1003: _TokenTypeName[161:177],
+	1004: _TokenTypeName[177:190],
+	1005: _TokenTypeName[190:205],
+	1006: _TokenTypeName[205:216],
+	2000: _TokenTypeName[216:220],
+	2001: _TokenTypeName[220:233],
+	2002: _TokenTypeName[233:244],
+	2003: _TokenTypeName[244:261],
+	2004: _TokenTypeName[261:270],
+	2005: _TokenTypeName[270:282],
+	2006: _TokenTypeName[282:295],
+	2007: _TokenTypeName[295:305],
+	2008: _TokenTypeName[305:318],
+	2009: _TokenTypeName[318:330],
+	2010: _TokenTypeName[330:347],
+	2011: _TokenTypeName[347:358],
+	2012: _TokenTypeName[358:367],
+	2013: _TokenTypeName[367:380],
+	2014: _TokenTypeName[380:392],
+	2015: _TokenTypeName[392:401],
+	2016: _TokenTypeName[401:411],
+	2017: _TokenTypeName[411:423],
+	2018: _TokenTypeName[423:430],
+	2019: _TokenTypeName[430:442],
+	2020: _TokenTypeName[442:463],
+	2021: _TokenTypeName[463:480],
+	2022: _TokenTypeName[480:498],
+	2023: _TokenTypeName[498:518],
+	2024: _TokenTypeName[518:535],
+	3000: _TokenTypeName[535:542],
+	3001: _TokenTypeName[542:553],
+	3002: _TokenTypeName[553:565],
+	3100: _TokenTypeName[565:578],
+	3101: _TokenTypeName[578:596],
+	3102: _TokenTypeName[596:613],
+	3103: _TokenTypeName[613:634],
+	3104: _TokenTypeName[634:654],
+	3105: _TokenTypeName[654:671],
+	3106: _TokenTypeName[671:693],
+	3107: _TokenTypeName[693:709],
+	3108: _TokenTypeName[709:728],
+	3109: _TokenTypeName[728:747],
+	3110: _TokenTypeName[747:767],
+	3111: _TokenTypeName[767:788],
+	3112: _TokenTypeName[788:805],
+	3113: _TokenTypeName[805:823],
+	3114: _TokenTypeName[823:841],
+	3115: _TokenTypeName[841:860],
+	3116: _TokenTypeName[860:879],
+	3200: _TokenTypeName[879:892],
+	3201: _TokenTypeName[892:908],
+	3202: _TokenTypeName[908:926],
+	3203: _TokenTypeName[926:942],
+	3204: _TokenTypeName[942:962],
+	3205: _TokenTypeName[962:986],
+	3206: _TokenTypeName[986:1002],
+	4000: _TokenTypeName[1002:1010],
+	4001: _TokenTypeName[1010:1022],
+	5000: _TokenTypeName[1022:1033],
+	6000: _TokenTypeName[1033:1040],
+	6001: _TokenTypeName[1040:1055],
+	6002: _TokenTypeName[1055:1071],
+	6003: _TokenTypeName[1071:1084],
+	6004: _TokenTypeName[1084:1098],
+	6100: _TokenTypeName[1098:1112],
+	6101: _TokenTypeName[1112:1130],
+	7000: _TokenTypeName[1130:1137],
+	7001: _TokenTypeName[1137:1151],
+	7002: _TokenTypeName[1151:1162],
+	7003: _TokenTypeName[1162:1174],
+	7004: _TokenTypeName[1174:1188],
+	7005: _TokenTypeName[1188:1203],
+	7006: _TokenTypeName[1203:1216],
+	7007: _TokenTypeName[1216:1229],
+	7008: _TokenTypeName[1229:1242],
+	7009: _TokenTypeName[1242:1259],
+	7010: _TokenTypeName[1259:1275],
+	7011: _TokenTypeName[1275:1291],
+	8000: _TokenTypeName[1291:1295],
+	8001: _TokenTypeName[1295:1309],
+	8002: _TokenTypeName[1309:1319],
+	8003: _TokenTypeName[1319:1334],
+}
+
+func (i TokenType) String() string {
+	if str, ok := _TokenTypeMap[i]; ok {
+		return str
+	}
+	return fmt.Sprintf("TokenType(%d)", i)
+}
+
+// An "invalid array index" compiler error signifies that the constant values have changed.
+// Re-run the stringer command to generate them again.
+func _TokenTypeNoOp() {
+	var x [1]struct{}
+	_ = x[None-(-13)]
+	_ = x[Other-(-12)]
+	_ = x[Error-(-11)]
+	_ = x[CodeLine-(-10)]
+	_ = x[LineLink-(-9)]
+	_ = x[LineTableTD-(-8)]
+	_ = x[LineTable-(-7)]
+	_ = x[LineHighlight-(-6)]
+	_ = x[LineNumbersTable-(-5)]
+	_ = x[LineNumbers-(-4)]
+	_ = x[Line-(-3)]
+	_ = x[PreWrapper-(-2)]
+	_ = x[Background-(-1)]
+	_ = x[EOFType-(0)]
+	_ = x[Keyword-(1000)]
+	_ = x[KeywordConstant-(1001)]
+	_ = x[KeywordDeclaration-(1002)]
+	_ = x[KeywordNamespace-(1003)]
+	_ = x[KeywordPseudo-(1004)]
+	_ = x[KeywordReserved-(1005)]
+	_ = x[KeywordType-(1006)]
+	_ = x[Name-(2000)]
+	_ = x[NameAttribute-(2001)]
+	_ = x[NameBuiltin-(2002)]
+	_ = x[NameBuiltinPseudo-(2003)]
+	_ = x[NameClass-(2004)]
+	_ = x[NameConstant-(2005)]
+	_ = x[NameDecorator-(2006)]
+	_ = x[NameEntity-(2007)]
+	_ = x[NameException-(2008)]
+	_ = x[NameFunction-(2009)]
+	_ = x[NameFunctionMagic-(2010)]
+	_ = x[NameKeyword-(2011)]
+	_ = x[NameLabel-(2012)]
+	_ = x[NameNamespace-(2013)]
+	_ = x[NameOperator-(2014)]
+	_ = x[NameOther-(2015)]
+	_ = x[NamePseudo-(2016)]
+	_ = x[NameProperty-(2017)]
+	_ = x[NameTag-(2018)]
+	_ = x[NameVariable-(2019)]
+	_ = x[NameVariableAnonymous-(2020)]
+	_ = x[NameVariableClass-(2021)]
+	_ = x[NameVariableGlobal-(2022)]
+	_ = x[NameVariableInstance-(2023)]
+	_ = x[NameVariableMagic-(2024)]
+	_ = x[Literal-(3000)]
+	_ = x[LiteralDate-(3001)]
+	_ = x[LiteralOther-(3002)]
+	_ = x[LiteralString-(3100)]
+	_ = x[LiteralStringAffix-(3101)]
+	_ = x[LiteralStringAtom-(3102)]
+	_ = x[LiteralStringBacktick-(3103)]
+	_ = x[LiteralStringBoolean-(3104)]
+	_ = x[LiteralStringChar-(3105)]
+	_ = x[LiteralStringDelimiter-(3106)]
+	_ = x[LiteralStringDoc-(3107)]
+	_ = x[LiteralStringDouble-(3108)]
+	_ = x[LiteralStringEscape-(3109)]
+	_ = x[LiteralStringHeredoc-(3110)]
+	_ = x[LiteralStringInterpol-(3111)]
+	_ = x[LiteralStringName-(3112)]
+	_ = x[LiteralStringOther-(3113)]
+	_ = x[LiteralStringRegex-(3114)]
+	_ = x[LiteralStringSingle-(3115)]
+	_ = x[LiteralStringSymbol-(3116)]
+	_ = x[LiteralNumber-(3200)]
+	_ = x[LiteralNumberBin-(3201)]
+	_ = x[LiteralNumberFloat-(3202)]
+	_ = x[LiteralNumberHex-(3203)]
+	_ = x[LiteralNumberInteger-(3204)]
+	_ = x[LiteralNumberIntegerLong-(3205)]
+	_ = x[LiteralNumberOct-(3206)]
+	_ = x[Operator-(4000)]
+	_ = x[OperatorWord-(4001)]
+	_ = x[Punctuation-(5000)]
+	_ = x[Comment-(6000)]
+	_ = x[CommentHashbang-(6001)]
+	_ = x[CommentMultiline-(6002)]
+	_ = x[CommentSingle-(6003)]
+	_ = x[CommentSpecial-(6004)]
+	_ = x[CommentPreproc-(6100)]
+	_ = x[CommentPreprocFile-(6101)]
+	_ = x[Generic-(7000)]
+	_ = x[GenericDeleted-(7001)]
+	_ = x[GenericEmph-(7002)]
+	_ = x[GenericError-(7003)]
+	_ = x[GenericHeading-(7004)]
+	_ = x[GenericInserted-(7005)]
+	_ = x[GenericOutput-(7006)]
+	_ = x[GenericPrompt-(7007)]
+	_ = x[GenericStrong-(7008)]
+	_ = x[GenericSubheading-(7009)]
+	_ = x[GenericTraceback-(7010)]
+	_ = x[GenericUnderline-(7011)]
+	_ = x[Text-(8000)]
+	_ = x[TextWhitespace-(8001)]
+	_ = x[TextSymbol-(8002)]
+	_ = x[TextPunctuation-(8003)]
+}
+
+var _TokenTypeValues = []TokenType{None, Other, Error, CodeLine, LineLink, LineTableTD, LineTable, LineHighlight, LineNumbersTable, LineNumbers, Line, PreWrapper, Background, EOFType, Keyword, KeywordConstant, KeywordDeclaration, KeywordNamespace, KeywordPseudo, KeywordReserved, KeywordType, Name, NameAttribute, NameBuiltin, NameBuiltinPseudo, NameClass, NameConstant, NameDecorator, NameEntity, NameException, NameFunction, NameFunctionMagic, NameKeyword, NameLabel, NameNamespace, NameOperator, NameOther, NamePseudo, NameProperty, NameTag, NameVariable, NameVariableAnonymous, NameVariableClass, NameVariableGlobal, NameVariableInstance, NameVariableMagic, Literal, LiteralDate, LiteralOther, LiteralString, LiteralStringAffix, LiteralStringAtom, LiteralStringBacktick, LiteralStringBoolean, LiteralStringChar, LiteralStringDelimiter, LiteralStringDoc, LiteralStringDouble, LiteralStringEscape, LiteralStringHeredoc, LiteralStringInterpol, LiteralStringName, LiteralStringOther, LiteralStringRegex, LiteralStringSingle, LiteralStringSymbol, LiteralNumber, LiteralNumberBin, LiteralNumberFloat, LiteralNumberHex, LiteralNumberInteger, LiteralNumberIntegerLong, LiteralNumberOct, Operator, OperatorWord, Punctuation, Comment, CommentHashbang, CommentMultiline, CommentSingle, CommentSpecial, CommentPreproc, CommentPreprocFile, Generic, GenericDeleted, GenericEmph, GenericError, GenericHeading, GenericInserted, GenericOutput, GenericPrompt, GenericStrong, GenericSubheading, GenericTraceback, GenericUnderline, Text, TextWhitespace, TextSymbol, TextPunctuation}
+
+var _TokenTypeNameToValueMap = map[string]TokenType{
+	_TokenTypeName[0:4]:            None,
+	_TokenTypeLowerName[0:4]:       None,
+	_TokenTypeName[4:9]:            Other,
+	_TokenTypeLowerName[4:9]:       Other,
+	_TokenTypeName[9:14]:           Error,
+	_TokenTypeLowerName[9:14]:      Error,
+	_TokenTypeName[14:22]:          CodeLine,
+	_TokenTypeLowerName[14:22]:     CodeLine,
+	_TokenTypeName[22:30]:          LineLink,
+	_TokenTypeLowerName[22:30]:     LineLink,
+	_TokenTypeName[30:41]:          LineTableTD,
+	_TokenTypeLowerName[30:41]:     LineTableTD,
+	_TokenTypeName[41:50]:          LineTable,
+	_TokenTypeLowerName[41:50]:     LineTable,
+	_TokenTypeName[50:63]:          LineHighlight,
+	_TokenTypeLowerName[50:63]:     LineHighlight,
+	_TokenTypeName[63:79]:          LineNumbersTable,
+	_TokenTypeLowerName[63:79]:     LineNumbersTable,
+	_TokenTypeName[79:90]:          LineNumbers,
+	_TokenTypeLowerName[79:90]:     LineNumbers,
+	_TokenTypeName[90:94]:          Line,
+	_TokenTypeLowerName[90:94]:     Line,
+	_TokenTypeName[94:104]:         PreWrapper,
+	_TokenTypeLowerName[94:104]:    PreWrapper,
+	_TokenTypeName[104:114]:        Background,
+	_TokenTypeLowerName[104:114]:   Background,
+	_TokenTypeName[114:121]:        EOFType,
+	_TokenTypeLowerName[114:121]:   EOFType,
+	_TokenTypeName[121:128]:        Keyword,
+	_TokenTypeLowerName[121:128]:   Keyword,
+	_TokenTypeName[128:143]:        KeywordConstant,
+	_TokenTypeLowerName[128:143]:   KeywordConstant,
+	_TokenTypeName[143:161]:        KeywordDeclaration,
+	_TokenTypeLowerName[143:161]:   KeywordDeclaration,
+	_TokenTypeName[161:177]:        KeywordNamespace,
+	_TokenTypeLowerName[161:177]:   KeywordNamespace,
+	_TokenTypeName[177:190]:        KeywordPseudo,
+	_TokenTypeLowerName[177:190]:   KeywordPseudo,
+	_TokenTypeName[190:205]:        KeywordReserved,
+	_TokenTypeLowerName[190:205]:   KeywordReserved,
+	_TokenTypeName[205:216]:        KeywordType,
+	_TokenTypeLowerName[205:216]:   KeywordType,
+	_TokenTypeName[216:220]:        Name,
+	_TokenTypeLowerName[216:220]:   Name,
+	_TokenTypeName[220:233]:        NameAttribute,
+	_TokenTypeLowerName[220:233]:   NameAttribute,
+	_TokenTypeName[233:244]:        NameBuiltin,
+	_TokenTypeLowerName[233:244]:   NameBuiltin,
+	_TokenTypeName[244:261]:        NameBuiltinPseudo,
+	_TokenTypeLowerName[244:261]:   NameBuiltinPseudo,
+	_TokenTypeName[261:270]:        NameClass,
+	_TokenTypeLowerName[261:270]:   NameClass,
+	_TokenTypeName[270:282]:        NameConstant,
+	_TokenTypeLowerName[270:282]:   NameConstant,
+	_TokenTypeName[282:295]:        NameDecorator,
+	_TokenTypeLowerName[282:295]:   NameDecorator,
+	_TokenTypeName[295:305]:        NameEntity,
+	_TokenTypeLowerName[295:305]:   NameEntity,
+	_TokenTypeName[305:318]:        NameException,
+	_TokenTypeLowerName[305:318]:   NameException,
+	_TokenTypeName[318:330]:        NameFunction,
+	_TokenTypeLowerName[318:330]:   NameFunction,
+	_TokenTypeName[330:347]:        NameFunctionMagic,
+	_TokenTypeLowerName[330:347]:   NameFunctionMagic,
+	_TokenTypeName[347:358]:        NameKeyword,
+	_TokenTypeLowerName[347:358]:   NameKeyword,
+	_TokenTypeName[358:367]:        NameLabel,
+	_TokenTypeLowerName[358:367]:   NameLabel,
+	_TokenTypeName[367:380]:        NameNamespace,
+	_TokenTypeLowerName[367:380]:   NameNamespace,
+	_TokenTypeName[380:392]:        NameOperator,
+	_TokenTypeLowerName[380:392]:   NameOperator,
+	_TokenTypeName[392:401]:        NameOther,
+	_TokenTypeLowerName[392:401]:   NameOther,
+	_TokenTypeName[401:411]:        NamePseudo,
+	_TokenTypeLowerName[401:411]:   NamePseudo,
+	_TokenTypeName[411:423]:        NameProperty,
+	_TokenTypeLowerName[411:423]:   NameProperty,
+	_TokenTypeName[423:430]:        NameTag,
+	_TokenTypeLowerName[423:430]:   NameTag,
+	_TokenTypeName[430:442]:        NameVariable,
+	_TokenTypeLowerName[430:442]:   NameVariable,
+	_TokenTypeName[442:463]:        NameVariableAnonymous,
+	_TokenTypeLowerName[442:463]:   NameVariableAnonymous,
+	_TokenTypeName[463:480]:        NameVariableClass,
+	_TokenTypeLowerName[463:480]:   NameVariableClass,
+	_TokenTypeName[480:498]:        NameVariableGlobal,
+	_TokenTypeLowerName[480:498]:   NameVariableGlobal,
+	_TokenTypeName[498:518]:        NameVariableInstance,
+	_TokenTypeLowerName[498:518]:   NameVariableInstance,
+	_TokenTypeName[518:535]:        NameVariableMagic,
+	_TokenTypeLowerName[518:535]:   NameVariableMagic,
+	_TokenTypeName[535:542]:        Literal,
+	_TokenTypeLowerName[535:542]:   Literal,
+	_TokenTypeName[542:553]:        LiteralDate,
+	_TokenTypeLowerName[542:553]:   LiteralDate,
+	_TokenTypeName[553:565]:        LiteralOther,
+	_TokenTypeLowerName[553:565]:   LiteralOther,
+	_TokenTypeName[565:578]:        LiteralString,
+	_TokenTypeLowerName[565:578]:   LiteralString,
+	_TokenTypeName[578:596]:        LiteralStringAffix,
+	_TokenTypeLowerName[578:596]:   LiteralStringAffix,
+	_TokenTypeName[596:613]:        LiteralStringAtom,
+	_TokenTypeLowerName[596:613]:   LiteralStringAtom,
+	_TokenTypeName[613:634]:        LiteralStringBacktick,
+	_TokenTypeLowerName[613:634]:   LiteralStringBacktick,
+	_TokenTypeName[634:654]:        LiteralStringBoolean,
+	_TokenTypeLowerName[634:654]:   LiteralStringBoolean,
+	_TokenTypeName[654:671]:        LiteralStringChar,
+	_TokenTypeLowerName[654:671]:   LiteralStringChar,
+	_TokenTypeName[671:693]:        LiteralStringDelimiter,
+	_TokenTypeLowerName[671:693]:   LiteralStringDelimiter,
+	_TokenTypeName[693:709]:        LiteralStringDoc,
+	_TokenTypeLowerName[693:709]:   LiteralStringDoc,
+	_TokenTypeName[709:728]:        LiteralStringDouble,
+	_TokenTypeLowerName[709:728]:   LiteralStringDouble,
+	_TokenTypeName[728:747]:        LiteralStringEscape,
+	_TokenTypeLowerName[728:747]:   LiteralStringEscape,
+	_TokenTypeName[747:767]:        LiteralStringHeredoc,
+	_TokenTypeLowerName[747:767]:   LiteralStringHeredoc,
+	_TokenTypeName[767:788]:        LiteralStringInterpol,
+	_TokenTypeLowerName[767:788]:   LiteralStringInterpol,
+	_TokenTypeName[788:805]:        LiteralStringName,
+	_TokenTypeLowerName[788:805]:   LiteralStringName,
+	_TokenTypeName[805:823]:        LiteralStringOther,
+	_TokenTypeLowerName[805:823]:   LiteralStringOther,
+	_TokenTypeName[823:841]:        LiteralStringRegex,
+	_TokenTypeLowerName[823:841]:   LiteralStringRegex,
+	_TokenTypeName[841:860]:        LiteralStringSingle,
+	_TokenTypeLowerName[841:860]:   LiteralStringSingle,
+	_TokenTypeName[860:879]:        LiteralStringSymbol,
+	_TokenTypeLowerName[860:879]:   LiteralStringSymbol,
+	_TokenTypeName[879:892]:        LiteralNumber,
+	_TokenTypeLowerName[879:892]:   LiteralNumber,
+	_TokenTypeName[892:908]:        LiteralNumberBin,
+	_TokenTypeLowerName[892:908]:   LiteralNumberBin,
+	_TokenTypeName[908:926]:        LiteralNumberFloat,
+	_TokenTypeLowerName[908:926]:   LiteralNumberFloat,
+	_TokenTypeName[926:942]:        LiteralNumberHex,
+	_TokenTypeLowerName[926:942]:   LiteralNumberHex,
+	_TokenTypeName[942:962]:        LiteralNumberInteger,
+	_TokenTypeLowerName[942:962]:   LiteralNumberInteger,
+	_TokenTypeName[962:986]:        LiteralNumberIntegerLong,
+	_TokenTypeLowerName[962:986]:   LiteralNumberIntegerLong,
+	_TokenTypeName[986:1002]:       LiteralNumberOct,
+	_TokenTypeLowerName[986:1002]:  LiteralNumberOct,
+	_TokenTypeName[1002:1010]:      Operator,
+	_TokenTypeLowerName[1002:1010]: Operator,
+	_TokenTypeName[1010:1022]:      OperatorWord,
+	_TokenTypeLowerName[1010:1022]: OperatorWord,
+	_TokenTypeName[1022:1033]:      Punctuation,
+	_TokenTypeLowerName[1022:1033]: Punctuation,
+	_TokenTypeName[1033:1040]:      Comment,
+	_TokenTypeLowerName[1033:1040]: Comment,
+	_TokenTypeName[1040:1055]:      CommentHashbang,
+	_TokenTypeLowerName[1040:1055]: CommentHashbang,
+	_TokenTypeName[1055:1071]:      CommentMultiline,
+	_TokenTypeLowerName[1055:1071]: CommentMultiline,
+	_TokenTypeName[1071:1084]:      CommentSingle,
+	_TokenTypeLowerName[1071:1084]: CommentSingle,
+	_TokenTypeName[1084:1098]:      CommentSpecial,
+	_TokenTypeLowerName[1084:1098]: CommentSpecial,
+	_TokenTypeName[1098:1112]:      CommentPreproc,
+	_TokenTypeLowerName[1098:1112]: CommentPreproc,
+	_TokenTypeName[1112:1130]:      CommentPreprocFile,
+	_TokenTypeLowerName[1112:1130]: CommentPreprocFile,
+	_TokenTypeName[1130:1137]:      Generic,
+	_TokenTypeLowerName[1130:1137]: Generic,
+	_TokenTypeName[1137:1151]:      GenericDeleted,
+	_TokenTypeLowerName[1137:1151]: GenericDeleted,
+	_TokenTypeName[1151:1162]:      GenericEmph,
+	_TokenTypeLowerName[1151:1162]: GenericEmph,
+	_TokenTypeName[1162:1174]:      GenericError,
+	_TokenTypeLowerName[1162:1174]: GenericError,
+	_TokenTypeName[1174:1188]:      GenericHeading,
+	_TokenTypeLowerName[1174:1188]: GenericHeading,
+	_TokenTypeName[1188:1203]:      GenericInserted,
+	_TokenTypeLowerName[1188:1203]: GenericInserted,
+	_TokenTypeName[1203:1216]:      GenericOutput,
+	_TokenTypeLowerName[1203:1216]: GenericOutput,
+	_TokenTypeName[1216:1229]:      GenericPrompt,
+	_TokenTypeLowerName[1216:1229]: GenericPrompt,
+	_TokenTypeName[1229:1242]:      GenericStrong,
+	_TokenTypeLowerName[1229:1242]: GenericStrong,
+	_TokenTypeName[1242:1259]:      GenericSubheading,
+	_TokenTypeLowerName[1242:1259]: GenericSubheading,
+	_TokenTypeName[1259:1275]:      GenericTraceback,
+	_TokenTypeLowerName[1259:1275]: GenericTraceback,
+	_TokenTypeName[1275:1291]:      GenericUnderline,
+	_TokenTypeLowerName[1275:1291]: GenericUnderline,
+	_TokenTypeName[1291:1295]:      Text,
+	_TokenTypeLowerName[1291:1295]: Text,
+	_TokenTypeName[1295:1309]:      TextWhitespace,
+	_TokenTypeLowerName[1295:1309]: TextWhitespace,
+	_TokenTypeName[1309:1319]:      TextSymbol,
+	_TokenTypeLowerName[1309:1319]: TextSymbol,
+	_TokenTypeName[1319:1334]:      TextPunctuation,
+	_TokenTypeLowerName[1319:1334]: TextPunctuation,
+}
+
+var _TokenTypeNames = []string{
+	_TokenTypeName[0:4],
+	_TokenTypeName[4:9],
+	_TokenTypeName[9:14],
+	_TokenTypeName[14:22],
+	_TokenTypeName[22:30],
+	_TokenTypeName[30:41],
+	_TokenTypeName[41:50],
+	_TokenTypeName[50:63],
+	_TokenTypeName[63:79],
+	_TokenTypeName[79:90],
+	_TokenTypeName[90:94],
+	_TokenTypeName[94:104],
+	_TokenTypeName[104:114],
+	_TokenTypeName[114:121],
+	_TokenTypeName[121:128],
+	_TokenTypeName[128:143],
+	_TokenTypeName[143:161],
+	_TokenTypeName[161:177],
+	_TokenTypeName[177:190],
+	_TokenTypeName[190:205],
+	_TokenTypeName[205:216],
+	_TokenTypeName[216:220],
+	_TokenTypeName[220:233],
+	_TokenTypeName[233:244],
+	_TokenTypeName[244:261],
+	_TokenTypeName[261:270],
+	_TokenTypeName[270:282],
+	_TokenTypeName[282:295],
+	_TokenTypeName[295:305],
+	_TokenTypeName[305:318],
+	_TokenTypeName[318:330],
+	_TokenTypeName[330:347],
+	_TokenTypeName[347:358],
+	_TokenTypeName[358:367],
+	_TokenTypeName[367:380],
+	_TokenTypeName[380:392],
+	_TokenTypeName[392:401],
+	_TokenTypeName[401:411],
+	_TokenTypeName[411:423],
+	_TokenTypeName[423:430],
+	_TokenTypeName[430:442],
+	_TokenTypeName[442:463],
+	_TokenTypeName[463:480],
+	_TokenTypeName[480:498],
+	_TokenTypeName[498:518],
+	_TokenTypeName[518:535],
+	_TokenTypeName[535:542],
+	_TokenTypeName[542:553],
+	_TokenTypeName[553:565],
+	_TokenTypeName[565:578],
+	_TokenTypeName[578:596],
+	_TokenTypeName[596:613],
+	_TokenTypeName[613:634],
+	_TokenTypeName[634:654],
+	_TokenTypeName[654:671],
+	_TokenTypeName[671:693],
+	_TokenTypeName[693:709],
+	_TokenTypeName[709:728],
+	_TokenTypeName[728:747],
+	_TokenTypeName[747:767],
+	_TokenTypeName[767:788],
+	_TokenTypeName[788:805],
+	_TokenTypeName[805:823],
+	_TokenTypeName[823:841],
+	_TokenTypeName[841:860],
+	_TokenTypeName[860:879],
+	_TokenTypeName[879:892],
+	_TokenTypeName[892:908],
+	_TokenTypeName[908:926],
+	_TokenTypeName[926:942],
+	_TokenTypeName[942:962],
+	_TokenTypeName[962:986],
+	_TokenTypeName[986:1002],
+	_TokenTypeName[1002:1010],
+	_TokenTypeName[1010:1022],
+	_TokenTypeName[1022:1033],
+	_TokenTypeName[1033:1040],
+	_TokenTypeName[1040:1055],
+	_TokenTypeName[1055:1071],
+	_TokenTypeName[1071:1084],
+	_TokenTypeName[1084:1098],
+	_TokenTypeName[1098:1112],
+	_TokenTypeName[1112:1130],
+	_TokenTypeName[1130:1137],
+	_TokenTypeName[1137:1151],
+	_TokenTypeName[1151:1162],
+	_TokenTypeName[1162:1174],
+	_TokenTypeName[1174:1188],
+	_TokenTypeName[1188:1203],
+	_TokenTypeName[1203:1216],
+	_TokenTypeName[1216:1229],
+	_TokenTypeName[1229:1242],
+	_TokenTypeName[1242:1259],
+	_TokenTypeName[1259:1275],
+	_TokenTypeName[1275:1291],
+	_TokenTypeName[1291:1295],
+	_TokenTypeName[1295:1309],
+	_TokenTypeName[1309:1319],
+	_TokenTypeName[1319:1334],
+}
+
+// TokenTypeString retrieves an enum value from the enum constants string name.
+// Throws an error if the param is not part of the enum.
+func TokenTypeString(s string) (TokenType, error) {
+	if val, ok := _TokenTypeNameToValueMap[s]; ok {
+		return val, nil
+	}
+
+	if val, ok := _TokenTypeNameToValueMap[strings.ToLower(s)]; ok {
+		return val, nil
+	}
+	return 0, fmt.Errorf("%s does not belong to TokenType values", s)
+}
+
+// TokenTypeValues returns all values of the enum
+func TokenTypeValues() []TokenType {
+	return _TokenTypeValues
+}
+
+// TokenTypeStrings returns a slice of all String values of the enum
+func TokenTypeStrings() []string {
+	strs := make([]string, len(_TokenTypeNames))
+	copy(strs, _TokenTypeNames)
+	return strs
+}
+
+// IsATokenType returns "true" if the value is listed in the enum definition. "false" otherwise
+func (i TokenType) IsATokenType() bool {
+	_, ok := _TokenTypeMap[i]
+	return ok
+}
+
+// MarshalText implements the encoding.TextMarshaler interface for TokenType
+func (i TokenType) MarshalText() ([]byte, error) {
+	return []byte(i.String()), nil
+}
+
+// UnmarshalText implements the encoding.TextUnmarshaler interface for TokenType
+func (i *TokenType) UnmarshalText(text []byte) error {
+	var err error
+	*i, err = TokenTypeString(string(text))
+	return err
+}
diff --git a/types.go b/types.go
new file mode 100644
index 0000000..3d12310
--- /dev/null
+++ b/types.go
@@ -0,0 +1,340 @@
+package chroma
+
+//go:generate enumer -text -type TokenType
+
+// TokenType is the type of token to highlight.
+//
+// It is also an Emitter, emitting a single token of itself
+type TokenType int
+
+// Set of TokenTypes.
+//
+// Categories of types are grouped in ranges of 1000, while sub-categories are in ranges of 100. For
+// example, the literal category is in the range 3000-3999. The sub-category for literal strings is
+// in the range 3100-3199.
+
+// Meta token types.
+const (
+	// Default background style.
+	Background TokenType = -1 - iota
+	// PreWrapper style.
+	PreWrapper
+	// Line style.
+	Line
+	// Line numbers in output.
+	LineNumbers
+	// Line numbers in output when in table.
+	LineNumbersTable
+	// Line higlight style.
+	LineHighlight
+	// Line numbers table wrapper style.
+	LineTable
+	// Line numbers table TD wrapper style.
+	LineTableTD
+	// Line number links.
+	LineLink
+	// Code line wrapper style.
+	CodeLine
+	// Input that could not be tokenised.
+	Error
+	// Other is used by the Delegate lexer to indicate which tokens should be handled by the delegate.
+	Other
+	// No highlighting.
+	None
+	// Used as an EOF marker / nil token
+	EOFType TokenType = 0
+)
+
+// Keywords.
+const (
+	Keyword TokenType = 1000 + iota
+	KeywordConstant
+	KeywordDeclaration
+	KeywordNamespace
+	KeywordPseudo
+	KeywordReserved
+	KeywordType
+)
+
+// Names.
+const (
+	Name TokenType = 2000 + iota
+	NameAttribute
+	NameBuiltin
+	NameBuiltinPseudo
+	NameClass
+	NameConstant
+	NameDecorator
+	NameEntity
+	NameException
+	NameFunction
+	NameFunctionMagic
+	NameKeyword
+	NameLabel
+	NameNamespace
+	NameOperator
+	NameOther
+	NamePseudo
+	NameProperty
+	NameTag
+	NameVariable
+	NameVariableAnonymous
+	NameVariableClass
+	NameVariableGlobal
+	NameVariableInstance
+	NameVariableMagic
+)
+
+// Literals.
+const (
+	Literal TokenType = 3000 + iota
+	LiteralDate
+	LiteralOther
+)
+
+// Strings.
+const (
+	LiteralString TokenType = 3100 + iota
+	LiteralStringAffix
+	LiteralStringAtom
+	LiteralStringBacktick
+	LiteralStringBoolean
+	LiteralStringChar
+	LiteralStringDelimiter
+	LiteralStringDoc
+	LiteralStringDouble
+	LiteralStringEscape
+	LiteralStringHeredoc
+	LiteralStringInterpol
+	LiteralStringName
+	LiteralStringOther
+	LiteralStringRegex
+	LiteralStringSingle
+	LiteralStringSymbol
+)
+
+// Literals.
+const (
+	LiteralNumber TokenType = 3200 + iota
+	LiteralNumberBin
+	LiteralNumberFloat
+	LiteralNumberHex
+	LiteralNumberInteger
+	LiteralNumberIntegerLong
+	LiteralNumberOct
+)
+
+// Operators.
+const (
+	Operator TokenType = 4000 + iota
+	OperatorWord
+)
+
+// Punctuation.
+const (
+	Punctuation TokenType = 5000 + iota
+)
+
+// Comments.
+const (
+	Comment TokenType = 6000 + iota
+	CommentHashbang
+	CommentMultiline
+	CommentSingle
+	CommentSpecial
+)
+
+// Preprocessor "comments".
+const (
+	CommentPreproc TokenType = 6100 + iota
+	CommentPreprocFile
+)
+
+// Generic tokens.
+const (
+	Generic TokenType = 7000 + iota
+	GenericDeleted
+	GenericEmph
+	GenericError
+	GenericHeading
+	GenericInserted
+	GenericOutput
+	GenericPrompt
+	GenericStrong
+	GenericSubheading
+	GenericTraceback
+	GenericUnderline
+)
+
+// Text.
+const (
+	Text TokenType = 8000 + iota
+	TextWhitespace
+	TextSymbol
+	TextPunctuation
+)
+
+// Aliases.
+const (
+	Whitespace = TextWhitespace
+
+	Date = LiteralDate
+
+	String          = LiteralString
+	StringAffix     = LiteralStringAffix
+	StringBacktick  = LiteralStringBacktick
+	StringChar      = LiteralStringChar
+	StringDelimiter = LiteralStringDelimiter
+	StringDoc       = LiteralStringDoc
+	StringDouble    = LiteralStringDouble
+	StringEscape    = LiteralStringEscape
+	StringHeredoc   = LiteralStringHeredoc
+	StringInterpol  = LiteralStringInterpol
+	StringOther     = LiteralStringOther
+	StringRegex     = LiteralStringRegex
+	StringSingle    = LiteralStringSingle
+	StringSymbol    = LiteralStringSymbol
+
+	Number            = LiteralNumber
+	NumberBin         = LiteralNumberBin
+	NumberFloat       = LiteralNumberFloat
+	NumberHex         = LiteralNumberHex
+	NumberInteger     = LiteralNumberInteger
+	NumberIntegerLong = LiteralNumberIntegerLong
+	NumberOct         = LiteralNumberOct
+)
+
+var (
+	StandardTypes = map[TokenType]string{
+		Background:       "bg",
+		PreWrapper:       "chroma",
+		Line:             "line",
+		LineNumbers:      "ln",
+		LineNumbersTable: "lnt",
+		LineHighlight:    "hl",
+		LineTable:        "lntable",
+		LineTableTD:      "lntd",
+		LineLink:         "lnlinks",
+		CodeLine:         "cl",
+		Text:             "",
+		Whitespace:       "w",
+		Error:            "err",
+		Other:            "x",
+		// I have no idea what this is used for...
+		// Escape:     "esc",
+
+		Keyword:            "k",
+		KeywordConstant:    "kc",
+		KeywordDeclaration: "kd",
+		KeywordNamespace:   "kn",
+		KeywordPseudo:      "kp",
+		KeywordReserved:    "kr",
+		KeywordType:        "kt",
+
+		Name:                 "n",
+		NameAttribute:        "na",
+		NameBuiltin:          "nb",
+		NameBuiltinPseudo:    "bp",
+		NameClass:            "nc",
+		NameConstant:         "no",
+		NameDecorator:        "nd",
+		NameEntity:           "ni",
+		NameException:        "ne",
+		NameFunction:         "nf",
+		NameFunctionMagic:    "fm",
+		NameProperty:         "py",
+		NameLabel:            "nl",
+		NameNamespace:        "nn",
+		NameOther:            "nx",
+		NameTag:              "nt",
+		NameVariable:         "nv",
+		NameVariableClass:    "vc",
+		NameVariableGlobal:   "vg",
+		NameVariableInstance: "vi",
+		NameVariableMagic:    "vm",
+
+		Literal:     "l",
+		LiteralDate: "ld",
+
+		String:          "s",
+		StringAffix:     "sa",
+		StringBacktick:  "sb",
+		StringChar:      "sc",
+		StringDelimiter: "dl",
+		StringDoc:       "sd",
+		StringDouble:    "s2",
+		StringEscape:    "se",
+		StringHeredoc:   "sh",
+		StringInterpol:  "si",
+		StringOther:     "sx",
+		StringRegex:     "sr",
+		StringSingle:    "s1",
+		StringSymbol:    "ss",
+
+		Number:            "m",
+		NumberBin:         "mb",
+		NumberFloat:       "mf",
+		NumberHex:         "mh",
+		NumberInteger:     "mi",
+		NumberIntegerLong: "il",
+		NumberOct:         "mo",
+
+		Operator:     "o",
+		OperatorWord: "ow",
+
+		Punctuation: "p",
+
+		Comment:            "c",
+		CommentHashbang:    "ch",
+		CommentMultiline:   "cm",
+		CommentPreproc:     "cp",
+		CommentPreprocFile: "cpf",
+		CommentSingle:      "c1",
+		CommentSpecial:     "cs",
+
+		Generic:           "g",
+		GenericDeleted:    "gd",
+		GenericEmph:       "ge",
+		GenericError:      "gr",
+		GenericHeading:    "gh",
+		GenericInserted:   "gi",
+		GenericOutput:     "go",
+		GenericPrompt:     "gp",
+		GenericStrong:     "gs",
+		GenericSubheading: "gu",
+		GenericTraceback:  "gt",
+		GenericUnderline:  "gl",
+	}
+)
+
+func (t TokenType) Parent() TokenType {
+	if t%100 != 0 {
+		return t / 100 * 100
+	}
+	if t%1000 != 0 {
+		return t / 1000 * 1000
+	}
+	return 0
+}
+
+func (t TokenType) Category() TokenType {
+	return t / 1000 * 1000
+}
+
+func (t TokenType) SubCategory() TokenType {
+	return t / 100 * 100
+}
+
+func (t TokenType) InCategory(other TokenType) bool {
+	return t/1000 == other/1000
+}
+
+func (t TokenType) InSubCategory(other TokenType) bool {
+	return t/100 == other/100
+}
+
+func (t TokenType) Emit(groups []string, _ *LexerState) Iterator {
+	return Literator(Token{Type: t, Value: groups[0]})
+}
+
+func (t TokenType) EmitterKind() string { return "token" }