Giter Site home page Giter Site logo

depado / bfchroma Goto Github PK

View Code? Open in Web Editor NEW
63.0 4.0 8.0 58 KB

Integrating Chroma syntax highlighter as a Blackfriday renderer

License: MIT License

Go 100.00%
chroma blackfriday blackfriday-renderer syntax-highlighting markdown markdown-to-html

bfchroma's Introduction

bfchroma

forthebadgeforthebadge

Go Report Card Build Status codecov License Godoc Sourcegraph Say Thanks!

Integrating Chroma syntax highlighter as a Blackfriday renderer.

Install and prerequisites

This project requires and uses the v2 version of Blackfriday.

$ go get github.com/Depado/bfchroma/v2

Features

This renderer integrates chroma to highlight code with triple backtick notation. It will try to use the given language when available otherwise it will try to detect the language. If none of these two method works it will fallback to sane defaults.

Usage

bfchroma uses the functional options approach so you can customize the behavior of the renderer. It uses sane defaults when no option is passed so you can use the renderer simply by doing so :

html := bf.Run([]byte(md), bf.WithRenderer(bfchroma.NewRenderer()))

Options

  • Style(s string) Define the style used by chroma for the rendering. The full list can be found here
  • ChromaStyle(*chroma.Style) This option can be used to passe directly a *chroma.Style instead of the string representing the style as with the Style(string) option.
  • WithoutAutodetect() By default when no language information is written in the code block, this renderer will try to auto-detect the used language. This option disables this behavior and will fallback to a sane default when no language information is available.
  • EmbedCSS() This option will embed CSS needed for chroma's html.WithClasses() at the beginning of blackfriday document. CSS can also be extracted separately by calling Renderer's.ChromaCSS(w) method, which will return styleshet for currently set style
  • Extend(bf.Renderer) This option allows to define the base blackfriday that will be extended.
  • ChromaOptions(...html.Option) This option allows you to pass Chroma's html options in the renderer. Such options can be found here.

Option examples

Disabling language auto-detection and displaying line numbers

r := bfchroma.NewRenderer(
	bfchroma.WithoutAutodetect(),
	bfchroma.ChromaOptions(html.WithLineNumbers()),
)

Extend a blackfriday renderer

b := bf.NewHTMLRenderer(bf.HTMLRendererParameters{
	Flags: bf.CommonHTMLFlags,
})

r := bfchroma.NewRenderer(bfchroma.Extend(b))

Use a different style

r := bfchroma.NewRenderer(bfchroma.Style("dracula"))
// Or
r = bfchroma.NewRenderer(bfchroma.ChromaStyle(styles.Dracula))

Examples

package main

import (
	"fmt"

	"github.com/Depado/bfchroma/v2"

	bf "github.com/russross/blackfriday/v2"
)

var md = "This is some sample code.\n\n```go\n" +
	`func main() {
	fmt.Println("Hi")
}
` + "```"

func main() {
	html := bf.Run([]byte(md), bf.WithRenderer(bfchroma.NewRenderer()))
	fmt.Println(string(html))
}

Will output :

