diff --git a/blorg/util.go b/blorg/util.go index e24ea9a..ef588db 100644 --- a/blorg/util.go +++ b/blorg/util.go @@ -63,7 +63,14 @@ func highlightCodeBlock(source, lang string, inline bool, params map[string]stri } l = chroma.Coalesce(l) it, _ := l.Tokenise(nil, source) - _ = html.New().Format(&w, styles.Get("github"), it) + options := []html.Option{} + if params[":hl_lines"] != "" { + ranges := org.ParseRanges(params[":hl_lines"]) + if ranges != nil { + options = append(options, html.HighlightLines(ranges)) + } + } + _ = html.New(options...).Format(&w, styles.Get("github"), it) if inline { return `
` + "\n" + w.String() + "\n" + `
` } diff --git a/main.go b/main.go index c400d56..62a22f3 100644 --- a/main.go +++ b/main.go @@ -127,7 +127,14 @@ func highlightCodeBlock(source, lang string, inline bool, params map[string]stri } l = chroma.Coalesce(l) it, _ := l.Tokenise(nil, source) - _ = html.New().Format(&w, styles.Get("friendly"), it) + options := []html.Option{} + if params[":hl_lines"] != "" { + ranges := org.ParseRanges(params[":hl_lines"]) + if ranges != nil { + options = append(options, html.HighlightLines(ranges)) + } + } + _ = html.New(options...).Format(&w, styles.Get("friendly"), it) if inline { return `
` + "\n" + w.String() + "\n" + `
` } diff --git a/org/testdata/hl-lines.html b/org/testdata/hl-lines.html new file mode 100644 index 0000000..c458903 --- /dev/null +++ b/org/testdata/hl-lines.html @@ -0,0 +1,12 @@ +

Lines in a source block can be highlighted with :hl_lines.

+
+
+
+(+ 1 2)
+(+ 1 2)
+(+ 1 2)
+(+ 1 2)
+(+ 1 2)
+
+
+
diff --git a/org/testdata/hl-lines.org b/org/testdata/hl-lines.org new file mode 100644 index 0000000..17851b8 --- /dev/null +++ b/org/testdata/hl-lines.org @@ -0,0 +1,9 @@ +Lines in a source block can be highlighted with =:hl_lines=. + +#+begin_src emacs-lisp :hl_lines 3-4 +(+ 1 2) +(+ 1 2) +(+ 1 2) +(+ 1 2) +(+ 1 2) +#+end_src diff --git a/org/testdata/hl-lines.pretty_org b/org/testdata/hl-lines.pretty_org new file mode 100644 index 0000000..5d7ba70 --- /dev/null +++ b/org/testdata/hl-lines.pretty_org @@ -0,0 +1,9 @@ +Lines in a source block can be highlighted with =:hl_lines=. + +#+BEGIN_SRC emacs-lisp :hl_lines 3-4 +(+ 1 2) +(+ 1 2) +(+ 1 2) +(+ 1 2) +(+ 1 2) +#+END_SRC diff --git a/org/util.go b/org/util.go index c25bf27..b83b6f4 100644 --- a/org/util.go +++ b/org/util.go @@ -1,5 +1,10 @@ package org +import ( + "strconv" + "strings" +) + func isSecondBlankLine(d *Document, i int) bool { if i-1 <= 0 { return false @@ -17,3 +22,49 @@ func isImageOrVideoLink(n Node) bool { } return false } + +// Parse ranges like this: +// "3-5" -> [[3, 5]] +// "3 8-10" -> [[3, 3], [8, 10]] +// "3 5 6" -> [[3, 3], [5, 5], [6, 6]] +// +// This is Hugo's hlLinesToRanges with "startLine" removed and errors +// ignored. +func ParseRanges(s string) [][2]int { + var ranges [][2]int + s = strings.TrimSpace(s) + if s == "" { + return ranges + } + fields := strings.Split(s, " ") + for _, field := range fields { + field = strings.TrimSpace(field) + if field == "" { + continue + } + numbers := strings.Split(field, "-") + var r [2]int + if len(numbers) > 1 { + first, err := strconv.Atoi(numbers[0]) + if err != nil { + return ranges + } + second, err := strconv.Atoi(numbers[1]) + if err != nil { + return ranges + } + r[0] = first + r[1] = second + } else { + first, err := strconv.Atoi(numbers[0]) + if err != nil { + return ranges + } + r[0] = first + r[1] = first + } + + ranges = append(ranges, r) + } + return ranges +}