Full Code of tj/go-termd for AI

master 7f6aeb166380 cached
13 files
21.6 KB
7.8k tokens
14 symbols
1 requests
Download .txt
Repository: tj/go-termd
Branch: master
Commit: 7f6aeb166380
Files: 13
Total size: 21.6 KB

Directory structure:
gitextract_09an3s_0/

├── .github/
│   ├── FUNDING.yml
│   ├── ISSUE_TEMPLATE.yml
│   └── PULL_REQUEST_TEMPLATE.md
├── .gitignore
├── LICENSE
├── Readme.md
├── go.mod
├── go.sum
├── highlight.go
├── termd.go
├── termd_test.go
├── testdata/
│   └── example.md
└── theme.go

================================================
FILE CONTENTS
================================================

================================================
FILE: .github/FUNDING.yml
================================================
github: tj

================================================
FILE: .github/ISSUE_TEMPLATE.yml
================================================
## Prerequisites

* [ ] I searched to see if the issue already exists.

## Description

Describe the bug or feature.

## Steps to Reproduce

Describe the steps required to reproduce the issue if applicable.

## Slack

Join us on Slack https://chat.apex.sh/


================================================
FILE: .github/PULL_REQUEST_TEMPLATE.md
================================================
Please open an issue and discuss changes before spending time on them, unless the change is trivial or an issue already exists.


================================================
FILE: .gitignore
================================================
.envrc


================================================
FILE: LICENSE
================================================
The MIT License

Copyright (c) 2019 TJ Holowaychuk tj@tjholowaychuk.com

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
'Software'), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.



================================================
FILE: Readme.md
================================================
# Termd

Package termd provides terminal markdown rendering, with code block syntax highlighting support.

## Features