<p>This is some sample code.</p>
<pre style="color:#f8f8f2;background-color:#272822"><span style="color:#66d9ef">func</span> <span style="color:#a6e22e">main</span>() {
<span style="color:#a6e22e">fmt</span>.<span style="color:#a6e22e">Println</span>(<span style="color:#e6db74">&#34;Hi&#34;</span>)
}
</pre>

Real-life example

In smallblog I'm using bfchroma to render my articles. It's using a combination of both bfchroma's options and blackfriday extensions and flags.

package main

import (
	"github.com/Depado/bfchroma/v2"

	"github.com/alecthomas/chroma/v2/formatters/html"
	bf "github.com/russross/blackfriday/v2"
)

// Defines the extensions that are used
var exts = bf.NoIntraEmphasis | bf.Tables | bf.FencedCode | bf.Autolink |
	bf.Strikethrough | bf.SpaceHeadings | bf.BackslashLineBreak |
	bf.DefinitionLists | bf.Footnotes

// Defines the HTML rendering flags that are used
var flags = bf.UseXHTML | bf.Smartypants | bf.SmartypantsFractions |
	bf.SmartypantsDashes | bf.SmartypantsLatexDashes | bf.TOC

// render will take a []byte input and will render it using a new renderer each
// time because reusing the same can mess with TOC and header IDs
func render(input []byte) []byte {
	return bf.Run(
		input,
		bf.WithRenderer(
			bfchroma.NewRenderer(
				bfchroma.WithoutAutodetect(),
				bfchroma.ChromaOptions(
					html.WithLineNumbers(),
				),
				bfchroma.Extend(
					bf.NewHTMLRenderer(bf.HTMLRendererParameters{
						Flags: flags,
					}),
				),
			),
		),
		bf.WithExtensions(exts),
	)
}

Classes

If you have loads of code in your markdown, you might want to consider using html.WithClasses() in your bfchroma.ChromaOptions(). The CSS of the style you chose can then be accessed like this :

r := bfchroma.NewRenderer(
	bfchroma.WithoutAutodetect(),
	bfchroma.Extend(
		bf.NewHTMLRenderer(bf.HTMLRendererParameters{Flags: flags}),
	),
	bfchroma.Style("monokai"),
	bfchroma.ChromaOptions(html.WithClasses()),
)

var css template.CSS

b := new(bytes.Buffer)
if err := r.ChromaCSS(b); err != nil {
	logrus.WithError(err).Warning("Couldn't write CSS")
}
css = template.CSS(b.String())

bf.Run(input, bf.WithRenderer(r), bf.WithExtensions(exts))

This way, you can pass your css var to any template and render it along the rendered markdown.

bfchroma's People

Contributors

depado avatar renatoathaydes avatar renovate[bot] avatar xani avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

bfchroma's Issues

Underterministic output

Hi, I am having trouble writing tests when using this library.

The following test always fails:

import (
	"bufio"
	"fmt"
	"github.com/Depado/bfchroma"
	"github.com/renatoathaydes/magnanimous/mg"
	"gopkg.in/russross/blackfriday.v2"
	"strings"
	"testing"
)

func TestBfChroma(t *testing.T) {
	var chromaRenderer = blackfriday.WithRenderer(bfchroma.NewRenderer(bfchroma.WithoutAutodetect()))

	examples := []string{
		"# hello\n## world",
		"# hello\n## world",

	}

	expectedResult := "\n<h1>hello</h1>\n\n<h2>world</h2>\n"
	for i, v := range examples {
		r := blackfriday.Run([]byte(v), chromaRenderer)
		if string(r) != expectedResult {
			t.Errorf("[%d] '%s' != %s", i, string(r), expectedResult)
		} else {
			fmt.Printf("[%d] All good\n", i)
		}
	}
}

The first iteration results in text that does NOT contain a trailing new-line, but the second (and further) iterations do.

This is undeterministic in the sense that the same input does not always result in the same output. This causes havoc on testing as depending on the order tests run, I get different results.

Finally, I don't think the trailing new-line was supposed to be there anyway. Using just blackfriday, it consistently gives the same output, without the trailing new-line.

gopkg.in -> go/dep, however vendor dir hasn't been checked in

Went to check this library out today, however it doesn't want to go get, due to the changes in 7130586. The switch away from gopkg.in isn't necessarily the issue, rather it seems you have switched to using go/dep in a library, without checking in vendor/ which is needed for go get functionality to work (otherwise, Go has no idea that you want to use that specific version), IIRC.

tl;dr, when running go get on this lib, it's fetching blackfriday master branch, not v2:

liam:~$ go get -v -u github.com/Depado/bfchroma
github.com/Depado/bfchroma (download)
github.com/alecthomas/chroma (download)
github.com/dlclark/regexp2 (download)
github.com/danwakefield/fnmatch (download)
github.com/russross/blackfriday (download)
github.com/russross/blackfriday
github.com/Depado/bfchroma
# github.com/Depado/bfchroma
../../Depado/bfchroma/renderer.go:61:9: undefined: blackfriday.NewHTMLRenderer
../../Depado/bfchroma/renderer.go:61:28: undefined: blackfriday.HTMLRendererParameters
../../Depado/bfchroma/renderer.go:75:68: undefined: blackfriday.CodeBlockData
../../Depado/bfchroma/renderer.go:107:50: undefined: blackfriday.Node
../../Depado/bfchroma/renderer.go:107:74: undefined: blackfriday.WalkStatus
../../Depado/bfchroma/renderer.go:109:7: undefined: blackfriday.CodeBlock
../../Depado/bfchroma/renderer.go:120:51: undefined: blackfriday.Node
../../Depado/bfchroma/renderer.go:121:8: r.Base.RenderHeader undefined (type blackfriday.Renderer has no field or method RenderHeader)
../../Depado/bfchroma/renderer.go:125:51: undefined: blackfriday.Node
../../Depado/bfchroma/renderer.go:126:8: r.Base.RenderFooter undefined (type blackfriday.Renderer has no field or method RenderFooter)
../../Depado/bfchroma/renderer.go:126:8: too many errors

Cannot use bfchroma with Go 1.11 modules

I am trying to use this module with a Go 1.11 module.

I have this in my go.mod file:

require (
	github.com/Depado/bfchroma v1.1.1
	github.com/russross/blackfriday v2.0.0+incompatible
)

go build automatically adds the second require.

This is the code I have:

func main() {
	s := blackfriday.Run(
		[]byte("# Hello"),
		blackfriday.WithRenderer(bfchroma.NewRenderer()))
	fmt.Println(string(s))
}

This gives an error:

 cannot use bfchroma.NewRenderer() (type *bfchroma.Renderer) as type "github.com/russross/blackfriday".Renderer in argument to "github.com/russross/blackfriday".WithRenderer:
        *bfchroma.Renderer does not implement "github.com/russross/blackfriday".Renderer (wrong type for RenderFooter method)
                have RenderFooter(io.Writer, *"gopkg.in/russross/blackfriday.v2".Node)
                want RenderFooter(io.Writer, *"github.com/russross/blackfriday".Node)

Any ideas?

Not detecting yaml in v1.1.1?

The following section seems to not be highlighted as YAML, and I'm not sure why not (ignore the backslashes; I had to "escape" the code fences or it breaks github rendering--GH doesn't support nested code fences afaict):

