diff --git a/README.md b/README.md index 83cca54..043295c 100644 --- a/README.md +++ b/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 - [] ["collapse"] ["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 diff --git a/pkg/mark/markdown.go b/pkg/mark/markdown.go index 85b060b..baa9225 100644 --- a/pkg/mark/markdown.go +++ b/pkg/mark/markdown.go @@ -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( + // (|-) (collapse||\d)* (title )? + + `^(?:(\w*)|-)\s*\b(\S.*?\S?)??\s*(?:\btitle\s+(\S.*\S?))?$`, ) type ConfluenceRenderer struct { @@ -16,57 +23,59 @@ 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", struct { - Language string - Collapse bool - Title string - Text string + 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"), }, ) diff --git a/pkg/mark/stdlib/stdlib.go b/pkg/mark/stdlib/stdlib.go index f1bc132..86bbf3e 100644 --- a/pkg/mark/stdlib/stdlib.go +++ b/pkg/mark/stdlib/stdlib.go @@ -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"}}`,