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
|
Or linenumbers, by giving the first number
|
||||||
must stay in the front _if it is given_:
|
|
||||||
|
|
||||||
[<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
|
[Code Block Macro]: https://confluence.atlassian.com/doc/code-block-macro-139390.html
|
||||||
|
|
||||||
|
@ -8,6 +8,13 @@ import (
|
|||||||
bf "github.com/kovetskiy/blackfriday/v2"
|
bf "github.com/kovetskiy/blackfriday/v2"
|
||||||
"github.com/kovetskiy/mark/pkg/mark/stdlib"
|
"github.com/kovetskiy/mark/pkg/mark/stdlib"
|
||||||
"github.com/reconquest/pkg/log"
|
"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 {
|
type ConfluenceRenderer struct {
|
||||||
@ -16,57 +23,59 @@ type ConfluenceRenderer struct {
|
|||||||
Stdlib *stdlib.Lib
|
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(
|
func (renderer ConfluenceRenderer) RenderNode(
|
||||||
writer io.Writer,
|
writer io.Writer,
|
||||||
node *bf.Node,
|
node *bf.Node,
|
||||||
entering bool,
|
entering bool,
|
||||||
) bf.WalkStatus {
|
) bf.WalkStatus {
|
||||||
if node.Type == bf.CodeBlock {
|
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(
|
renderer.Stdlib.Templates.ExecuteTemplate(
|
||||||
writer,
|
writer,
|
||||||
"ac:code",
|
"ac:code",
|
||||||
struct {
|
struct {
|
||||||
Language string
|
Language string
|
||||||
Collapse bool
|
Collapse bool
|
||||||
Title string
|
Title string
|
||||||
Text string
|
Theme string
|
||||||
|
Linenumbers bool
|
||||||
|
Firstline int
|
||||||
|
Text string
|
||||||
}{
|
}{
|
||||||
ParseLanguage(lang),
|
lang,
|
||||||
strings.Contains(lang, "collapse"),
|
collapse,
|
||||||
ParseTitle(lang),
|
title,
|
||||||
|
theme,
|
||||||
|
linenumbers,
|
||||||
|
firstline,
|
||||||
strings.TrimSuffix(string(node.Literal), "\n"),
|
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 }}`,
|
/**/ `{{ 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="language">{{ .Language }}</ac:parameter>{{printf "\n"}}{{ end }}`,
|
||||||
/**/ `<ac:parameter ac:name="collapse">{{ .Collapse }}</ac:parameter>{{printf "\n"}}`,
|
/**/ `<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 }}`,
|
/**/ `{{ 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:plain-text-body><![CDATA[{{ .Text | cdata }}]]></ac:plain-text-body>{{printf "\n"}}`,
|
||||||
`</ac:structured-macro>{{printf "\n"}}`,
|
`</ac:structured-macro>{{printf "\n"}}`,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user