mirror of
https://github.com/kovetskiy/mark.git
synced 2025-04-24 05:42:40 +08:00
Feature/themed blocks (#223)
* Allow themed blocks * add macro code for themed blocks
This commit is contained in:
parent
0b745c25e4
commit
f4bbbb19ca
26
README.md
26
README.md
@ -177,10 +177,30 @@ And you can also add a title:
|
||||
...
|
||||
```
|
||||
|
||||
You can collapse or have a title without language or any mix, but the language
|
||||
must stay in the front _if it is given_:
|
||||
Or linenumbers, by giving the first number
|
||||
|
||||
[<language>] ["collapse"] ["title" <your title>]
|
||||
```bash 1 collapse title Some long long bash function
|
||||
...
|
||||
some long bash code block
|
||||
...
|
||||
```
|
||||
|
||||
And even themes
|
||||
|
||||
```bash 1 collapse midnight title Some long long bash function
|
||||
...
|
||||
some long bash code block
|
||||
...
|
||||
```
|
||||
|
||||
Please note that, if you want to have a code block without a language
|
||||
use `-` as the first character, if you want to have the other goodies
|
||||
|
||||
``` - 1 collapse midnight title Some long long code
|
||||
...
|
||||
some long code block
|
||||
...
|
||||
```
|
||||
|
||||
[Code Block Macro]: https://confluence.atlassian.com/doc/code-block-macro-139390.html
|
||||
|
||||
|
@ -8,6 +8,13 @@ import (
|
||||
bf "github.com/kovetskiy/blackfriday/v2"
|
||||
"github.com/kovetskiy/mark/pkg/mark/stdlib"
|
||||
"github.com/reconquest/pkg/log"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
var reBlockDetails = regexp.MustCompile(
|
||||
// (<Lang>|-) (collapse|<theme>|\d)* (title <title>)?
|
||||
|
||||
`^(?:(\w*)|-)\s*\b(\S.*?\S?)??\s*(?:\btitle\s+(\S.*\S?))?$`,
|
||||
)
|
||||
|
||||
type ConfluenceRenderer struct {
|
||||
@ -16,45 +23,41 @@ type ConfluenceRenderer struct {
|
||||
Stdlib *stdlib.Lib
|
||||
}
|
||||
|
||||
func ParseLanguage(lang string) string {
|
||||
// lang takes the following form: language? "collapse"? ("title"? <any string>*)?
|
||||
// let's split it by spaces
|
||||
paramlist := strings.Fields(lang)
|
||||
|
||||
// get the word in question, aka the first one
|
||||
first := lang
|
||||
if len(paramlist) > 0 {
|
||||
first = paramlist[0]
|
||||
}
|
||||
|
||||
if first == "collapse" || first == "title" {
|
||||
// collapsing or including a title without a language
|
||||
return ""
|
||||
}
|
||||
// the default case with language being the first one
|
||||
return first
|
||||
}
|
||||
|
||||
func ParseTitle(lang string) string {
|
||||
index := strings.Index(lang, "title")
|
||||
if index >= 0 {
|
||||
// it's found, check if title is given and return it
|
||||
start := index + 6
|
||||
if len(lang) > start {
|
||||
return lang[start:]
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (renderer ConfluenceRenderer) RenderNode(
|
||||
writer io.Writer,
|
||||
node *bf.Node,
|
||||
entering bool,
|
||||
) bf.WalkStatus {
|
||||
if node.Type == bf.CodeBlock {
|
||||
lang := string(node.Info)
|
||||
|
||||
groups:= reBlockDetails.FindStringSubmatch(string(node.Info))
|
||||
linenumbers := false
|
||||
firstline := 0
|
||||
theme := ""
|
||||
collapse := false
|
||||
lang := ""
|
||||
var options []string
|
||||
title := ""
|
||||
if len(groups) > 0 {
|
||||
lang, options, title = groups[1], strings.Fields(groups[2]), groups[3]
|
||||
for _, option := range options {
|
||||
if option == "collapse" {
|
||||
collapse = true
|
||||
continue
|
||||
}
|
||||
if option == "nocollapse" {
|
||||
collapse = false
|
||||
continue
|
||||
}
|
||||
var i int
|
||||
if _, err := fmt.Sscanf(option, "%d", &i); err == nil {
|
||||
linenumbers = i > 0
|
||||
firstline = i
|
||||
continue
|
||||
}
|
||||
theme = option
|
||||
}
|
||||
}
|
||||
renderer.Stdlib.Templates.ExecuteTemplate(
|
||||
writer,
|
||||
"ac:code",
|
||||
@ -62,11 +65,17 @@ func (renderer ConfluenceRenderer) RenderNode(
|
||||
Language string
|
||||
Collapse bool
|
||||
Title string
|
||||
Theme string
|
||||
Linenumbers bool
|
||||
Firstline int
|
||||
Text string
|
||||
}{
|
||||
ParseLanguage(lang),
|
||||
strings.Contains(lang, "collapse"),
|
||||
ParseTitle(lang),
|
||||
lang,
|
||||
collapse,
|
||||
title,
|
||||
theme,
|
||||
linenumbers,
|
||||
firstline,
|
||||
strings.TrimSuffix(string(node.Literal), "\n"),
|
||||
},
|
||||
)
|
||||
|
@ -110,6 +110,9 @@ func templates(api *confluence.API) (*template.Template, error) {
|
||||
/**/ `{{ if eq .Language "mermaid" }}<ac:parameter ac:name="showSource">true</ac:parameter>{{printf "\n"}}{{ else }}`,
|
||||
/**/ `<ac:parameter ac:name="language">{{ .Language }}</ac:parameter>{{printf "\n"}}{{ end }}`,
|
||||
/**/ `<ac:parameter ac:name="collapse">{{ .Collapse }}</ac:parameter>{{printf "\n"}}`,
|
||||
/**/ `{{ if .Theme }}<ac:parameter ac:name="theme">{{ .Theme }}</ac:parameter>{{printf "\n"}}{{ end }}`,
|
||||
/**/ `{{ if .Linenumbers }}<ac:parameter ac:name="linenumbers">{{ .Linenumbers }}</ac:parameter>{{printf "\n"}}{{ end }}`,
|
||||
/**/ `{{ if .Firstline }}<ac:parameter ac:name="firstline">{{ .Firstline }}</ac:parameter>{{printf "\n"}}{{ end }}`,
|
||||
/**/ `{{ if .Title }}<ac:parameter ac:name="title">{{ .Title }}</ac:parameter>{{printf "\n"}}{{ end }}`,
|
||||
/**/ `<ac:plain-text-body><![CDATA[{{ .Text | cdata }}]]></ac:plain-text-body>{{printf "\n"}}`,
|
||||
`</ac:structured-macro>{{printf "\n"}}`,
|
||||
|
Loading…
x
Reference in New Issue
Block a user