mirror of
https://github.com/facundoolano/jorge.git
synced 2024-12-24 21:58:15 +01:00
Add a jorge meta command to get site metadata in scripts (#49)
Some checks failed
Test project / build (push) Has been cancelled
Some checks failed
Test project / build (push) Has been cancelled
* add a jorge meta command * add a basic metadata eval test * fix staticcheck
This commit is contained in:
parent
c252507af9
commit
2e5403d07f
5 changed files with 88 additions and 10 deletions
|
@ -49,3 +49,25 @@ func Prompt(label string) string {
|
|||
}
|
||||
return strings.TrimSpace(s)
|
||||
}
|
||||
|
||||
type Meta struct {
|
||||
Expression string `arg:"" name:"expression" default:"site" help:"liquid expression to be evaluated (what goes inside of {{ ... }} in templates)"`
|
||||
}
|
||||
|
||||
// Load the site metadata and use it as context to evaluate a liquid expression
|
||||
func (cmd *Meta) Run(ctx *kong.Context) error {
|
||||
|
||||
config, err := config.Load(".")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// remove optional {{}} wrapper
|
||||
expression := strings.Trim(cmd.Expression, " {}")
|
||||
|
||||
result, err := site.EvalMetadata(*config, expression)
|
||||
if err == nil {
|
||||
fmt.Println(result)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
|
1
main.go
1
main.go
|
@ -10,6 +10,7 @@ var cli struct {
|
|||
Build commands.Build `cmd:"" help:"Build a website project." aliases:"b"`
|
||||
Post commands.Post `cmd:"" help:"Initialize a new post template file." aliases:"p"`
|
||||
Serve commands.Serve `cmd:"" help:"Run a local server for the website." aliases:"s"`
|
||||
Meta commands.Meta `cmd:"" help:"Get the JSON results from evaluating a liquid template expression within the site context." aliases:"m"`
|
||||
Version kong.VersionFlag `short:"v"`
|
||||
}
|
||||
|
||||
|
|
|
@ -42,6 +42,11 @@ func NewEngine(siteUrl string, includesDir string) *Engine {
|
|||
return e
|
||||
}
|
||||
|
||||
func EvalExpression(engine *Engine, expression string, context map[string]interface{}) (string, error) {
|
||||
template := fmt.Sprintf("{{ %s | json }}", expression)
|
||||
return engine.ParseAndRenderString(template, context)
|
||||
}
|
||||
|
||||
// Try to parse a liquid template at the given location.
|
||||
// Files starting with front matter (--- sorrrounded yaml)
|
||||
// are considered templates. If the given file is not headed by front matter
|
||||
|
|
34
site/site.go
34
site/site.go
|
@ -49,6 +49,16 @@ func Build(config config.Config) error {
|
|||
return site.build()
|
||||
}
|
||||
|
||||
// Parse and render the given liquid expression, eg. " site.posts | map:title "
|
||||
// and return the results as a json string.
|
||||
func EvalMetadata(config config.Config, expression string) (string, error) {
|
||||
site, err := load(config)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return markup.EvalExpression(site.templateEngine, expression, site.AsContext())
|
||||
}
|
||||
|
||||
// Create a new site instance by scanning the project directories
|
||||
// pointed by `config`, loading layouts, templates and data files.
|
||||
func load(config config.Config) (*site, error) {
|
||||
|
@ -374,16 +384,7 @@ func (site *site) buildFile(path string) error {
|
|||
}
|
||||
|
||||
func (site *site) render(templ *markup.Template) ([]byte, error) {
|
||||
ctx := map[string]interface{}{
|
||||
"site": map[string]interface{}{
|
||||
"config": site.config.AsContext(),
|
||||
"posts": site.posts,
|
||||
"tags": site.tags,
|
||||
"pages": site.pages,
|
||||
"static_files": site.static_files,
|
||||
"data": site.data,
|
||||
},
|
||||
}
|
||||
ctx := site.AsContext()
|
||||
|
||||
ctx["page"] = templ.Metadata
|
||||
content, err := templ.RenderWith(ctx, site.config.HighlightTheme)
|
||||
|
@ -410,6 +411,19 @@ func (site *site) render(templ *markup.Template) ([]byte, error) {
|
|||
return content, nil
|
||||
}
|
||||
|
||||
func (site *site) AsContext() map[string]interface{} {
|
||||
return map[string]interface{}{
|
||||
"site": map[string]interface{}{
|
||||
"config": site.config.AsContext(),
|
||||
"posts": site.posts,
|
||||
"tags": site.tags,
|
||||
"pages": site.pages,
|
||||
"static_files": site.static_files,
|
||||
"data": site.data,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func checkFileError(err error) error {
|
||||
// When walking the source dir it can happen that a file is present when walking starts
|
||||
// but missing or inaccessible when trying to open it (this is particularly frequent with
|
||||
|
|
|
@ -271,6 +271,42 @@ date: 2023-01-01
|
|||
</ul>`)
|
||||
}
|
||||
|
||||
func TestEvalMetadata(t *testing.T) {
|
||||
config := newProject()
|
||||
defer os.RemoveAll(config.RootDir)
|
||||
|
||||
content := `---
|
||||
title: hello world!
|
||||
date: 2024-01-01
|
||||
---
|
||||
<p>Hello world!</p>`
|
||||
file := newFile(config.SrcDir, "hello.html", content)
|
||||
defer os.Remove(file.Name())
|
||||
|
||||
content = `---
|
||||
title: goodbye!
|
||||
date: 2024-02-01
|
||||
---
|
||||
<p>goodbye world!</p>`
|
||||
file = newFile(config.SrcDir, "goodbye.html", content)
|
||||
defer os.Remove(file.Name())
|
||||
|
||||
content = `---
|
||||
title: an oldie!
|
||||
date: 2023-01-01
|
||||
---
|
||||
<p>oldie</p>`
|
||||
file = newFile(config.SrcDir, "an-oldie.html", content)
|
||||
defer os.Remove(file.Name())
|
||||
|
||||
output, err := EvalMetadata(*config, "site.posts | map:'title'")
|
||||
assertEqual(t, err, nil)
|
||||
assertEqual(t, output, `["goodbye!","hello world!","an oldie!"]`)
|
||||
|
||||
_, err = EvalMetadata(*config, "site.posts | map:'title")
|
||||
assert(t, strings.Contains(err.Error(), "Liquid error"))
|
||||
}
|
||||
|
||||
func TestRenderTags(t *testing.T) {
|
||||
config := newProject()
|
||||
defer os.RemoveAll(config.RootDir)
|
||||
|
|
Loading…
Reference in a new issue