\`\`\`yaml
pipelines:
  default:
    - step:
        services:
          - docker
        caches:
          - docker
        script:
          - docker build -t weberc2/neon:latest .
          - docker login --username $DOCKER_USERNAME --password $DOCKER_PASSWORD
          - docker tag weberc2/neon weberc2/neon:$BITBUCKET_COMMIT
          - docker push weberc2/neon:latest
          - docker push weberc2/neon:$BITBUCKET_COMMIT
\`\`\`

I assume it's user error, but I'm not really sure how to set about debugging.

error using go mod

I'm getting an error while using go mod with an import declaration for bfchroma
From what I can tell go.mod file contains the line

require "github.com/russross/blackfriday v2.0.0+incompatible

this is obvious not version 2.0.1. I don't understand what's wrong exactly. If this is a blackfriday issue, I will gladly take it up with them. Figured I'd start here since this is the package that is causing the error.

2019/06/17 12:21:53 ERROR โ–ถ 0066 Failed to build the application: go: downloading gopkg.in/russross/blackfriday.v2 v2.0.1 go: gopkg.in/russross/[email protected]: go.mod has non-....v2 module path "github.com/russross/blackfriday/v2" at revision v2.0.1

Couple comments from Blackfriday

Hi Depado. Thanks for building this package!

A couple comments from me:

  1. Can you provide a constructor that picks some sane defaults for the fallback renderer and the color scheme? It would be super neat if using Blackfriday+bfchrome were as easy as this:

    html := bf.Run([]byte(md), bf.WithRenderer(bfchroma.NewRenderer()))

    There are several options for providing both easy defaults and customization: you can have several
    constructors, an Options struct or the functional options approach. Pick any of them
    and make bfchroma extensible.

  2. In addition to that, please export the renderWithChroma function for people who might want to use your basic functionality, but incorporate it into a larger renderer of their own.

Dependency Dashboard

This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.

Open

These updates have all been created already. Click a checkbox below to force a retry/rebase of any.

Detected dependencies

droneci
.drone.yml
  • golang 1.22
  • golang 1.22
gomod
go.mod
  • go 1.20
  • github.com/alecthomas/chroma/v2 v2.12.0
  • github.com/russross/blackfriday/v2 v2.1.0
  • github.com/stretchr/testify v1.8.4

  • Check this box to trigger a request for Renovate to run again on this repository

Upgrade to chroma v2

The current version of Chroma is very out-of-date.

Any chance you can upgrade to Chroma v2?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.