1
0
mirror of https://github.com/danog/gojekyll.git synced 2024-11-26 17:24:42 +01:00

Use template.SetSourceLocation instead of adding fake whitespace

This commit is contained in:
Oliver Steele 2017-07-09 11:57:20 -04:00
parent bec42f24d7
commit ad59c0239d
7 changed files with 39 additions and 32 deletions

View File

@ -24,7 +24,7 @@ Gojekyll is a clone of the [Jekyll](https://jekyllrb.com) static site generator,
First-time install:
1. [Install go](https://golang.org/doc/install#install). On macOS running Homebrew, `brew install go` is easier than the linked instructions.
1. [Install go](https://golang.org/doc/install#install). (On macOS running [Homebrew](https://brew.sh), `brew install go` is easier than the Install instructions on the Go site.)
2. `go get osteele/gojekyll/cmd/gojekyll`
3. To use the `{% highlight %}` tag, you need Pygments. `pip install Pygments`.
@ -36,7 +36,7 @@ Update to the latest version:
```bash
gojekyll build # builds the site in the current directory into _site
gojekyll serve # serve the app at http://localhost:4000
gojekyll serve # serve the app at http://localhost:4000; reload on changes
gojekyll help
gojekyll help build
```

View File

@ -12,6 +12,7 @@ import (
// FrontMatter wraps a map to provide interface functions
type FrontMatter map[string]interface{}
// The first four bytes of a file with front matter.
const fmMagic = "---\n"
// FileHasFrontMatter returns a bool indicating whether the

View File

@ -1,9 +1,11 @@
package templates
package frontmatter
import (
"bytes"
"regexp"
"github.com/osteele/gojekyll/templates"
yaml "gopkg.in/yaml.v2"
)
@ -12,13 +14,14 @@ var (
emptyFontMatterMatcher = regexp.MustCompile(`(?s)^---\n+---\n`)
)
// ReadFrontMatter reads the front matter from a document.
func ReadFrontMatter(sourcePtr *[]byte) (frontMatter VariableMap, err error) {
// Read reads the frontmatter from a document. It modifies srcPtr to point to the
// content after the frontmatter, and sets firstLine to its 1-indexed line number.
func Read(sourcePtr *[]byte, firstLine *int) (frontMatter templates.VariableMap, err error) {
var (
source = *sourcePtr
start = 0
)
// Replace Windows linefeeds. This allows the following regular expressions to work.
// Replace Windows line feeds. This allows the following regular expressions to work.
source = bytes.Replace(source, []byte("\r\n"), []byte("\n"), -1)
if match := frontMatterMatcher.FindSubmatchIndex(source); match != nil {
start = match[1]
@ -28,10 +31,9 @@ func ReadFrontMatter(sourcePtr *[]byte) (frontMatter VariableMap, err error) {
} else if match := emptyFontMatterMatcher.FindSubmatchIndex(source); match != nil {
start = match[1]
}
// This fixes the line numbers, so that template errors show with the correct line.
// TODO find a less hack-ey solution
*sourcePtr = append(
regexp.MustCompile(`[^\n\r]+`).ReplaceAllLiteral(source[:start], []byte{}),
source[start:]...)
if firstLine != nil {
*firstLine = 1 + bytes.Count(source[:start], []byte("\n"))
}
*sourcePtr = source[start:]
return
}

View File

@ -7,6 +7,7 @@ import (
"io/ioutil"
"time"
"github.com/osteele/gojekyll/frontmatter"
"github.com/osteele/gojekyll/templates"
"github.com/osteele/liquid/evaluator"
)
@ -27,8 +28,9 @@ type Page interface {
type page struct {
file
raw []byte
content *[]byte
firstLine int
raw []byte
content *[]byte
}
// Static is in the File interface.
@ -39,15 +41,16 @@ func makePage(filename string, f file) (*page, error) {
if err != nil {
return nil, err
}
frontMatter, err := templates.ReadFrontMatter(&b)
lineNo := 1
frontMatter, err := frontmatter.Read(&b, &lineNo)
if err != nil {
return nil, err
}
f.frontMatter = templates.MergeVariableMaps(f.frontMatter, frontMatter)
p := page{
file: f,
raw: b,
file: f,
firstLine: lineNo,
raw: b,
}
if err = p.setPermalink(); err != nil {
return nil, err
@ -106,7 +109,7 @@ func (p *page) Content(rc RenderingContext) ([]byte, error) {
if p.content == nil {
rp := rc.RenderingPipeline()
buf := new(bytes.Buffer)
b, err := rp.Render(buf, p.raw, p.filename, p.TemplateContext(rc))
b, err := rp.Render(buf, p.raw, p.filename, p.firstLine, p.TemplateContext(rc))
if err != nil {
return nil, err
}

View File

@ -17,14 +17,14 @@ type renderingContextFake struct {
func (c renderingContextFake) RenderingPipeline() pipelines.PipelineInterface { return c }
func (c renderingContextFake) Config() config.Config { return c.cfg }
func (c renderingContextFake) PathPrefix() string { return "." }
func (c renderingContextFake) PathPrefix() string { return "." }
func (c renderingContextFake) OutputExt(string) string { return ".html" }
func (c renderingContextFake) Site() interface{} { return nil }
func (c renderingContextFake) ApplyLayout(layout string, src []byte, vars map[string]interface{}) ([]byte, error) {
require.Equal(c.t, "layout1", layout)
return nil, nil
}
func (c renderingContextFake) Render(w io.Writer, src []byte, filename string, vars map[string]interface{}) ([]byte, error) {
func (c renderingContextFake) Render(w io.Writer, src []byte, filename string, lineNo int, vars map[string]interface{}) ([]byte, error) {
require.Equal(c.t, "testdata/page_with_layout.md", filename)
return nil, nil
}

View File

@ -7,12 +7,12 @@ import (
"path/filepath"
"strings"
"github.com/osteele/gojekyll/templates"
"github.com/osteele/gojekyll/frontmatter"
"github.com/osteele/liquid"
)
// FindLayout returns a template for the named layout.
func (p *Pipeline) FindLayout(base string, fm *map[string]interface{}) (t liquid.Template, err error) {
func (p *Pipeline) FindLayout(base string, fm *map[string]interface{}) (tpl liquid.Template, err error) {
exts := []string{"", ".html"}
for _, ext := range strings.SplitN(p.config.MarkdownExt, `,`, -1) {
exts = append(exts, "."+ext)
@ -37,15 +37,16 @@ func (p *Pipeline) FindLayout(base string, fm *map[string]interface{}) (t liquid
if !found {
return nil, fmt.Errorf("no template for %s", base)
}
*fm, err = templates.ReadFrontMatter(&content)
lineNo := 1
*fm, err = frontmatter.Read(&content, &lineNo)
if err != nil {
return
}
t, err = p.liquidEngine.ParseTemplate(content)
tpl, err = p.liquidEngine.ParseTemplate(content)
if err != nil {
return nil, err
}
t.SetSourcePath(filename)
tpl.SetSourceLocation(filename, lineNo)
return
}

View File

@ -16,7 +16,7 @@ import (
type PipelineInterface interface {
ApplyLayout(string, []byte, map[string]interface{}) ([]byte, error)
OutputExt(pathname string) string
Render(io.Writer, []byte, string, map[string]interface{}) ([]byte, error)
Render(io.Writer, []byte, string, int, map[string]interface{}) ([]byte, error)
}
// Pipeline applies a rendering transformation to a file.
@ -59,11 +59,11 @@ func (p *Pipeline) OutputExt(pathname string) string {
}
// Render returns nil iff it wrote to the writer
func (p *Pipeline) Render(w io.Writer, b []byte, filename string, e map[string]interface{}) ([]byte, error) {
func (p *Pipeline) Render(w io.Writer, b []byte, filename string, lineNo int, e map[string]interface{}) ([]byte, error) {
if p.config.IsSASSPath(filename) {
return nil, p.WriteSass(w, b)
}
b, err := p.renderTemplate(b, e, filename)
b, err := p.renderTemplate(b, e, filename, lineNo)
if err != nil {
return nil, err
}
@ -73,12 +73,12 @@ func (p *Pipeline) Render(w io.Writer, b []byte, filename string, e map[string]i
return b, nil
}
func (p *Pipeline) renderTemplate(src []byte, b map[string]interface{}, filename string) ([]byte, error) {
func (p *Pipeline) renderTemplate(src []byte, b map[string]interface{}, filename string, lineNo int) ([]byte, error) {
tpl, err := p.liquidEngine.ParseTemplate(src)
if err != nil {
return nil, helpers.PathError(err, "Liquid Error", filename)
}
tpl.SetSourcePath(filename)
tpl.SetSourceLocation(filename, lineNo)
out, err := tpl.Render(b)
if err != nil {
return nil, helpers.PathError(err, "Liquid Error", filename)
@ -90,7 +90,7 @@ func (p *Pipeline) renderTemplate(src []byte, b map[string]interface{}, filename
func (p *Pipeline) ApplyLayout(name string, data []byte, e map[string]interface{}) ([]byte, error) {
for name != "" {
var lfm map[string]interface{}
t, err := p.FindLayout(name, &lfm)
tpl, err := p.FindLayout(name, &lfm)
if err != nil {
return nil, err
}
@ -98,7 +98,7 @@ func (p *Pipeline) ApplyLayout(name string, data []byte, e map[string]interface{
"content": string(data),
"layout": lfm,
})
data, err = t.Render(b)
data, err = tpl.Render(b)
if err != nil {
return nil, helpers.PathError(err, "render template", name)
}