1
0
mirror of https://github.com/danog/gojekyll.git synced 2024-11-27 08:44:41 +01:00
gojekyll/pipelines/pipeline.go

122 lines
3.2 KiB
Go
Raw Normal View History

2017-06-24 20:00:19 +02:00
package pipelines
2017-06-24 19:30:01 +02:00
import (
2017-07-09 20:31:47 +02:00
"bytes"
2017-06-24 19:30:01 +02:00
"io"
"github.com/osteele/gojekyll/config"
2017-07-01 01:40:52 +02:00
"github.com/osteele/gojekyll/filters"
"github.com/osteele/gojekyll/tags"
2017-06-24 19:30:01 +02:00
"github.com/osteele/gojekyll/templates"
2017-07-09 22:17:20 +02:00
"github.com/osteele/gojekyll/utils"
2017-07-01 01:37:31 +02:00
"github.com/osteele/liquid"
2017-06-24 19:30:01 +02:00
"github.com/russross/blackfriday"
)
2017-06-24 20:00:19 +02:00
// PipelineInterface applies transformations to a document.
type PipelineInterface interface {
2017-07-01 05:56:29 +02:00
ApplyLayout(string, []byte, map[string]interface{}) ([]byte, error)
2017-06-24 20:00:19 +02:00
OutputExt(pathname string) string
Render(io.Writer, []byte, string, int, map[string]interface{}) ([]byte, error)
2017-06-24 20:00:19 +02:00
}
2017-06-24 19:30:01 +02:00
// Pipeline applies a rendering transformation to a file.
type Pipeline struct {
PipelineOptions
2017-06-24 19:30:01 +02:00
config config.Config
liquidEngine *liquid.Engine
2017-06-24 19:30:01 +02:00
sassTempDir string
2017-07-10 00:19:22 +02:00
sassHash string
2017-06-24 19:30:01 +02:00
}
// PipelineOptions configures a pipeline.
type PipelineOptions struct {
2017-07-01 01:37:31 +02:00
RelativeFilenameToURL tags.LinkTagHandler
2017-06-24 19:30:01 +02:00
}
// NewPipeline makes a rendering pipeline.
func NewPipeline(c config.Config, options PipelineOptions) (*Pipeline, error) {
p := Pipeline{PipelineOptions: options, config: c}
2017-06-29 13:27:43 +02:00
p.liquidEngine = p.makeLiquidEngine()
2017-06-24 19:30:01 +02:00
if err := p.CopySassFileIncludes(); err != nil {
return nil, err
}
return &p, nil
}
2017-07-01 05:10:58 +02:00
// SourceDir returns the site source directory. Seeing how far we can bend
// the Law of Demeter.
2017-07-01 03:06:12 +02:00
func (p *Pipeline) SourceDir() string {
return p.config.Source
}
2017-07-01 01:40:52 +02:00
// TemplateEngine returns the Liquid engine.
func (p *Pipeline) TemplateEngine() *liquid.Engine {
2017-06-30 18:53:34 +02:00
return p.liquidEngine
}
2017-06-24 19:30:01 +02:00
// OutputExt returns the output extension.
func (p *Pipeline) OutputExt(pathname string) string {
return p.config.OutputExt(pathname)
}
// Render returns nil iff it wrote to the writer
func (p *Pipeline) Render(w io.Writer, b []byte, filename string, lineNo int, e map[string]interface{}) ([]byte, error) {
2017-07-09 15:37:23 +02:00
if p.config.IsSASSPath(filename) {
2017-07-09 20:31:47 +02:00
buf := new(bytes.Buffer)
if err := p.WriteSass(buf, b); err != nil {
return nil, err
}
return buf.Bytes(), nil
2017-06-24 19:30:01 +02:00
}
b, err := p.renderTemplate(b, e, filename, lineNo)
2017-06-24 19:30:01 +02:00
if err != nil {
return nil, err
}
if p.config.IsMarkdown(filename) {
b = blackfriday.MarkdownCommon(b)
}
return b, nil
}
func (p *Pipeline) renderTemplate(src []byte, b map[string]interface{}, filename string, lineNo int) ([]byte, error) {
2017-07-04 23:13:47 +02:00
tpl, err := p.liquidEngine.ParseTemplate(src)
if err != nil {
return nil, utils.WrapPathError(err, filename)
2017-07-04 23:13:47 +02:00
}
tpl.SetSourceLocation(filename, lineNo)
2017-07-04 23:13:47 +02:00
out, err := tpl.Render(b)
2017-06-24 19:30:01 +02:00
if err != nil {
return nil, utils.WrapPathError(err, filename)
2017-06-24 19:30:01 +02:00
}
2017-07-02 05:54:12 +02:00
return out, err
2017-06-24 19:30:01 +02:00
}
// ApplyLayout applies the named layout to the data.
2017-07-01 05:56:29 +02:00
func (p *Pipeline) ApplyLayout(name string, data []byte, e map[string]interface{}) ([]byte, error) {
2017-06-24 19:30:01 +02:00
for name != "" {
2017-07-01 05:56:29 +02:00
var lfm map[string]interface{}
tpl, err := p.FindLayout(name, &lfm)
2017-06-24 19:30:01 +02:00
if err != nil {
return nil, err
}
2017-07-09 22:17:20 +02:00
b := utils.MergeStringMaps(e, map[string]interface{}{
"content": string(data),
2017-06-24 19:30:01 +02:00
"layout": lfm,
})
data, err = tpl.Render(b)
2017-06-24 19:30:01 +02:00
if err != nil {
return nil, utils.WrapPathError(err, name)
2017-06-24 19:30:01 +02:00
}
2017-07-01 05:56:29 +02:00
name = templates.VariableMap(lfm).String("layout", "")
2017-06-24 19:30:01 +02:00
}
return data, nil
2017-06-24 19:30:01 +02:00
}
func (p *Pipeline) makeLiquidEngine() *liquid.Engine {
2017-06-29 13:27:43 +02:00
engine := liquid.NewEngine()
filters.AddJekyllFilters(engine, &p.config)
tags.AddJekyllTags(engine, &p.config, p.RelativeFilenameToURL)
2017-06-24 19:30:01 +02:00
return engine
}