aboutsummaryrefslogtreecommitdiff
path: root/vendor/github.com/yuin/goldmark-highlighting/v2
diff options
context:
space:
mode:
authorMitja Felicijan <mitja.felicijan@gmail.com>2024-10-25 00:47:47 +0200
committerMitja Felicijan <mitja.felicijan@gmail.com>2024-10-25 00:47:47 +0200
commitc6cc0108ca7738023b45e0eeac0fa2390532dd93 (patch)
tree36890e6cd3091bbab8efbe686cc56f467f645bfd /vendor/github.com/yuin/goldmark-highlighting/v2
parent0130404a1dc663d4aa68d780c9bcb23a4243e68d (diff)
downloadjbmafp-c6cc0108ca7738023b45e0eeac0fa2390532dd93.tar.gz
Added vendor lock on depsHEADmaster
Diffstat (limited to 'vendor/github.com/yuin/goldmark-highlighting/v2')
-rw-r--r--vendor/github.com/yuin/goldmark-highlighting/v2/.gitignore13
-rw-r--r--vendor/github.com/yuin/goldmark-highlighting/v2/LICENSE21
-rw-r--r--vendor/github.com/yuin/goldmark-highlighting/v2/README.md66
-rw-r--r--vendor/github.com/yuin/goldmark-highlighting/v2/highlighting.go578
4 files changed, 678 insertions, 0 deletions
diff --git a/vendor/github.com/yuin/goldmark-highlighting/v2/.gitignore b/vendor/github.com/yuin/goldmark-highlighting/v2/.gitignore
new file mode 100644
index 0000000..6e4db92
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark-highlighting/v2/.gitignore
@@ -0,0 +1,13 @@
1# Binaries for programs and plugins
2*.exe
3*.exe~
4*.dll
5*.so
6*.dylib
7
8# Test binary, build with `go test -c`
9*.test
10*.pprof
11
12# Output of the go coverage tool, specifically when used with LiteIDE
13*.out
diff --git a/vendor/github.com/yuin/goldmark-highlighting/v2/LICENSE b/vendor/github.com/yuin/goldmark-highlighting/v2/LICENSE
new file mode 100644
index 0000000..dc5b2a6
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark-highlighting/v2/LICENSE
@@ -0,0 +1,21 @@
1MIT License
2
3Copyright (c) 2019 Yusuke Inuzuka
4
5Permission is hereby granted, free of charge, to any person obtaining a copy
6of this software and associated documentation files (the "Software"), to deal
7in the Software without restriction, including without limitation the rights
8to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9copies of the Software, and to permit persons to whom the Software is
10furnished to do so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in all
13copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21SOFTWARE.
diff --git a/vendor/github.com/yuin/goldmark-highlighting/v2/README.md b/vendor/github.com/yuin/goldmark-highlighting/v2/README.md
new file mode 100644
index 0000000..5f33672
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark-highlighting/v2/README.md
@@ -0,0 +1,66 @@
1goldmark-highlighting
2=========================
3
4goldmark-highlighting is an extension for the [goldmark](http://github.com/yuin/goldmark)
5that adds syntax-highlighting to the fenced code blocks.
6
7goldmark-highlighting uses [chroma](https://github.com/alecthomas/chroma) as a
8syntax highlighter.
9
10Installation
11--------------------
12
13```
14go get github.com/yuin/goldmark-highlighting/v2
15```
16
17Usage
18--------------------
19
20```go
21import (
22 "bytes"
23 "fmt"
24 "github.com/alecthomas/chroma/formatters/html"
25 "github.com/yuin/goldmark"
26 "github.com/yuin/goldmark/extension"
27 "github.com/yuin/goldmark/parser"
28 "github.com/yuin/goldmark-highlighting/v2"
29
30)
31
32func main() {
33 markdown := goldmark.New(
34 goldmark.WithExtensions(
35 highlighting.Highlighting,
36 ),
37 )
38 var buf bytes.Buffer
39 if err := markdown.Convert([]byte(source), &buf); err != nil {
40 panic(err)
41 }
42 fmt.Print(title)
43}
44```
45
46
47```go
48 markdown := goldmark.New(
49 goldmark.WithExtensions(
50 highlighting.NewHighlighting(
51 highlighting.WithStyle("monokai"),
52 highlighting.WithFormatOptions(
53 html.WithLineNumbers(),
54 ),
55 ),
56 ),
57 )
58```
59
60License
61--------------------
62MIT
63
64Author
65--------------------
66Yusuke Inuzuka
diff --git a/vendor/github.com/yuin/goldmark-highlighting/v2/highlighting.go b/vendor/github.com/yuin/goldmark-highlighting/v2/highlighting.go
new file mode 100644
index 0000000..d14408a
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark-highlighting/v2/highlighting.go
@@ -0,0 +1,578 @@
1// package highlighting is a extension for the goldmark(http://github.com/yuin/goldmark).
2//
3// This extension adds syntax-highlighting to the fenced code blocks using
4// chroma(https://github.com/alecthomas/chroma).
5package highlighting
6
7import (
8 "bytes"
9 "io"
10 "strconv"
11 "strings"
12
13 "github.com/yuin/goldmark"
14 "github.com/yuin/goldmark/ast"
15 "github.com/yuin/goldmark/parser"
16 "github.com/yuin/goldmark/renderer"
17 "github.com/yuin/goldmark/renderer/html"
18 "github.com/yuin/goldmark/text"
19 "github.com/yuin/goldmark/util"
20
21 "github.com/alecthomas/chroma/v2"
22 chromahtml "github.com/alecthomas/chroma/v2/formatters/html"
23 "github.com/alecthomas/chroma/v2/lexers"
24 "github.com/alecthomas/chroma/v2/styles"
25)
26
27// ImmutableAttributes is a read-only interface for ast.Attributes.
28type ImmutableAttributes interface {
29 // Get returns (value, true) if an attribute associated with given
30 // name exists, otherwise (nil, false)
31 Get(name []byte) (interface{}, bool)
32
33 // GetString returns (value, true) if an attribute associated with given
34 // name exists, otherwise (nil, false)
35 GetString(name string) (interface{}, bool)
36
37 // All returns all attributes.
38 All() []ast.Attribute
39}
40
41type immutableAttributes struct {
42 n ast.Node
43}
44
45func (a *immutableAttributes) Get(name []byte) (interface{}, bool) {
46 return a.n.Attribute(name)
47}
48
49func (a *immutableAttributes) GetString(name string) (interface{}, bool) {
50 return a.n.AttributeString(name)
51}
52
53func (a *immutableAttributes) All() []ast.Attribute {
54 if a.n.Attributes() == nil {
55 return []ast.Attribute{}
56 }
57 return a.n.Attributes()
58}
59
60// CodeBlockContext holds contextual information of code highlighting.
61type CodeBlockContext interface {
62 // Language returns (language, true) if specified, otherwise (nil, false).
63 Language() ([]byte, bool)
64
65 // Highlighted returns true if this code block can be highlighted, otherwise false.
66 Highlighted() bool
67
68 // Attributes return attributes of the code block.
69 Attributes() ImmutableAttributes
70}
71
72type codeBlockContext struct {
73 language []byte
74 highlighted bool
75 attributes ImmutableAttributes
76}
77
78func newCodeBlockContext(language []byte, highlighted bool, attrs ImmutableAttributes) CodeBlockContext {
79 return &codeBlockContext{
80 language: language,
81 highlighted: highlighted,
82 attributes: attrs,
83 }
84}
85
86func (c *codeBlockContext) Language() ([]byte, bool) {
87 if c.language != nil {
88 return c.language, true
89 }
90 return nil, false
91}
92
93func (c *codeBlockContext) Highlighted() bool {
94 return c.highlighted
95}
96
97func (c *codeBlockContext) Attributes() ImmutableAttributes {
98 return c.attributes
99}
100
101// WrapperRenderer renders wrapper elements like div, pre, etc.
102type WrapperRenderer func(w util.BufWriter, context CodeBlockContext, entering bool)
103
104// CodeBlockOptions creates Chroma options per code block.
105type CodeBlockOptions func(ctx CodeBlockContext) []chromahtml.Option
106
107// Config struct holds options for the extension.
108type Config struct {
109 html.Config
110
111 // Style is a highlighting style.
112 // Supported styles are defined under https://github.com/alecthomas/chroma/tree/master/formatters.
113 Style string
114
115 // Pass in a custom Chroma style. If this is not nil, the Style string will be ignored
116 CustomStyle *chroma.Style
117
118 // If set, will try to guess language if none provided.
119 // If the guessing fails, we will fall back to a text lexer.
120 // Note that while Chroma's API supports language guessing, the implementation
121 // is not there yet, so you will currently always get the basic text lexer.
122 GuessLanguage bool
123
124 // FormatOptions is a option related to output formats.
125 // See https://github.com/alecthomas/chroma#the-html-formatter for details.
126 FormatOptions []chromahtml.Option
127
128 // CSSWriter is an io.Writer that will be used as CSS data output buffer.
129 // If WithClasses() is enabled, you can get CSS data corresponds to the style.
130 CSSWriter io.Writer
131
132 // CodeBlockOptions allows set Chroma options per code block.
133 CodeBlockOptions CodeBlockOptions
134
135 // WrapperRenderer allows you to change wrapper elements.
136 WrapperRenderer WrapperRenderer
137}
138
139// NewConfig returns a new Config with defaults.
140func NewConfig() Config {
141 return Config{
142 Config: html.NewConfig(),
143 Style: "github",
144 FormatOptions: []chromahtml.Option{},
145 CSSWriter: nil,
146 WrapperRenderer: nil,
147 CodeBlockOptions: nil,
148 }
149}
150
151// SetOption implements renderer.SetOptioner.
152func (c *Config) SetOption(name renderer.OptionName, value interface{}) {
153 switch name {
154 case optStyle:
155 c.Style = value.(string)
156 case optCustomStyle:
157 c.CustomStyle = value.(*chroma.Style)
158 case optFormatOptions:
159 if value != nil {
160 c.FormatOptions = value.([]chromahtml.Option)
161 }
162 case optCSSWriter:
163 c.CSSWriter = value.(io.Writer)
164 case optWrapperRenderer:
165 c.WrapperRenderer = value.(WrapperRenderer)
166 case optCodeBlockOptions:
167 c.CodeBlockOptions = value.(CodeBlockOptions)
168 case optGuessLanguage:
169 c.GuessLanguage = value.(bool)
170 default:
171 c.Config.SetOption(name, value)
172 }
173}
174
175// Option interface is a functional option interface for the extension.
176type Option interface {
177 renderer.Option
178 // SetHighlightingOption sets given option to the extension.
179 SetHighlightingOption(*Config)
180}
181
182type withHTMLOptions struct {
183 value []html.Option
184}
185
186func (o *withHTMLOptions) SetConfig(c *renderer.Config) {
187 if o.value != nil {
188 for _, v := range o.value {
189 v.(renderer.Option).SetConfig(c)
190 }
191 }
192}
193
194func (o *withHTMLOptions) SetHighlightingOption(c *Config) {
195 if o.value != nil {
196 for _, v := range o.value {
197 v.SetHTMLOption(&c.Config)
198 }
199 }
200}
201
202// WithHTMLOptions is functional option that wraps goldmark HTMLRenderer options.
203func WithHTMLOptions(opts ...html.Option) Option {
204 return &withHTMLOptions{opts}
205}
206
207const optStyle renderer.OptionName = "HighlightingStyle"
208const optCustomStyle renderer.OptionName = "HighlightingCustomStyle"
209
210var highlightLinesAttrName = []byte("hl_lines")
211
212var styleAttrName = []byte("hl_style")
213var nohlAttrName = []byte("nohl")
214var linenosAttrName = []byte("linenos")
215var linenosTableAttrValue = []byte("table")
216var linenosInlineAttrValue = []byte("inline")
217var linenostartAttrName = []byte("linenostart")
218
219type withStyle struct {
220 value string
221}
222
223func (o *withStyle) SetConfig(c *renderer.Config) {
224 c.Options[optStyle] = o.value
225}
226
227func (o *withStyle) SetHighlightingOption(c *Config) {
228 c.Style = o.value
229}
230
231// WithStyle is a functional option that changes highlighting style.
232func WithStyle(style string) Option {
233 return &withStyle{style}
234}
235
236type withCustomStyle struct {
237 value *chroma.Style
238}
239
240func (o *withCustomStyle) SetConfig(c *renderer.Config) {
241 c.Options[optCustomStyle] = o.value
242}
243
244func (o *withCustomStyle) SetHighlightingOption(c *Config) {
245 c.CustomStyle = o.value
246}
247
248// WithStyle is a functional option that changes highlighting style.
249func WithCustomStyle(style *chroma.Style) Option {
250 return &withCustomStyle{style}
251}
252
253const optCSSWriter renderer.OptionName = "HighlightingCSSWriter"
254
255type withCSSWriter struct {
256 value io.Writer
257}
258
259func (o *withCSSWriter) SetConfig(c *renderer.Config) {
260 c.Options[optCSSWriter] = o.value
261}
262
263func (o *withCSSWriter) SetHighlightingOption(c *Config) {
264 c.CSSWriter = o.value
265}
266
267// WithCSSWriter is a functional option that sets io.Writer for CSS data.
268func WithCSSWriter(w io.Writer) Option {
269 return &withCSSWriter{w}
270}
271
272const optGuessLanguage renderer.OptionName = "HighlightingGuessLanguage"
273
274type withGuessLanguage struct {
275 value bool
276}
277
278func (o *withGuessLanguage) SetConfig(c *renderer.Config) {
279 c.Options[optGuessLanguage] = o.value
280}
281
282func (o *withGuessLanguage) SetHighlightingOption(c *Config) {
283 c.GuessLanguage = o.value
284}
285
286// WithGuessLanguage is a functional option that toggles language guessing
287// if none provided.
288func WithGuessLanguage(b bool) Option {
289 return &withGuessLanguage{value: b}
290}
291
292const optWrapperRenderer renderer.OptionName = "HighlightingWrapperRenderer"
293
294type withWrapperRenderer struct {
295 value WrapperRenderer
296}
297
298func (o *withWrapperRenderer) SetConfig(c *renderer.Config) {
299 c.Options[optWrapperRenderer] = o.value
300}
301
302func (o *withWrapperRenderer) SetHighlightingOption(c *Config) {
303 c.WrapperRenderer = o.value
304}
305
306// WithWrapperRenderer is a functional option that sets WrapperRenderer that
307// renders wrapper elements like div, pre, etc.
308func WithWrapperRenderer(w WrapperRenderer) Option {
309 return &withWrapperRenderer{w}
310}
311
312const optCodeBlockOptions renderer.OptionName = "HighlightingCodeBlockOptions"
313
314type withCodeBlockOptions struct {
315 value CodeBlockOptions
316}
317
318func (o *withCodeBlockOptions) SetConfig(c *renderer.Config) {
319 c.Options[optWrapperRenderer] = o.value
320}
321
322func (o *withCodeBlockOptions) SetHighlightingOption(c *Config) {
323 c.CodeBlockOptions = o.value
324}
325
326// WithCodeBlockOptions is a functional option that sets CodeBlockOptions that
327// allows setting Chroma options per code block.
328func WithCodeBlockOptions(c CodeBlockOptions) Option {
329 return &withCodeBlockOptions{value: c}
330}
331
332const optFormatOptions renderer.OptionName = "HighlightingFormatOptions"
333
334type withFormatOptions struct {
335 value []chromahtml.Option
336}
337
338func (o *withFormatOptions) SetConfig(c *renderer.Config) {
339 if _, ok := c.Options[optFormatOptions]; !ok {
340 c.Options[optFormatOptions] = []chromahtml.Option{}
341 }
342 c.Options[optFormatOptions] = append(c.Options[optFormatOptions].([]chromahtml.Option), o.value...)
343}
344
345func (o *withFormatOptions) SetHighlightingOption(c *Config) {
346 c.FormatOptions = append(c.FormatOptions, o.value...)
347}
348
349// WithFormatOptions is a functional option that wraps chroma HTML formatter options.
350func WithFormatOptions(opts ...chromahtml.Option) Option {
351 return &withFormatOptions{opts}
352}
353
354// HTMLRenderer struct is a renderer.NodeRenderer implementation for the extension.
355type HTMLRenderer struct {
356 Config
357}
358
359// NewHTMLRenderer builds a new HTMLRenderer with given options and returns it.
360func NewHTMLRenderer(opts ...Option) renderer.NodeRenderer {
361 r := &HTMLRenderer{
362 Config: NewConfig(),
363 }
364 for _, opt := range opts {
365 opt.SetHighlightingOption(&r.Config)
366 }
367 return r
368}
369
370// RegisterFuncs implements NodeRenderer.RegisterFuncs.
371func (r *HTMLRenderer) RegisterFuncs(reg renderer.NodeRendererFuncRegisterer) {
372 reg.Register(ast.KindFencedCodeBlock, r.renderFencedCodeBlock)
373}
374
375func getAttributes(node *ast.FencedCodeBlock, infostr []byte) ImmutableAttributes {
376 if node.Attributes() != nil {
377 return &immutableAttributes{node}
378 }
379 if infostr != nil {
380 attrStartIdx := -1
381
382 for idx, char := range infostr {
383 if char == '{' {
384 attrStartIdx = idx
385 break
386 }
387 }
388 if attrStartIdx > 0 {
389 n := ast.NewTextBlock() // dummy node for storing attributes
390 attrStr := infostr[attrStartIdx:]
391 if attrs, hasAttr := parser.ParseAttributes(text.NewReader(attrStr)); hasAttr {
392 for _, attr := range attrs {
393 n.SetAttribute(attr.Name, attr.Value)
394 }
395 return &immutableAttributes{n}
396 }
397 }
398 }
399 return nil
400}
401
402func (r *HTMLRenderer) renderFencedCodeBlock(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) {
403 n := node.(*ast.FencedCodeBlock)
404 if !entering {
405 return ast.WalkContinue, nil
406 }
407 language := n.Language(source)
408
409 chromaFormatterOptions := make([]chromahtml.Option, len(r.FormatOptions))
410 copy(chromaFormatterOptions, r.FormatOptions)
411
412 style := r.CustomStyle
413 if style == nil {
414 style = styles.Get(r.Style)
415 }
416 nohl := false
417
418 var info []byte
419 if n.Info != nil {
420 info = n.Info.Segment.Value(source)
421 }
422 attrs := getAttributes(n, info)
423 if attrs != nil {
424 baseLineNumber := 1
425 if linenostartAttr, ok := attrs.Get(linenostartAttrName); ok {
426 if linenostart, ok := linenostartAttr.(float64); ok {
427 baseLineNumber = int(linenostart)
428 chromaFormatterOptions = append(chromaFormatterOptions, chromahtml.BaseLineNumber(baseLineNumber))
429 }
430 }
431 if linesAttr, hasLinesAttr := attrs.Get(highlightLinesAttrName); hasLinesAttr {
432 if lines, ok := linesAttr.([]interface{}); ok {
433 var hlRanges [][2]int
434 for _, l := range lines {
435 if ln, ok := l.(float64); ok {
436 hlRanges = append(hlRanges, [2]int{int(ln) + baseLineNumber - 1, int(ln) + baseLineNumber - 1})
437 }
438 if rng, ok := l.([]uint8); ok {
439 slices := strings.Split(string([]byte(rng)), "-")
440 lhs, err := strconv.Atoi(slices[0])
441 if err != nil {
442 continue
443 }
444 rhs := lhs
445 if len(slices) > 1 {
446 rhs, err = strconv.Atoi(slices[1])
447 if err != nil {
448 continue
449 }
450 }
451 hlRanges = append(hlRanges, [2]int{lhs + baseLineNumber - 1, rhs + baseLineNumber - 1})
452 }
453 }
454 chromaFormatterOptions = append(chromaFormatterOptions, chromahtml.HighlightLines(hlRanges))
455 }
456 }
457 if styleAttr, hasStyleAttr := attrs.Get(styleAttrName); hasStyleAttr {
458 if st, ok := styleAttr.([]uint8); ok {
459 styleStr := string([]byte(st))
460 style = styles.Get(styleStr)
461 }
462 }
463 if _, hasNohlAttr := attrs.Get(nohlAttrName); hasNohlAttr {
464 nohl = true
465 }
466
467 if linenosAttr, ok := attrs.Get(linenosAttrName); ok {
468 switch v := linenosAttr.(type) {
469 case bool:
470 chromaFormatterOptions = append(chromaFormatterOptions, chromahtml.WithLineNumbers(v))
471 case []uint8:
472 if v != nil {
473 chromaFormatterOptions = append(chromaFormatterOptions, chromahtml.WithLineNumbers(true))
474 }
475 if bytes.Equal(v, linenosTableAttrValue) {
476 chromaFormatterOptions = append(chromaFormatterOptions, chromahtml.LineNumbersInTable(true))
477 } else if bytes.Equal(v, linenosInlineAttrValue) {
478 chromaFormatterOptions = append(chromaFormatterOptions, chromahtml.LineNumbersInTable(false))
479 }
480 }
481 }
482 }
483
484 var lexer chroma.Lexer
485 if language != nil {
486 lexer = lexers.Get(string(language))
487 }
488 if !nohl && (lexer != nil || r.GuessLanguage) {
489 if style == nil {
490 style = styles.Fallback
491 }
492 var buffer bytes.Buffer
493 l := n.Lines().Len()
494 for i := 0; i < l; i++ {
495 line := n.Lines().At(i)
496 buffer.Write(line.Value(source))
497 }
498
499 if lexer == nil {
500 lexer = lexers.Analyse(buffer.String())
501 if lexer == nil {
502 lexer = lexers.Fallback
503 }
504 language = []byte(strings.ToLower(lexer.Config().Name))
505 }
506 lexer = chroma.Coalesce(lexer)
507
508 iterator, err := lexer.Tokenise(nil, buffer.String())
509 if err == nil {
510 c := newCodeBlockContext(language, true, attrs)
511
512 if r.CodeBlockOptions != nil {
513 chromaFormatterOptions = append(chromaFormatterOptions, r.CodeBlockOptions(c)...)
514 }
515 formatter := chromahtml.New(chromaFormatterOptions...)
516 if r.WrapperRenderer != nil {
517 r.WrapperRenderer(w, c, true)
518 }
519 _ = formatter.Format(w, style, iterator) == nil
520 if r.WrapperRenderer != nil {
521 r.WrapperRenderer(w, c, false)
522 }
523 if r.CSSWriter != nil {
524 _ = formatter.WriteCSS(r.CSSWriter, style)
525 }
526 return ast.WalkContinue, nil
527 }
528 }
529
530 var c CodeBlockContext
531 if r.WrapperRenderer != nil {
532 c = newCodeBlockContext(language, false, attrs)
533 r.WrapperRenderer(w, c, true)
534 } else {
535 _, _ = w.WriteString("<pre><code")
536 language := n.Language(source)
537 if language != nil {
538 _, _ = w.WriteString(" class=\"language-")
539 r.Writer.Write(w, language)
540 _, _ = w.WriteString("\"")
541 }
542 _ = w.WriteByte('>')
543 }
544 l := n.Lines().Len()
545 for i := 0; i < l; i++ {
546 line := n.Lines().At(i)
547 r.Writer.RawWrite(w, line.Value(source))
548 }
549 if r.WrapperRenderer != nil {
550 r.WrapperRenderer(w, c, false)
551 } else {
552 _, _ = w.WriteString("</code></pre>\n")
553 }
554 return ast.WalkContinue, nil
555}
556
557type highlighting struct {
558 options []Option
559}
560
561// Highlighting is a goldmark.Extender implementation.
562var Highlighting = &highlighting{
563 options: []Option{},
564}
565
566// NewHighlighting returns a new extension with given options.
567func NewHighlighting(opts ...Option) goldmark.Extender {
568 return &highlighting{
569 options: opts,
570 }
571}
572
573// Extend implements goldmark.Extender.
574func (e *highlighting) Extend(m goldmark.Markdown) {
575 m.Renderer().AddOptions(renderer.WithNodeRenderers(
576 util.Prioritized(NewHTMLRenderer(e.options...), 200),
577 ))
578}