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)
|
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"`
|
Build commands.Build `cmd:"" help:"Build a website project." aliases:"b"`
|
||||||
Post commands.Post `cmd:"" help:"Initialize a new post template file." aliases:"p"`
|
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"`
|
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"`
|
Version kong.VersionFlag `short:"v"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,11 @@ func NewEngine(siteUrl string, includesDir string) *Engine {
|
||||||
return e
|
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.
|
// Try to parse a liquid template at the given location.
|
||||||
// Files starting with front matter (--- sorrrounded yaml)
|
// Files starting with front matter (--- sorrrounded yaml)
|
||||||
// are considered templates. If the given file is not headed by front matter
|
// 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()
|
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
|
// Create a new site instance by scanning the project directories
|
||||||
// pointed by `config`, loading layouts, templates and data files.
|
// pointed by `config`, loading layouts, templates and data files.
|
||||||
func load(config config.Config) (*site, error) {
|
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) {
|
func (site *site) render(templ *markup.Template) ([]byte, error) {
|
||||||
ctx := map[string]interface{}{
|
ctx := site.AsContext()
|
||||||
"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["page"] = templ.Metadata
|
ctx["page"] = templ.Metadata
|
||||||
content, err := templ.RenderWith(ctx, site.config.HighlightTheme)
|
content, err := templ.RenderWith(ctx, site.config.HighlightTheme)
|
||||||
|
@ -410,6 +411,19 @@ func (site *site) render(templ *markup.Template) ([]byte, error) {
|
||||||
return content, nil
|
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 {
|
func checkFileError(err error) error {
|
||||||
// When walking the source dir it can happen that a file is present when walking starts
|
// 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
|
// but missing or inaccessible when trying to open it (this is particularly frequent with
|
||||||
|
|
|
@ -271,6 +271,42 @@ date: 2023-01-01
|
||||||
</ul>`)
|
</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) {
|
func TestRenderTags(t *testing.T) {
|
||||||
config := newProject()
|
config := newProject()
|
||||||
defer os.RemoveAll(config.RootDir)
|
defer os.RemoveAll(config.RootDir)
|
||||||
|
|
Loading…
Reference in a new issue