- Code block syntax highlighting (JSON-friendly for loading from user config)
- Word wrapping to the specified column width
- Terminal specific styling (still looks like markdown but it's cleaned up for the term)

![](https://apex-software.imgix.net/github/tj/termd/screenshot.png)

---

[![GoDoc](https://godoc.org/github.com/tj/go-termd?status.svg)](https://godoc.org/github.com/tj/go-termd)
![](https://img.shields.io/badge/license-MIT-blue.svg)
![](https://img.shields.io/badge/status-stable-green.svg)

## Sponsors

This project is [sponsored](https://github.com/sponsors/tj) by [CTO.ai](https://cto.ai/), making it easy for development teams to create and share workflow automations without leaving the command line.

[![](https://apex-software.imgix.net/github/sponsors/cto.png)](https://cto.ai/)




================================================
FILE: go.mod
================================================
module github.com/tj/go-termd

go 1.13

require (
	github.com/alecthomas/chroma v0.6.8
	github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59
	github.com/kr/text v0.1.0
	github.com/mitchellh/go-wordwrap v1.0.0
	github.com/russross/blackfriday/v2 v2.0.1
	github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect
	github.com/tj/go-css v0.0.0-20191108133013-220a796d1705
)


================================================
FILE: go.sum
================================================
github.com/GeertJohan/go.incremental v1.0.0/go.mod h1:6fAjUhbVuX1KcMD3c8TEgVUqmo4seqhv0i0kdATSkM0=
github.com/GeertJohan/go.rice v1.0.0/go.mod h1:eH6gbSOAUv07dQuZVnBmoDP8mgsM1rtixis4Tib9if0=
github.com/akavel/rsrc v0.8.0/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c=
github.com/alecthomas/assert v0.0.0-20170929043011-405dbfeb8e38 h1:smF2tmSOzy2Mm+0dGI2AIUHY+w0BUc+4tn40djz7+6U=
github.com/alecthomas/assert v0.0.0-20170929043011-405dbfeb8e38/go.mod h1:r7bzyVFMNntcxPZXK3/+KdruV1H5KSlyVY0gc+NgInI=
github.com/alecthomas/chroma v0.6.8 h1:TW4JJaIdbAbMyUtGEd6BukFlOKYvVQz3vVhLBEUNwMU=
github.com/alecthomas/chroma v0.6.8/go.mod h1:o9ohftueRi7H5be3+Q2cQCNa/YnLBFUNx40ZJfGVFKA=
github.com/alecthomas/colour v0.0.0-20160524082231-60882d9e2721 h1:JHZL0hZKJ1VENNfmXvHbgYlbUOvpzYzvy2aZU5gXVeo=
github.com/alecthomas/colour v0.0.0-20160524082231-60882d9e2721/go.mod h1:QO9JBoKquHd+jz9nshCh40fOfO+JzsoXy8qTHF68zU0=
github.com/alecthomas/kong v0.1.17-0.20190424132513-439c674f7ae0/go.mod h1:+inYUSluD+p4L8KdviBSgzcqEjUQOfC5fQDRFuc36lI=
github.com/alecthomas/kong v0.2.1-0.20190708041108-0548c6b1afae/go.mod h1:+inYUSluD+p4L8KdviBSgzcqEjUQOfC5fQDRFuc36lI=
github.com/alecthomas/kong-hcl v0.1.8-0.20190615233001-b21fea9723c8/go.mod h1:MRgZdU3vrFd05IQ89AxUZ0aYdF39BYoNFa324SodPCA=
github.com/alecthomas/repr v0.0.0-20180818092828-117648cd9897 h1:p9Sln00KOTlrYkxI1zYWl1QLnEqAqEARBEYa8FQnQcY=
github.com/alecthomas/repr v0.0.0-20180818092828-117648cd9897/go.mod h1:xTS7Pm1pD1mvyM075QCDSRqH6qRLXylzS24ZTpRiSzQ=
github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59 h1:WWB576BN5zNSZc/M9d/10pqEx5VHNhaQ/yOVAkmj5Yo=
github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59/go.mod h1:q/89r3U2H7sSsE2t6Kca0lfwTK8JdoNGS/yzM/4iH5I=
github.com/daaku/go.zipexe v1.0.0/go.mod h1:z8IiR6TsVLEYKwXAoE/I+8ys/sDkgTzSL0CLnGVd57E=
github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964 h1:y5HC9v93H5EPKqaS1UYVg1uYah5Xf51mBfIoWehClUQ=
github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964/go.mod h1:Xd9hchkHSWYkEqJwUGisez3G1QY8Ryz0sdWrLPMGjLk=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dlclark/regexp2 v1.1.6 h1:CqB4MjHw0MFCDj+PHHjiESmHX+N7t0tJzKvC6M97BRg=
github.com/dlclark/regexp2 v1.1.6/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
github.com/gorilla/csrf v1.6.0/go.mod h1:7tSf8kmjNYr7IWDCYhd3U8Ck34iQ/Yw5CJu7bAkHEGI=
github.com/gorilla/handlers v1.4.1/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ=
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-isatty v0.0.4 h1:bnP0vzxcAdeI1zdubAl5PjU6zsERjGZb7raWodagDYs=
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mitchellh/go-wordwrap v1.0.0 h1:6GlHJ/LTGMrIJbwgdqdl2eEH8o+Exx/0m8ir9Gns0u4=
github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/nkovacs/streamquote v0.0.0-20170412213628-49af9bddb229/go.mod h1:0aYXnNPJ8l7uZxf45rWW1a/uME32OF0rhiYGNQ2oF2E=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/tj/assert v0.0.0-20190920132354-ee03d75cd160 h1:NSWpaDaurcAJY7PkL8Xt0PhZE7qpvbZl5ljd8r6U0bI=
github.com/tj/assert v0.0.0-20190920132354-ee03d75cd160/go.mod h1:mZ9/Rh9oLWpLLDRpvE+3b7gP/C2YyLFYxNmcLnPTMe0=
github.com/tj/go-css v0.0.0-20191108133013-220a796d1705 h1:+UA89aFRjPMqdccHd9A0HLNCRDXIoElaDoW2C1V3TzA=
github.com/tj/go-css v0.0.0-20191108133013-220a796d1705/go.mod h1:e+JPLQ9wyQCgRnPenX2bo7MJoLphBHz5c1WUqaANSeA=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
golang.org/x/sys v0.0.0-20181128092732-4ed8d59d0b35 h1:YAFjXN64LMvktoUZH9zgY4lGc/msGN7HQfoSuKCgaDU=
golang.org/x/sys v0.0.0-20181128092732-4ed8d59d0b35/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=


================================================
FILE: highlight.go
================================================
package termd

import (
	"strings"

	"github.com/alecthomas/chroma"
	"github.com/alecthomas/chroma/lexers"
)

// SyntaxHighlighter is the interface used to highlight blocks of code.
type SyntaxHighlighter interface {
	Token(chroma.Token) string
}

// highlight returns highlighted code, or the input text on error.
func highlight(source, lang string, highlight SyntaxHighlighter) string {
	l := lexers.Get(lang)
	if l == nil {
		return source
	}

	l = chroma.Coalesce(l)

	it, err := l.Tokenise(nil, source)
	if err != nil {
		return source
	}

	var w strings.Builder
	for _, t := range it.Tokens() {
		w.WriteString(highlight.Token(t))
	}
	return w.String()
}


================================================
FILE: termd.go
================================================
// Package termd provides terminal markdown rendering,
// with code block syntax highlighting support.
package termd

import (
	"fmt"
	"strings"

	"github.com/kr/text"
	"github.com/mitchellh/go-wordwrap"
	"github.com/russross/blackfriday/v2"
)

// Compiler is the markdown to text compiler. The zero value can be used.
type Compiler struct {
	// Columns is the number of columns to wrap text, defaulting to 90.
	Columns int

	// Markdown is an optional instance of a blackfriday markdown parser,
	// defaulting to one with CommonExtensions enabled.
	Markdown *blackfriday.Markdown

	// SyntaxHighlighter is an optional syntax highlighter for code blocks,
	// using the low-level SyntaxHighlighter interface, or SyntaxTheme map.
	SyntaxHighlighter

	inBlockQuote bool
	inList       bool
}

// Compile returns a terminal-styled plain text representation of a markdown string.
func (c *Compiler) Compile(s string) string {
	if c.Markdown == nil {
		c.Markdown = blackfriday.New(blackfriday.WithExtensions(blackfriday.CommonExtensions))
	}

	if c.Columns == 0 {
		c.Columns = 90
	}

	if c.SyntaxHighlighter == nil {
		c.SyntaxHighlighter = SyntaxTheme{}
	}

	n := c.Markdown.Parse([]byte(s))
	return c.visit(n)
}

// visit returns a compiled node string.
func (c *Compiler) visit(n *blackfriday.Node) (s string) {
	switch n.Type {
	case blackfriday.Document:
		s = c.visit(n.FirstChild)
	case blackfriday.BlockQuote:
		prev := c.inBlockQuote
		c.inBlockQuote = true
		s = c.visit(n.FirstChild)
		s = fmt.Sprintf("\033[38;5;102m%s\033[m", s)
		c.inBlockQuote = prev
	case blackfriday.List:
		prev := c.inList
		c.inList = true
		s = fmt.Sprintf("%s\n", c.visit(n.FirstChild))
		c.inList = prev
	case blackfriday.Item:
		s = fmt.Sprintf("  - %s", c.visit(n.FirstChild))
	case blackfriday.Paragraph:
		s = c.visit(n.FirstChild)
		if c.inList {
			s += "\n"
		} else {
			s = wordwrap.WrapString(s, uint(c.Columns))
			s = text.Indent(s, "  ")
			s += "\n\n"
		}
	case blackfriday.Heading:
		h := strings.Repeat("#", n.HeadingData.Level)
		t := c.visit(n.FirstChild)
		s = fmt.Sprintf("\033[1m%s %s\033[m\n\n", h, t)
	case blackfriday.HorizontalRule:
		s = fmt.Sprintf("  %s\n\n", strings.Repeat("─", c.Columns))
	case blackfriday.Emph:
		s = c.visit(n.FirstChild)
		if !c.inBlockQuote {
			s = fmt.Sprintf("\033[3m%s\033[m", s)
		}
	case blackfriday.Strong:
		s = c.visit(n.FirstChild)
		if !c.inBlockQuote {
			s = fmt.Sprintf("\033[1m%s\033[m", s)
		}
	case blackfriday.Link:
		s = c.visit(n.FirstChild)
		d := string(n.LinkData.Destination)
		if s != d {
			s = fmt.Sprintf("%s (%s)", s, d)
		}
	case blackfriday.Image:
		s = string(n.LinkData.Destination)
	case blackfriday.Text:
		s = string(n.Literal)
	case blackfriday.CodeBlock:
		lang := string(n.CodeBlockData.Info)
		s = string(n.Literal)
		s = highlight(s, lang, c.SyntaxHighlighter)
		s = fmt.Sprintf("%s\n", text.Indent(s, "    "))
	case blackfriday.Code:
		s = fmt.Sprintf("\033[38;5;102m`%s`\033[m", string(n.Literal))
	case blackfriday.HTMLSpan:
		// ignore
	default:
		s = fmt.Sprintf("<unhandled: %v>", n)
	}

	if n.Next != nil {
		s += c.visit(n.Next)
	}

	return
}


================================================
FILE: termd_test.go
================================================
package termd_test

import (
	"fmt"
	"io/ioutil"

	"github.com/tj/go-termd"
)

func Example() {
	var c termd.Compiler

	c.SyntaxHighlighter = termd.SyntaxTheme{
		"keyword": termd.Style{},
		"comment": termd.Style{
			Color: "#323232",
		},
		"literal": termd.Style{
			Color: "#555555",
		},
		"name": termd.Style{
			Color: "#777777",
		},
		"name.function": termd.Style{
			Color: "#444444",
		},
		"literal.string": termd.Style{
			Color: "#333333",
		},
	}

	b, _ := ioutil.ReadFile("testdata/example.md")
	fmt.Printf("%s\n", c.Compile(string(b)))
	// Output:
}


================================================
FILE: testdata/example.md
================================================
# Heading

Lorem ipsum _dolor_ sit amet, consectetur **adipiscing** elit. Curabitur `convallis` aliquet diam ut pharetra. In et sapien dui. Pellentesque nec magna non diam volutpat commodo. Nam non lorem vitae justo facilisis varius eu at lorem.

## Sub Heading

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur convallis aliquet diam ut pharetra. In et sapien dui. Pellentesque nec magna non diam volutpat commodo. Nam non lorem vitae justo facilisis varius eu at lorem. Maecenas auctor, velit consectetur commodo pellentesque, nunc augue tristique justo, ac ullamcorper mi nisi a arcu. Cras lobortis lacus sed erat pellentesque malesuada. 

Integer iaculis commodo libero quis scelerisque. Integer tortor tortor, aliquet eu quam sed, viverra pellentesque augue. Sed suscipit nulla magna, at ultrices odio fermentum a. Praesent sodales nulla massa, eu imperdiet magna.

Odio fermentum a. Praesent sodales nulla massa, eu imperdiet magna. Integer iaculis commodo libero quis scelerisque. Integer tortor tortor, aliquet eu quam sed, viverra pellentesque augue. Sed suscipit nulla magna, at ultrices odio fermentum a. Praesent sodales nulla massa, eu imperdiet magna.

--- 

Integer iaculis commodo libero quis scelerisque. Integer tortor tortor, aliquet eu quam sed, viverra pellentesque augue. Sed suscipit nulla magna, at ultrices odio fermentum a. Praesent sodales nulla massa, eu imperdiet magna.

## Code Example

Here's an example code block:

```js
const foo = /something/

/**
 * isJSON returns true if the string looks like JSON.
 */

function isJSON(s = '') {
  s = s.trim()
  return s[0] == '{' && s[s.length - 1] == '}'
}

console.log('Testing some stuff')
```


================================================
FILE: theme.go
================================================
package termd

import (
	"fmt"

	"github.com/alecthomas/chroma"
	"github.com/aybabtme/rgbterm"
	"github.com/tj/go-css/csshex"
)

// Style is the configuration used to style a particular token.
type Style struct {
	Color      string `json:"color"`
	Background string `json:"background"`
	Bold       bool   `json:"bold"`
	Faint      bool   `json:"faint"`
	Italic     bool   `json:"italic"`
	Underline  bool   `json:"underline"`
}

// apply returns a string with the style applied.
func (s Style) apply(v string) string {
	if s.Bold {
		v = escape(1, v)
	}

	if s.Faint {
		v = escape(2, v)
	}

	if s.Italic {
		v = escape(3, v)
	}

	if s.Underline {
		v = escape(4, v)
	}

	if s.Color != "" {
		v = foreground(v, s.Color)
	}

	if s.Background != "" {
		v = background(v, s.Background)
	}

	return v
}

// SyntaxTheme is a map of token names to style configurations.
type SyntaxTheme map[string]Style

// Token implementation.
func (c SyntaxTheme) Token(t chroma.Token) string {
	// specific
	if s, ok := c.mapped(t.Type, t.Value); ok {
		return s
	}

	// sub-category
	if s, ok := c.mapped(t.Type.SubCategory(), t.Value); ok {
		return s
	}

	// category
	if s, ok := c.mapped(t.Type.Category(), t.Value); ok {
		return s
	}

	return t.Value
}

// mapped returns a string mapped to its style, or returns the input string as-is.
func (c SyntaxTheme) mapped(t chroma.TokenType, v string) (string, bool) {
	// check if the key is valid
	k, ok := themeKeys[t]
	if !ok {
		return v, false
	}

	// check if the style is mapped
	s, ok := c[k]
	if !ok {
		return v, false
	}

	return s.apply(v), true
}

// escape returns an ansi escape sequence with the given code.
func escape(code int, s string) string {
	return fmt.Sprintf("\033[%dm%s\033[m", code, s)
}

// foreground color.
func foreground(s, color string) string {
	r, g, b, ok := csshex.Parse(color)
	if !ok {
		return s
	}
	return rgbterm.FgString(s, r, g, b)
}

// background color.
func background(s, color string) string {
	r, g, b, ok := csshex.Parse(color)
	if !ok {
		return s
	}
	return rgbterm.BgString(s, r, g, b)
}

// themeKeys is the map of token types to names.
var themeKeys = map[chroma.TokenType]string{
	chroma.Keyword:                  "keyword",
	chroma.KeywordConstant:          "keyword.constant",
	chroma.KeywordDeclaration:       "keyword.declaration",
	chroma.KeywordNamespace:         "keyword.namespace",
	chroma.KeywordPseudo:            "keyword.pseudo",
	chroma.KeywordReserved:          "keyword.reserved",
	chroma.KeywordType:              "keyword.type",
	chroma.Name:                     "name",
	chroma.NameAttribute:            "name.attribute",
	chroma.NameBuiltin:              "name.builtin",
	chroma.NameBuiltinPseudo:        "name.builtin.pseudo",
	chroma.NameClass:                "name.class",
	chroma.NameConstant:             "name.constant",
	chroma.NameDecorator:            "name.decorator",
	chroma.NameEntity:               "name.entity",
	chroma.NameException:            "name.exception",
	chroma.NameFunction:             "name.function",
	chroma.NameFunctionMagic:        "name.function.magic",
	chroma.NameKeyword:              "name.keyword",
	chroma.NameLabel:                "name.label",
	chroma.NameNamespace:            "name.namespace",
	chroma.NameOperator:             "name.operator",
	chroma.NameOther:                "name.other",
	chroma.NamePseudo:               "name.pseudo",
	chroma.NameProperty:             "name.property",
	chroma.NameTag:                  "name.tag",
	chroma.NameVariable:             "name.variable",
	chroma.NameVariableAnonymous:    "name.variable.anonymous",
	chroma.NameVariableClass:        "name.variable.class",
	chroma.NameVariableGlobal:       "name.variable.global",
	chroma.NameVariableInstance:     "name.variable.instance",
	chroma.NameVariableMagic:        "name.variable.magic",
	chroma.Literal:                  "literal",
	chroma.LiteralDate:              "literal.date",
	chroma.LiteralOther:             "literal.other",
	chroma.LiteralString:            "literal.string",
	chroma.LiteralStringAffix:       "literal.string.affix",
	chroma.LiteralStringAtom:        "literal.string.atom",
	chroma.LiteralStringBacktick:    "literal.string.backtick",
	chroma.LiteralStringBoolean:     "literal.string.boolean",
	chroma.LiteralStringChar:        "literal.string.char",
	chroma.LiteralStringDelimiter:   "literal.string.delimiter",
	chroma.LiteralStringDoc:         "literal.string.doc",
	chroma.LiteralStringDouble:      "literal.string.double",
	chroma.LiteralStringEscape:      "literal.string.escape",
	chroma.LiteralStringHeredoc:     "literal.string.heredoc",
	chroma.LiteralStringInterpol:    "literal.string.interpol",
	chroma.LiteralStringName:        "literal.string.name",
	chroma.LiteralStringOther:       "literal.string.other",
	chroma.LiteralStringRegex:       "literal.string.regex",
	chroma.LiteralStringSingle:      "literal.string.single",
	chroma.LiteralStringSymbol:      "literal.string.symbol",
	chroma.LiteralNumber:            "literal.number",
	chroma.LiteralNumberBin:         "literal.number.bin",
	chroma.LiteralNumberFloat:       "literal.number.float",
	chroma.LiteralNumberHex:         "literal.number.hex",
	chroma.LiteralNumberInteger:     "literal.number.integer",
	chroma.LiteralNumberIntegerLong: "literal.number.integer.long",
	chroma.LiteralNumberOct:         "literal.number.oct",
	chroma.Operator:                 "operator",
	chroma.OperatorWord:             "operator.word",
	chroma.Punctuation:              "punctuation",
	chroma.Comment:                  "comment",
	chroma.CommentHashbang:          "comment.hashbang",
	chroma.CommentMultiline:         "comment.multiline",
	chroma.CommentSingle:            "comment.single",
	chroma.CommentSpecial:           "comment.special",
	chroma.CommentPreproc:           "comment.preproc",
	chroma.CommentPreprocFile:       "comment.preproc.file",
	chroma.Generic:                  "generic",
	chroma.GenericDeleted:           "generic.deleted",
	chroma.GenericEmph:              "generic.emph",
	chroma.GenericError:             "generic.error",
	chroma.GenericHeading:           "generic.heading",
	chroma.GenericInserted:          "generic.inserted",
	chroma.GenericOutput:            "generic.output",
	chroma.GenericPrompt:            "generic.prompt",
	chroma.GenericStrong:            "generic.strong",
	chroma.GenericSubheading:        "generic.subheading",
	chroma.GenericTraceback:         "generic.traceback",
	chroma.GenericUnderline:         "generic.underline",
	chroma.Text:                     "text",
	chroma.TextWhitespace:           "text.whitespace",
	chroma.TextSymbol:               "text.symbol",
	chroma.TextPunctuation:          "text.punctuation",
}
Download .txt
gitextract_09an3s_0/

├── .github/
│   ├── FUNDING.yml
│   ├── ISSUE_TEMPLATE.yml
│   └── PULL_REQUEST_TEMPLATE.md
├── .gitignore
├── LICENSE
├── Readme.md
├── go.mod
├── go.sum
├── highlight.go
├── termd.go
├── termd_test.go
├── testdata/
│   └── example.md
└── theme.go
Download .txt
SYMBOL INDEX (14 symbols across 4 files)

FILE: highlight.go
  type SyntaxHighlighter (line 11) | type SyntaxHighlighter interface
  function highlight (line 16) | func highlight(source, lang string, highlight SyntaxHighlighter) string {

FILE: termd.go
  type Compiler (line 15) | type Compiler struct
    method Compile (line 32) | func (c *Compiler) Compile(s string) string {
    method visit (line 50) | func (c *Compiler) visit(n *blackfriday.Node) (s string) {

FILE: termd_test.go
  function Example (line 10) | func Example() {

FILE: theme.go
  type Style (line 12) | type Style struct
    method apply (line 22) | func (s Style) apply(v string) string {
  type SyntaxTheme (line 51) | type SyntaxTheme
    method Token (line 54) | func (c SyntaxTheme) Token(t chroma.Token) string {
    method mapped (line 74) | func (c SyntaxTheme) mapped(t chroma.TokenType, v string) (string, boo...
  function escape (line 91) | func escape(code int, s string) string {
  function foreground (line 96) | func foreground(s, color string) string {
  function background (line 105) | func background(s, color string) string {
Condensed preview — 13 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (24K chars).
[
  {
    "path": ".github/FUNDING.yml",
    "chars": 10,
    "preview": "github: tj"
  },
  {
    "path": ".github/ISSUE_TEMPLATE.yml",
    "chars": 257,
    "preview": "## Prerequisites\n\n* [ ] I searched to see if the issue already exists.\n\n## Description\n\nDescribe the bug or feature.\n\n##"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "chars": 128,
    "preview": "Please open an issue and discuss changes before spending time on them, unless the change is trivial or an issue already "
  },
  {
    "path": ".gitignore",
    "chars": 7,
    "preview": ".envrc\n"
  },
  {
    "path": "LICENSE",
    "chars": 1097,
    "preview": "The MIT License\n\nCopyright (c) 2019 TJ Holowaychuk tj@tjholowaychuk.com\n\nPermission is hereby granted, free of charge, t"
  },
  {
    "path": "Readme.md",
    "chars": 926,
    "preview": "# Termd\n\nPackage termd provides terminal markdown rendering, with code block syntax highlighting support.\n\n## Features\n\n"
  },
  {
    "path": "go.mod",
    "chars": 383,
    "preview": "module github.com/tj/go-termd\n\ngo 1.13\n\nrequire (\n\tgithub.com/alecthomas/chroma v0.6.8\n\tgithub.com/aybabtme/rgbterm v0.0"
  },
  {
    "path": "go.sum",
    "chars": 6528,
    "preview": "github.com/GeertJohan/go.incremental v1.0.0/go.mod h1:6fAjUhbVuX1KcMD3c8TEgVUqmo4seqhv0i0kdATSkM0=\ngithub.com/GeertJohan"
  },
  {
    "path": "highlight.go",
    "chars": 661,
    "preview": "package termd\n\nimport (\n\t\"strings\"\n\n\t\"github.com/alecthomas/chroma\"\n\t\"github.com/alecthomas/chroma/lexers\"\n)\n\n// SyntaxH"
  },
  {
    "path": "termd.go",
    "chars": 3129,
    "preview": "// Package termd provides terminal markdown rendering,\n// with code block syntax highlighting support.\npackage termd\n\nim"
  },
  {
    "path": "termd_test.go",
    "chars": 567,
    "preview": "package termd_test\n\nimport (\n\t\"fmt\"\n\t\"io/ioutil\"\n\n\t\"github.com/tj/go-termd\"\n)\n\nfunc Example() {\n\tvar c termd.Compiler\n\n\t"
  },
  {
    "path": "testdata/example.md",
    "chars": 1690,
    "preview": "# Heading\n\nLorem ipsum _dolor_ sit amet, consectetur **adipiscing** elit. Curabitur `convallis` aliquet diam ut pharetra"
  },
  {
    "path": "theme.go",
    "chars": 6723,
    "preview": "package termd\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/alecthomas/chroma\"\n\t\"github.com/aybabtme/rgbterm\"\n\t\"github.com/tj/go-css/cs"
  }
]

About this extraction

This page contains the full source code of the tj/go-termd GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 13 files (21.6 KB), approximately 7.8k tokens, and a symbol index with 14 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!