Skip to content

Commit 190f588

Browse files
authored
Merge pull request #21 from iafan/master
Add an ability to produce an `<ol>...</ol>`-wrapped list to display line numbers
2 parents c95ac47 + 99fca80 commit 190f588

18 files changed

+204
-31
lines changed

.travis.yml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
language: go
2+
go_import_path: github.com/sourcegraph/syntaxhighlight
23
go:
3-
- 1.4
4+
- 1.6.x
5+
- 1.7.x
6+
- 1.8.x
7+
- tip
48
install:
5-
- go get golang.org/x/tools/cmd/vet
69
- go get -t -v ./...
710
script:
811
- diff -u <(echo -n) <(gofmt -d ./)

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ Remember you should set the environment variables correctly (GOPATH and PATH)
2020

2121
## Example usage
2222

23-
The function [`AsHTML(src []byte) ([]byte, error)`](https://sourcegraph.com/sourcegraph.com/sourcegraph/syntaxhighlight@master/.GoPackage/sourcegraph.com/sourcegraph/syntaxhighlight/.def/AsHTML) returns an HTML-highlighted version of `src`. The input source code can be in any language; the lexer is language independent.
23+
The function [`AsHTML(src []byte, options ...Option) ([]byte, error)`](https://sourcegraph.com/sourcegraph.com/sourcegraph/syntaxhighlight@master/.GoPackage/sourcegraph.com/sourcegraph/syntaxhighlight/.def/AsHTML) returns an HTML-highlighted version of `src`. The input source code can be in any language; the lexer is language independent. An `OrderedList()` option can be passed to produce an `<ol>...</ol>`-wrapped list to display line numbers.
2424

2525
```go
2626
package syntaxhighlight_test

highlight.go

Lines changed: 55 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package syntaxhighlight
66
import (
77
"bytes"
88
"io"
9+
"strings"
910
"text/scanner"
1011
"text/template"
1112
"unicode"
@@ -18,6 +19,7 @@ import (
1819
// A syntax highlighting scheme (style) maps text style properties to each token kind.
1920
type Kind uint8
2021

22+
// A set of supported highlighting kinds
2123
const (
2224
Whitespace Kind = iota
2325
String
@@ -36,6 +38,8 @@ const (
3638

3739
//go:generate gostringer -type=Kind
3840

41+
// Printer implements an interface to render highlighted output
42+
// (see HTMLPrinter for the implementation of this interface)
3943
type Printer interface {
4044
Print(w io.Writer, kind Kind, tokText string) error
4145
}
@@ -56,8 +60,12 @@ type HTMLConfig struct {
5660
HTMLAttrValue string
5761
Decimal string
5862
Whitespace string
63+
64+
AsOrderedList bool
5965
}
6066

67+
// HTMLPrinter implements Printer interface and is used to produce
68+
// HTML-based highligher
6169
type HTMLPrinter HTMLConfig
6270

6371
// Class returns the set class for a given token Kind.
@@ -91,7 +99,22 @@ func (c HTMLConfig) Class(kind Kind) string {
9199
return ""
92100
}
93101

102+
// Print is the function that emits highlighted source code using
103+
// <span class="...">...</span> wrapper tags
94104
func (p HTMLPrinter) Print(w io.Writer, kind Kind, tokText string) error {
105+
if p.AsOrderedList {
106+
if i := strings.Index(tokText, "\n"); i > -1 {
107+
if err := p.Print(w, kind, tokText[:i]); err != nil {
108+
return err
109+
}
110+
w.Write([]byte("</li>\n<li>"))
111+
if err := p.Print(w, kind, tokText[i+1:]); err != nil {
112+
return err
113+
}
114+
return nil
115+
}
116+
}
117+
95118
class := ((HTMLConfig)(p)).Class(kind)
96119
if class != "" {
97120
_, err := w.Write([]byte(`<span class="`))
@@ -137,7 +160,22 @@ func (a HTMLAnnotator) Annotate(start int, kind Kind, tokText string) (*annotate
137160
return nil, nil
138161
}
139162

140-
// DefaultHTMLConfig's class names match those of google-code-prettify
163+
// Option is a type of the function that can modify
164+
// one or more of the options in the HTMLConfig structure.
165+
type Option func(options *HTMLConfig)
166+
167+
// OrderedList allows you to format the output as an ordered list
168+
// to have line numbers in the output.
169+
//
170+
// Example:
171+
// AsHTML(input, OrderedList())
172+
func OrderedList() Option {
173+
return func(o *HTMLConfig) {
174+
o.AsOrderedList = true
175+
}
176+
}
177+
178+
// DefaultHTMLConfig provides class names that match those of google-code-prettify
141179
// (https://code.google.com/p/google-code-prettify/).
142180
var DefaultHTMLConfig = HTMLConfig{
143181
String: "str",
@@ -195,9 +233,23 @@ func Annotate(src []byte, a Annotator) (annotate.Annotations, error) {
195233
return anns, nil
196234
}
197235

198-
func AsHTML(src []byte) ([]byte, error) {
236+
// AsHTML converts source code into an HTML-highlighted version;
237+
// It accepts optional configuration parameters to control rendering
238+
// (see OrderedList as one example)
239+
func AsHTML(src []byte, options ...Option) ([]byte, error) {
240+
opt := DefaultHTMLConfig
241+
for _, f := range options {
242+
f(&opt)
243+
}
244+
199245
var buf bytes.Buffer
200-
err := Print(NewScanner(src), &buf, HTMLPrinter(DefaultHTMLConfig))
246+
if opt.AsOrderedList {
247+
buf.Write([]byte("<ol>\n<li>"))
248+
}
249+
err := Print(NewScanner(src), &buf, HTMLPrinter(opt))
250+
if opt.AsOrderedList {
251+
buf.Write([]byte("</li>\n</ol>"))
252+
}
201253
if err != nil {
202254
return nil, err
203255
}

highlight_test.go

Lines changed: 33 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,36 @@ import (
1616
var saveExp = flag.Bool("exp", false, "overwrite all expected output files with actual output (returning a failure)")
1717
var match = flag.String("m", "", "only run tests whose name contains this string")
1818

19+
func testExpected(t *testing.T, fn, path, name, ext string, got []byte, err error) {
20+
if err != nil {
21+
t.Errorf("%s: %s: %s", fn, name, err)
22+
return
23+
}
24+
25+
expPath := path + ext
26+
if *saveExp {
27+
err = ioutil.WriteFile(expPath, got, 0700)
28+
if err != nil {
29+
t.Fatal(err)
30+
}
31+
return
32+
}
33+
34+
want, err := ioutil.ReadFile(expPath)
35+
if err != nil {
36+
t.Fatal(err)
37+
}
38+
39+
want = bytes.TrimSpace(want)
40+
got = bytes.TrimSpace(got)
41+
42+
if !bytes.Equal(want, got) {
43+
t.Errorf("%s: %s:\nwant ==========\n%q\ngot ===========\n%q", fn, name, want, got)
44+
return
45+
}
46+
return
47+
}
48+
1949
func TestAsHTML(t *testing.T) {
2050
dir := "testdata"
2151
tests, err := ioutil.ReadDir(dir)
@@ -43,32 +73,10 @@ func TestAsHTML(t *testing.T) {
4373
}
4474

4575
got, err := AsHTML(input)
46-
if err != nil {
47-
t.Errorf("%s: AsHTML: %s", name, err)
48-
continue
49-
}
50-
51-
expPath := path + ".html"
52-
if *saveExp {
53-
err = ioutil.WriteFile(expPath, got, 0700)
54-
if err != nil {
55-
t.Fatal(err)
56-
}
57-
continue
58-
}
76+
testExpected(t, "AsHTML", path, name, ".html", got, err)
5977

60-
want, err := ioutil.ReadFile(expPath)
61-
if err != nil {
62-
t.Fatal(err)
63-
}
64-
65-
want = bytes.TrimSpace(want)
66-
got = bytes.TrimSpace(got)
67-
68-
if !bytes.Equal(want, got) {
69-
t.Errorf("%s:\nwant ==========\n%q\ngot ===========\n%q", name, want, got)
70-
continue
71-
}
78+
got, err = AsHTML(input, OrderedList())
79+
testExpected(t, "AsOrderedListHTML", path, name, ".ol.html", got, err)
7280
}
7381

7482
if *saveExp {

testdata/escaped_string.py.ol.html

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<ol>
2+
<li><span class="str">&#34;this string\&#34; continues to here&#34;</span></li>
3+
<li></li>
4+
</ol>

testdata/html_in_string.py.ol.html

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<ol>
2+
<li><span class="str">&#34;&lt;h1&gt;hello!&lt;/h1&gt;&#34;</span></li>
3+
<li></li>
4+
</ol>

testdata/no_ending_newline.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
'test'

testdata/no_ending_newline.js.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<span class="str">&#39;test&#39;</span>
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<ol>
2+
<li><span class="str">&#39;test&#39;</span></li>
3+
</ol>

testdata/simple.c.ol.html

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<ol>
2+
<li><span class="pun">#</span><span class="pln">include</span> <span class="pun">&lt;</span><span class="pln">stdio</span><span class="pun">.</span><span class="pln">h</span><span class="pun">&gt;</span></li>
3+
<li> </li>
4+
<li><span class="kwd">int</span> <span class="pln">main</span><span class="pun">(</span><span class="kwd">void</span><span class="pun">)</span></li>
5+
<li><span class="pun">{</span></li>
6+
<li> <span class="pln">printf</span><span class="pun">(</span><span class="str">&#34;hello, world\n&#34;</span><span class="pun">)</span><span class="pun">;</span></li>
7+
<li><span class="pun">}</span></li>
8+
<li></li>
9+
</ol>

0 commit comments

Comments
 (0)