package stdlib
import (
"strings"
"text/template"
"github.com/kovetskiy/mark/confluence"
"github.com/kovetskiy/mark/macro"
"github.com/reconquest/pkg/log"
"github.com/reconquest/karma-go"
)
type Lib struct {
Macros []macro.Macro
Templates *template.Template
}
func New(api *confluence.API) (*Lib, error) {
var (
lib Lib
err error
)
lib.Templates, err = templates(api)
if err != nil {
return nil, err
}
lib.Macros, err = macros(lib.Templates)
if err != nil {
return nil, err
}
return &lib, nil
}
func macros(templates *template.Template) ([]macro.Macro, error) {
text := func(line ...string) []byte {
return []byte(strings.Join(line, "\n"))
}
macros, _, err := macro.ExtractMacros(
"",
"",
text(
``,
// TODO(seletskiy): more macros here
),
templates,
)
if err != nil {
return nil, err
}
return macros, nil
}
func templates(api *confluence.API) (*template.Template, error) {
text := func(line ...string) string {
return strings.Join(line, ``)
}
templates := template.New(`stdlib`).Funcs(
template.FuncMap{
"user": func(name string) *confluence.User {
user, err := api.GetUserByName(name)
if err != nil {
log.Error(err)
}
return user
},
// The only way to escape CDATA end marker ']]>' is to split it
// into two CDATA sections.
"cdata": func(data string) string {
return strings.ReplaceAll(
data,
"]]>",
"]]>",
)
},
"convertAttachment": func(data string) string {
return strings.ReplaceAll(
data,
"/",
"_",
)
},
},
)
var err error
for name, body := range map[string]string{
// This template is used to select whole article layout
`ac:layout`: text(
`{{ if eq .Layout "article" }}`,
/**/ ``,
/**/ ``,
/**/ `{{ .Body }}`,
/**/ `{{ .Sidebar }}`,
/**/ ``,
/**/ ``,
`{{ else }}`,
/**/ `{{ .Body }}`,
`{{ end }}`,
),
// This template is used for rendering code in ```
`ac:code`: text(
``,
/**/ `{{ if eq .Language "mermaid" }}true{{ else }}`,
/**/ `{{ .Language }}{{ end }}`,
/**/ `{{ .Collapse }}`,
/**/ `{{ if .Theme }}{{ .Theme }}{{ end }}`,
/**/ `{{ if .Linenumbers }}{{ .Linenumbers }}{{ end }}`,
/**/ `{{ if .Firstline }}{{ .Firstline }}{{ end }}`,
/**/ `{{ if .Title }}{{ .Title }}{{ end }}`,
/**/ ``,
``,
),
`ac:status`: text(
``,
`{{ or .Color "Grey" }}`,
`{{ or .Title .Color }}`,
`{{ or .Subtle false }}`,
``,
),
`ac:link:user`: text(
`{{ with .Name | user }}`,
/**/ ``,
/**/ `{{ if .AccountID }}`,
/****/ ``,
/**/ `{{ else }}`,
/****/ ``,
/**/ `{{ end }}`,
/**/ ``,
`{{ else }}`,
/**/ `{{ .Name }}`,
`{{ end }}`,
),
`ac:jira:ticket`: text(
``,
`{{ .Ticket }}`,
``,
),
/* Used for rendering Jira Filters */
`ac:jira:filter`: text(
``,
`{{ or .Server "System JIRA" }}`,
`{{ .JQL }}`,
``,
),
/* https://confluence.atlassian.com/doc/jira-issues-macro-139380.html */
`ac:jiraissues`: text(
``,
`{{ or .Anonymous false }}`,
``,
`{{ or .Columns "type;key;summary;assignee;reporter;priority;status;resolution;created;updated;due" }}`,
`{{ or .Count false }}`,
`{{ or .Cache "on" }}`,
`{{ or .Height 480 }}`,
`{{ or .RenderMode "static" }}`,
`{{ or .Title "Jira Issues" }}`,
``,
`{{ or .Width "100%" }}`,
``,
),
/* https://confluence.atlassian.com/conf59/info-tip-note-and-warning-macros-792499127.html */
`ac:box`: text(
``,
`{{ or .Icon "false" }}`,
`{{ if .Title }}{{ .Title }}{{ end }}`,
`{{ .Body }}`,
``,
),
/* https://confluence.atlassian.com/conf59/table-of-contents-macro-792499210.html */
`ac:toc`: text(
``,
`{{ or .Printable "true" }}`,
`{{ or .Style "disc" }}`,
`{{ or .MaxLevel "7" }}`,
`{{ or .Indent "" }}`,
`{{ or .MinLevel "1" }}`,
`{{ or .Exclude "" }}`,
`{{ or .Type "list" }}`,
`{{ or .Outline "clear" }}`,
`{{ or .Include "" }}`,
``,
),
/* https://confluence.atlassian.com/doc/children-display-macro-139501.html */
`ac:children`: text(
``,
`{{ if .Reverse }}{{ or .Reverse }}{{ end }}`,
`{{ if .Sort }}{{ .Sort }}{{ end }}`,
`{{ if .Style }}{{ .Style }}{{ end }}`,
`{{ if .Page }}`,
/**/ ``,
/**/ ``,
/**/ ``,
/**/ ``,
/**/ ``,
`{{ end }}`,
`{{ if .Excerpt }}{{ .Excerpt }}{{ end }}`,
`{{ if .First }}{{ .First }}{{ end }}`,
`{{ if .Depth }}{{ .Depth }}{{ end }}`,
`{{ if .All }}{{ .All }}{{ end }}`,
``,
),
/* https://confluence.atlassian.com/doc/confluence-storage-format-790796544.html */
`ac:emoticon`: text(
``,
),
`ac:image`: text(
``,
`{{ if .Attachment }}{{ end }}`,
`{{ if .Url }}{{ end }}`,
``,
),
/* https://confluence.atlassian.com/doc/widget-connector-macro-171180449.html#WidgetConnectorMacro-YouTube */
`ac:youtube`: text(
``,
`youtube`,
`com/atlassian/confluence/extra/widgetconnector/templates/youtube.vm`,
`{{ or .Width "640px" }}`,
`{{ or .Height "360px" }}`,
``,
``,
),
/* https://support.atlassian.com/confluence-cloud/docs/insert-the-iframe-macro/ */
`ac:iframe`: text(
``,
``,
`{{ if .Frameborder }}{{ .Frameborder }}{{ end }}`,
`{{ if .Scrolling }}{{ .Scrolling }}{{ end }}`,
`{{ if .Align }}{{ .Align }}{{ end }}`,
`{{ or .Width "640px" }}`,
`{{ or .Height "360px" }}`,
``,
),
/* https://confluence.atlassian.com/doc/blog-posts-macro-139470.html */
`ac:blog-posts`: text(
``,
`{{ if .Content }}{{ .Content }}{{ end }}`,
`{{ if .Spaces }}{{ .Spaces }}{{ end }}`,
`{{ if .Author }}{{ .Author }}{{ end }}`,
`{{ if .Time }}{{ .Time }}{{ end }}`,
`{{ if .Reverse }}{{ .Reverse }}{{ end }}`,
`{{ if .Sort }}{{ .Sort }}{{ end }}`,
`{{ if .Max }}{{ .Max }}{{ end }}`,
`{{ if .Label }}{{ .Label }}{{ end }}`,
``,
),
/* https://confluence.atlassian.com/conf59/include-page-macro-792499125.html */
`ac:include`: text(
``,
``,
``,
``,
``,
``,
``,
),
/* https://confluence.atlassian.com/conf59/excerpt-include-macro-792499101.html */
/* https://support.atlassian.com/confluence-cloud/docs/insert-the-excerpt-include-macro/ */
`ac:excerpt-include`: text(
``,
`{{ if .Name }}{{ .Name }}{{ end }}`,
`{{ if .NoPanel }}{{ .NoPanel }}{{ else }}false{{ end }}`,
`{{ .Page }}`,
``,
),
/* https://confluence.atlassian.com/conf59/excerpt-macro-792499102.html */
/* https://support.atlassian.com/confluence-cloud/docs/insert-the-excerpt-macro/ */
`ac:excerpt`: text(
``,
`{{ if .Name }}{{ .Name }}{{ end }}`,
`{{ if .Hidden }}{{ .Hidden }}{{ else }}false{{ end }}`,
`{{ if .OutputType }}{{ .OutputType }}{{ else }}BLOCK{{ end }}`,
``,
`{{ .Excerpt }}`,
``,
``,
),
/* https://confluence.atlassian.com/conf59/anchor-macro-792499068.html */
`ac:anchor`: text(
``,
`{{ .Anchor }}`,
``,
),
/* https://confluence.atlassian.com/conf59/expand-macro-792499106.html */
`ac:expand`: text(
``,
`{{ .Title }}`,
`{{ .Body }}`,
``,
),
/* https://confluence.atlassian.com/conf59/user-profile-macro-792499223.html */
`ac:profile`: text(
`{{ with .Name | user }}`,
``,
``,
`{{ if .AccountID }}`,
/**/ ``,
`{{ else }}`,
/**/ ``,
`{{ end }}`,
``,
``,
`{{ end }}`,
),
/* https://confluence.atlassian.com/conf59/content-by-label-macro-792499087.html */
`ac:contentbylabel`: text(
``,
`{{ .CQL }}`,
``,
),
/* https://confluence.atlassian.com/conf59/page-properties-report-macro-792499165.html */
`ac:detailssummary`: text(
``,
`{{ .Headings }}`,
`{{ .FirstColumn }}`,
`{{ .SortBy }}`,
`{{ .CQL }}`,
``,
),
/* https://confluence.atlassian.com/conf59/page-properties-macro-792499154.html */
`ac:details`: text(
``,
`{{ .Body }}`,
``,
),
/* https://confluence.atlassian.com/conf59/page-tree-macro-792499177.html */
`ac:pagetree`: text(
``,
``,
``,
``,
``,
``,
`{{ or .Sort "" }}`,
`{{ or .Excerpt "" }}`,
`{{ or .Reverse "" }}`,
`{{ or .SearchBox "" }}`,
`{{ or .ExpandCollapseAll "" }}`,
`{{ or .StartDepth "" }}`,
``,
),
/* https://confluence.atlassian.com/conf59/page-tree-search-macro-792499178.html */
`ac:pagetreesearch`: text(
``,
`{{ if .Root }}{{ .Root }}{{ end }}`,
``,
),
/* https://confluence.atlassian.com/conf59/panel-macro-792499179.html */
`ac:panel`: text(
``,
`{{ or .BGColor "" }}`,
`{{ or .TitleBGColor "" }}`,
`{{ or .Title "" }}`,
`{{ or .BorderStyle "" }}`,
`{{ or .BorderColor "" }}`,
`{{ or .TitleColor "" }}`,
`{{ .Body }}`,
``,
),
/* https://confluence.atlassian.com/conf59/recently-updated-macro-792499187.html */
`ac:recently-updated`: text(
``,
`{{ if .Spaces }}{{ end }}`,
`{{ or .ShowProfilePic "" }}`,
`{{ or .Types "page, comment, blogpost" }}`,
`{{ or .Max "" }}`,
`{{ or .Labels "" }}`,
`{{ or .HideHeading "" }}`,
`{{ or .Theme "" }}`,
``,
),
/* https://confluence.atlassian.com/conf59/column-macro-792499085.html */
`ac:column`: text(
``,
`{{ or .Width "" }}`,
`{{ or .Body "" }}`,
``,
),
/* https://confluence.atlassian.com/conf59/multimedia-macro-792499140.html */
`ac:multimedia`: text(
``,
`{{ or .Width 500 }}`,
``,
``,
``,
`{{ or .AutoPlay "false"}}`,
``,
),
// TODO(seletskiy): more templates here
} {
templates, err = templates.New(name).Parse(body)
if err != nil {
return nil, karma.
Describe("template", body).
Format(
err,
"unable to parse template",
)
}
}
return templates, nil
}