Skip to content

Commit

Permalink
feat(cli): add 'css' arg to specify the stylesheet (#487)
Browse files Browse the repository at this point in the history
when the `--css=...` argument is used, the generated HTML
document contains a `<link type="text/html" rel="stylesheet" href="...">`
element with the given `--css` value.

Fixes #482

Signed-off-by: Xavier Coulon <[email protected]>
  • Loading branch information
xcoulon authored Jan 27, 2020
1 parent cdccf6f commit c1de2f2
Show file tree
Hide file tree
Showing 6 changed files with 43 additions and 18 deletions.
6 changes: 4 additions & 2 deletions cmd/libasciidoc/root_cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ func NewRootCmd() *cobra.Command {
var noHeaderFooter bool
var outputName string
var logLevel string
var css string

rootCmd := &cobra.Command{
Use: "libasciidoc [flags] FILE",
Expand All @@ -48,7 +49,7 @@ func NewRootCmd() *cobra.Command {
defer close()
path, _ := filepath.Abs(source)
log.Debugf("Starting to process file %v", path)
_, err := libasciidoc.ConvertFileToHTML(source, out, renderer.IncludeHeaderFooter(!noHeaderFooter))
_, err := libasciidoc.ConvertFileToHTML(source, out, renderer.IncludeHeaderFooter(!noHeaderFooter), renderer.IncludeCSS(css))
if err != nil {
return err
}
Expand All @@ -60,7 +61,8 @@ func NewRootCmd() *cobra.Command {
flags := rootCmd.Flags()
flags.BoolVarP(&noHeaderFooter, "no-header-footer", "s", false, "do not render header/footer (default: false)")
flags.StringVarP(&outputName, "out-file", "o", "", "output file (default: based on path of input file); use - to output to STDOUT")
rootCmd.PersistentFlags().StringVar(&logLevel, "log", "warning", "log level to set [debug|info|warning|error|fatal|panic]")
flags.StringVar(&logLevel, "log", "warning", "log level to set [debug|info|warning|error|fatal|panic]")
flags.StringVar(&css, "css", "", "the path to the CSS file to link to the document")
return rootCmd
}

Expand Down
4 changes: 3 additions & 1 deletion libasciidoc_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package libasciidoc_test

import (
"github.com/bytesparadise/libasciidoc/pkg/renderer"
. "github.com/bytesparadise/libasciidoc/testsupport"

. "github.com/onsi/ginkgo"
Expand Down Expand Up @@ -191,6 +192,7 @@ a paragraph with _italic content_`
<!--[if IE]><meta http-equiv="X-UA-Compatible" content="IE=edge"><![endif]-->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="generator" content="libasciidoc">
<link type="text/css" rel="stylesheet" href="path/to/style.css">
<title>Chapter A</title>
</head>
<body class="article">
Expand All @@ -209,7 +211,7 @@ Last updated {{.LastUpdated}}
</div>
</body>
</html>`
Expect("test/includes/chapter-a.adoc").To(RenderHTML5Document(expectedContent))
Expect("test/includes/chapter-a.adoc").To(RenderHTML5Document(expectedContent, renderer.IncludeCSS("path/to/style.css")))
})

})
Expand Down
5 changes: 4 additions & 1 deletion pkg/renderer/html5/document.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ func init() {
<meta charset="UTF-8">
<!--[if IE]><meta http-equiv="X-UA-Compatible" content="IE=edge"><![endif]-->
<meta name="viewport" content="width=device-width, initial-scale=1.0">{{ if .Generator }}
<meta name="generator" content="{{ .Generator }}">{{ end }}
<meta name="generator" content="{{ .Generator }}">{{ end }}{{ if .CSS}}
<link type="text/css" rel="stylesheet" href="{{ .CSS }}">{{ end }}
<title>{{ escape .Title }}</title>
</head>
<body class="article">
Expand Down Expand Up @@ -78,6 +79,7 @@ func renderDocument(ctx renderer.Context, output io.Writer) (map[string]interfac
Content htmltemplate.HTML
RevNumber string
LastUpdated string
CSS string
Details *htmltemplate.HTML
}{
Generator: "libasciidoc", // TODO: externalize this value and include the lib version ?
Expand All @@ -86,6 +88,7 @@ func renderDocument(ctx renderer.Context, output io.Writer) (map[string]interfac
Content: htmltemplate.HTML(string(renderedElements)), //nolint: gosec
RevNumber: revNumber,
LastUpdated: ctx.LastUpdated(),
CSS: ctx.CSS(),
Details: documentDetails,
})
if err != nil {
Expand Down
3 changes: 2 additions & 1 deletion pkg/renderer/html5/document_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ var _ = Describe("document header", func() {
<!--[if IE]><meta http-equiv="X-UA-Compatible" content="IE=edge"><![endif]-->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="generator" content="libasciidoc">
<link type="text/css" rel="stylesheet" href="/path/to/style.css">
<title>The Dangerous and Thrilling Documentation Chronicles</title>
</head>
<body class="article">
Expand All @@ -39,7 +40,7 @@ Last updated {{.LastUpdated}}
</div>
</body>
</html>`
Expect(source).To(RenderHTML5Body(expected, renderer.IncludeHeaderFooter(true), renderer.LastUpdated(time.Now())))
Expect(source).To(RenderHTML5Body(expected, renderer.IncludeHeaderFooter(true), renderer.IncludeCSS("/path/to/style.css"), renderer.LastUpdated(time.Now())))
})
})

Expand Down
36 changes: 25 additions & 11 deletions pkg/renderer/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,13 @@ const (
// keyLastUpdated the key to specify the last update of the document to render.
// Can be a string or a time, which will be formatted using the 2006/01/02 15:04:05 MST` pattern
keyLastUpdated string = types.AttrLastUpdated
// keyIncludeHeaderFooter a bool value to indicate if the header and footer should be rendered
// keyIncludeHeaderFooter key to a bool value to indicate if the header and footer should be rendered
keyIncludeHeaderFooter string = "IncludeHeaderFooter"
// keyEntrypoint a bool value to indicate if the entrypoint to start with when parsing the document
// keyCSS key to the options CSS to add in the document head. Default is empty ("")
keyCSS string = "CSS"
// keyEntrypoint key to the entrypoint to start with when parsing the document
keyEntrypoint string = "Entrypoint"
// LastUpdatedFormat the time format for the `last updated` document attribute
// LastUpdatedFormat key to the time format for the `last updated` document attribute
LastUpdatedFormat string = "2006-01-02 15:04:05 -0700"
)

Expand All @@ -35,6 +37,13 @@ func IncludeHeaderFooter(value bool) Option {
}
}

// IncludeCSS function to set the `css` option in the renderer context
func IncludeCSS(href string) Option {
return func(ctx *Context) {
ctx.options[keyCSS] = href
}
}

// Entrypoint function to set the `entrypoint` option in the renderer context
func Entrypoint(entrypoint string) Option {
return func(ctx *Context) {
Expand All @@ -52,21 +61,26 @@ func DefineMacro(name string, t MacroTemplate) Option {
// LastUpdated returns the value of the 'LastUpdated' Option if it was present,
// otherwise it returns the current time using the `2006/01/02 15:04:05 MST` format
func (ctx *Context) LastUpdated() string {
if lastUpdated, found := ctx.options[keyLastUpdated]; found {
if lastUpdated, typeMatch := lastUpdated.(time.Time); typeMatch {
return lastUpdated.Format(LastUpdatedFormat)
}
if lastUpdated, ok := ctx.options[keyLastUpdated].(time.Time); ok {
return lastUpdated.Format(LastUpdatedFormat)
}
return time.Now().Format(LastUpdatedFormat)
}

// IncludeHeaderFooter returns the value of the 'IncludeHeaderFooter' Option if it was present,
// otherwise it returns `false`
func (ctx *Context) IncludeHeaderFooter() bool {
if includeHeaderFooter, found := ctx.options[keyIncludeHeaderFooter]; found {
if includeHeaderFooter, typeMatch := includeHeaderFooter.(bool); typeMatch {
return includeHeaderFooter
}
if includeHeaderFooter, ok := ctx.options[keyIncludeHeaderFooter].(bool); ok {
return includeHeaderFooter
}
return false
}

// CSS returns the value of the 'CSS' Option if it was present,
// otherwise it returns an empty string
func (ctx *Context) CSS() string {
if css, ok := ctx.options[keyCSS].(string); ok {
return css
}
return ""
}
7 changes: 5 additions & 2 deletions testsupport/html5_rendering_matcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,14 +145,16 @@ func (m *html5TitleMatcher) NegatedFailureMessage(_ interface{}) (message string
// ---------------------

// RenderHTML5Document a custom matcher to verify that a block renders as the expectation
func RenderHTML5Document(expected string, options ...interface{}) gomegatypes.GomegaMatcher {
func RenderHTML5Document(expected string, options ...renderer.Option) gomegatypes.GomegaMatcher {
m := &html5DocumentMatcher{
expected: expected,
options: options,
}
return m
}

type html5DocumentMatcher struct {
options []renderer.Option
expected string
actual string
}
Expand All @@ -163,7 +165,8 @@ func (m *html5DocumentMatcher) Match(actual interface{}) (success bool, err erro
return false, errors.Errorf("RenderHTML5Body matcher expects a string (actual: %T)", actual)
}
resultWriter := bytes.NewBuffer(nil)
_, err = libasciidoc.ConvertFileToHTML(filename, resultWriter, renderer.IncludeHeaderFooter(true))
m.options = append(m.options, renderer.IncludeHeaderFooter(true))
_, err = libasciidoc.ConvertFileToHTML(filename, resultWriter, m.options...)
if err != nil {
return false, err
}
Expand Down

0 comments on commit c1de2f2

Please sign in to comment.