Skip to content

Commit 2e00816

Browse files
committed
[pandoc] Allow page parameters to override site parameters.
This allows specifying things like this in the page frontmatter: --- title: Something bibliography: source: mybibliography.bib pandoc: filter: - make-diagrams.lua ... These options are local to the page. Specifying the same under `markup` in the site configuration applies those settings to all pages. Paths (filters, bibliography, citation style) are resolved relative to the page, site, and the `static` folder.
1 parent ba5638d commit 2e00816

File tree

2 files changed

+93
-21
lines changed

2 files changed

+93
-21
lines changed

Diff for: markup/pandoc/convert.go

+72-14
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,50 @@
1515
package pandoc
1616

1717
import (
18+
"strings"
19+
1820
"github.com/cli/safeexec"
1921
"github.com/gohugoio/hugo/htesting"
22+
"github.com/mitchellh/mapstructure"
2023

2124
"github.com/gohugoio/hugo/identity"
25+
"github.com/gohugoio/hugo/markup/bibliography"
2226
"github.com/gohugoio/hugo/markup/internal"
27+
"github.com/gohugoio/hugo/markup/pandoc/pandoc_config"
2328

2429
"github.com/gohugoio/hugo/markup/converter"
2530

31+
"fmt"
32+
"os"
2633
"path"
2734
)
2835

36+
type paramer interface {
37+
Param(interface{}) (interface{}, error)
38+
}
39+
40+
type searchPaths struct {
41+
Paths []string
42+
}
43+
44+
func (s *searchPaths) NormalizePath(in_path string) (string, error) {
45+
if path.IsAbs(in_path) {
46+
return in_path, nil
47+
}
48+
49+
for _, p := range s.Paths {
50+
fp := path.Join(p, in_path)
51+
if _, err := os.Stat(fp); err == nil {
52+
return fp, nil
53+
}
54+
}
55+
return "", fmt.Errorf("Can't find %s", in_path)
56+
}
57+
58+
func (s *searchPaths) AsResourcePath() string {
59+
return strings.Join(s.Paths, ":")
60+
}
61+
2962
// Provider is the package entry point.
3063
var Provider converter.ProviderProvider = provider{}
3164

@@ -35,27 +68,27 @@ type provider struct {
3568
func (p provider) New(cfg converter.ProviderConfig) (converter.Provider, error) {
3669
return converter.NewProvider("pandoc", func(ctx converter.DocumentContext) (converter.Converter, error) {
3770
return &pandocConverter{
38-
ctx: ctx,
39-
cfg: cfg,
71+
docCtx: ctx,
72+
cfg: cfg,
4073
}, nil
4174
}), nil
4275
}
4376

4477
type pandocConverter struct {
45-
ctx converter.DocumentContext
46-
cfg converter.ProviderConfig
78+
docCtx converter.DocumentContext
79+
cfg converter.ProviderConfig
4780
}
4881

4982
func (c *pandocConverter) Convert(ctx converter.RenderContext) (converter.Result, error) {
50-
return converter.Bytes(c.getPandocContent(ctx.Src, c.ctx)), nil
83+
return converter.Bytes(c.getPandocContent(ctx.Src)), nil
5184
}
5285

5386
func (c *pandocConverter) Supports(feature identity.Identity) bool {
5487
return false
5588
}
5689

5790
// getPandocContent calls pandoc as an external helper to convert pandoc markdown to HTML.
58-
func (c *pandocConverter) getPandocContent(src []byte, ctx converter.DocumentContext) []byte {
91+
func (c *pandocConverter) getPandocContent(src []byte) []byte {
5992
logger := c.cfg.Logger
6093
pandoc_path := getPandocExecPath()
6194
if pandoc_path == "" {
@@ -64,21 +97,46 @@ func (c *pandocConverter) getPandocContent(src []byte, ctx converter.DocumentCon
6497
return src
6598
}
6699

67-
arguments := c.cfg.MarkupConfig.Pandoc.AsPandocArguments()
100+
searchPathSet := searchPaths{
101+
Paths: []string{path.Dir(c.docCtx.Filename), "static", "."},
102+
}
103+
104+
var pandocConfig pandoc_config.Config = c.cfg.MarkupConfig.Pandoc
105+
var bibConfig bibliography.Config = c.cfg.MarkupConfig.Bibliography
106+
107+
if pageParameters, ok := c.docCtx.Document.(paramer); ok {
108+
if bibParam, err := pageParameters.Param("bibliography"); err == nil {
109+
mapstructure.WeakDecode(bibParam, &bibConfig)
110+
}
111+
112+
if pandocParam, err := pageParameters.Param("pandoc"); err == nil {
113+
mapstructure.WeakDecode(pandocParam, &pandocConfig)
114+
}
115+
}
68116

69-
bibliography := c.cfg.MarkupConfig.Bibliography
117+
arguments := pandocConfig.AsPandocArguments(&searchPathSet)
70118

71-
if bibliography.Source != "" {
72-
arguments = append(arguments, "--bibliography", bibliography.Source)
119+
if bibConfig.Source != "" {
120+
sourcePath, err := searchPathSet.NormalizePath(bibConfig.Source)
121+
if err != nil {
122+
logger.Errorf("Can't find bibliography: %s", bibConfig.Source)
123+
} else {
124+
arguments = append(arguments, "--bibliography", sourcePath)
125+
}
73126
}
74127

75-
if bibliography.CitationStyle != "" {
76-
arguments = append(arguments, "--csl", bibliography.CitationStyle)
128+
if bibConfig.CitationStyle != "" {
129+
citationPath, err := searchPathSet.NormalizePath(bibConfig.CitationStyle)
130+
if err != nil {
131+
logger.Errorf("Can't find citation style: %s", bibConfig.CitationStyle)
132+
} else {
133+
arguments = append(arguments, "--csl", citationPath)
134+
}
77135
}
78136

79-
arguments = append(arguments, "--resource-path", path.Dir(ctx.Filename))
137+
arguments = append(arguments, "--resource-path", searchPathSet.AsResourcePath())
80138

81-
return internal.ExternallyRenderContent(c.cfg, ctx, src, pandoc_path, arguments)
139+
return internal.ExternallyRenderContent(c.cfg, c.docCtx, src, pandoc_path, arguments)
82140
}
83141

84142
func getPandocExecPath() string {

Diff for: markup/pandoc/pandoc_config/pandoc.go

+21-7
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,11 @@ type Config struct {
3535
// See https://pandoc.org/MANUAL.html#math-rendering-in-html
3636
UseKatex bool
3737

38-
// List of filters to use. These translate to '--filter=' arguments to the
39-
// pandoc invocation. The order of elements in `Filters` is preserved when
40-
// constructing the `pandoc` commandline.
38+
// List of filters to use. These translate to '--filter=' or '--lua-filter'
39+
// arguments to the pandoc invocation. The order of elements in `Filters`
40+
// is preserved when constructing the `pandoc` commandline.
41+
//
42+
// Use the prefix 'lua:' or the suffix '.lua' to indicate Lua filters.
4143
Filters []string
4244

4345
// List of Pandoc Markdown extensions to use. No need to include default
@@ -109,25 +111,37 @@ func (c *Config) getMathRenderingArg() string {
109111
}
110112
}
111113

112-
func (c *Config) getFilterArgs() []string {
114+
func (c *Config) getFilterArgs(pathLookup PathNormalizer) []string {
113115
var args []string
114116
for _, filter := range c.Filters {
115-
args = append(args, fmt.Sprintf("--filter=%s", filter))
117+
filterPath, err := pathLookup.NormalizePath(filter)
118+
if err != nil {
119+
continue
120+
}
121+
if strings.HasPrefix(filterPath, "lua:") || strings.HasSuffix(filterPath, ".lua") {
122+
args = append(args, fmt.Sprintf("--lua-filter=%s", strings.TrimPrefix(filterPath, "lua:")))
123+
} else {
124+
args = append(args, fmt.Sprintf("--filter=%s", filterPath))
125+
}
116126
}
117127
return args
118128
}
119129

120130
// AsPandocArguments returns a list of strings that can be used as arguments to
121131
// a "pandoc" invocation. All the settings contained in Config are represented
122132
// in the returned list of arguments.
123-
func (c *Config) AsPandocArguments() []string {
133+
func (c *Config) AsPandocArguments(pathLookup PathNormalizer) []string {
124134
args := []string{
125135
c.getInputArg(),
126136
c.getOutputArg(),
127137
c.getMathRenderingArg()}
128138

129-
args = append(args, c.getFilterArgs()...)
139+
args = append(args, c.getFilterArgs(pathLookup)...)
130140
args = append(args, c.ExtraArgs...)
131141

132142
return args
133143
}
144+
145+
type PathNormalizer interface {
146+
NormalizePath(string) (string, error)
147+
}

0 commit comments

Comments
 (0)