Adds customization to the bottom metadata

Fix #87
This commit is contained in:
Eduardo Cuducos
2021-08-06 13:44:02 -04:00
committed by Maas Lalani
parent 45ea575822
commit 74d6d19a30
4 changed files with 160 additions and 25 deletions

View File

@@ -1,10 +1,8 @@
package cmd
import (
"errors"
"fmt"
"os"
"os/user"
"time"
tea "github.com/charmbracelet/bubbletea"
@@ -24,14 +22,8 @@ var root = &cobra.Command{
fileName = args[0]
}
user, err := user.Current()
if err != nil {
return errors.New("could not get current user")
}
presentation := model.Model{
Page: 0,
Author: user.Name,
Date: time.Now().Format("2006-01-02"),
FileName: fileName,
}

View File

@@ -3,22 +3,28 @@
package meta
import (
"os/user"
"gopkg.in/yaml.v2"
)
const defaultTheme = "default"
// Temporary structure to differentiate values not present in the YAML header
// from values set to empty strings in the YAML header. We replace values not
// set by defaults values when parsing a header.
type parsedMeta struct {
Theme *string `yaml:"theme"`
Theme *string `yaml:"theme"`
Author *string `yaml:"author"`
Date *string `yaml:"date"`
Numbering *string `yaml:"numbering"`
}
// Meta contains all of the data to be parsed
// out of a markdown file's header section
type Meta struct {
Theme string
Theme string
Author string
Date string
Numbering string
}
// New creates a new instance of the
@@ -33,7 +39,12 @@ func New() *Meta {
// If no front matter is provided, it will fallback to the default theme and
// return false to acknowledge that there is no front matter in this slide
func (m *Meta) Parse(header string) (*Meta, bool) {
fallback := &Meta{Theme: defaultTheme}
fallback := &Meta{
Theme: defaultTheme(),
Author: defaultAuthor(),
Date: defaultDate(),
Numbering: defaultNumbering(),
}
var tmp parsedMeta
err := yaml.Unmarshal([]byte(header), &tmp)
@@ -47,5 +58,44 @@ func (m *Meta) Parse(header string) (*Meta, bool) {
m.Theme = fallback.Theme
}
if tmp.Author != nil {
m.Author = *tmp.Author
} else {
m.Author = fallback.Author
}
if tmp.Date != nil {
m.Date = *tmp.Date
} else {
m.Date = fallback.Date
}
if tmp.Numbering != nil {
m.Numbering = *tmp.Numbering
} else {
m.Numbering = fallback.Numbering
}
return m, true
}
func defaultTheme() string {
return "default"
}
func defaultAuthor() string {
user, err := user.Current()
if err != nil {
return ""
}
return user.Name
}
func defaultDate() string {
return "2006-01-02"
}
func defaultNumbering() string {
return "Slide %d / %d"
}

View File

@@ -2,6 +2,7 @@ package meta_test
import (
"fmt"
"os/user"
"testing"
"github.com/maaslalani/slides/internal/meta"
@@ -9,6 +10,9 @@ import (
)
func TestMeta_ParseHeader(t *testing.T) {
user, _ := user.Current()
date := "2006-01-02"
tests := []struct {
name string
slideshow string
@@ -18,21 +22,90 @@ func TestMeta_ParseHeader(t *testing.T) {
name: "Parse theme from header",
slideshow: fmt.Sprintf("---\ntheme: %q\n", "dark"),
want: &meta.Meta{
Theme: "dark",
Theme: "dark",
Author: user.Name,
Date: date,
Numbering: "Slide %d / %d",
},
},
{
name: "Fallback to default if no theme provided",
slideshow: "\n# Header Slide\n > Subtitle\n",
want: &meta.Meta{
Theme: "default",
Theme: "default",
Author: user.Name,
Date: date,
Numbering: "Slide %d / %d",
},
},
{
name: "Parse author from header",
slideshow: fmt.Sprintf("---\nauthor: %q\n", "gopher"),
want: &meta.Meta{
Theme: "default",
Author: "gopher",
Date: date,
Numbering: "Slide %d / %d",
},
},
{
name: "Fallback to default if no author provided",
slideshow: "\n# Header Slide\n > Subtitle\n",
want: &meta.Meta{
Theme: "default",
Author: user.Name,
Date: date,
Numbering: "Slide %d / %d",
},
},
{
name: "Parse date from header",
slideshow: fmt.Sprintf("---\ndate: %q\n", "31/01/1970"),
want: &meta.Meta{
Theme: "default",
Author: user.Name,
Date: "31/01/1970",
Numbering: "Slide %d / %d",
},
},
{
name: "Fallback to default if no date provided",
slideshow: "\n# Header Slide\n > Subtitle\n",
want: &meta.Meta{
Theme: "default",
Author: user.Name,
Date: date,
Numbering: "Slide %d / %d",
},
},
{
name: "Parse numbering from header",
slideshow: fmt.Sprintf("---\nnumbering: %q\n", "%d of %d"),
want: &meta.Meta{
Theme: "default",
Author: user.Name,
Date: date,
Numbering: "%d of %d",
},
},
{
name: "Fallback to default if no numebring provided",
slideshow: "\n# Header Slide\n > Subtitle\n",
want: &meta.Meta{
Theme: "default",
Author: user.Name,
Date: date,
Numbering: "Slide %d / %d",
},
},
{
name: "Fallback if first slide is valid yaml",
slideshow: "---\n# Header Slide---\nContent\n",
want: &meta.Meta{
Theme: "default",
Theme: "default",
Author: user.Name,
Date: date,
Numbering: "Slide %d / %d",
},
},
}
@@ -67,6 +140,9 @@ func ExampleMeta_Parse() {
header := `
---
theme: "dark"
author: "Gopher"
date: "Apr. 4, 2021"
numbering: "%d"
---
`
// Parse the header from the markdown
@@ -76,4 +152,7 @@ theme: "dark"
// Print the return theme
// meta
fmt.Println(m.Theme)
fmt.Println(m.Author)
fmt.Println(m.Date)
fmt.Println(m.Numbering)
}

View File

@@ -25,13 +25,14 @@ const (
)
type Model struct {
Slides []string
Page int
Author string
Date string
Theme glamour.TermRendererOption
FileName string
viewport viewport.Model
Slides []string
Page int
Author string
Date string
Theme glamour.TermRendererOption
Numbering string
FileName string
viewport viewport.Model
// VirtualText is used for additional information that is not part of the
// original slides, it will be displayed on a slide and reset on page change
VirtualText string
@@ -80,6 +81,9 @@ func (m *Model) Load() error {
}
m.Slides = slides
m.Author = metaData.Author
m.Date = time.Now().Format(metaData.Date)
m.Numbering = metaData.Numbering
if m.Theme == nil {
m.Theme = styles.SelectTheme(metaData.Theme)
}
@@ -145,11 +149,22 @@ func (m Model) View() string {
slide = styles.Slide.Render(slide)
left := styles.Author.Render(m.Author) + styles.Date.Render(m.Date)
right := styles.Page.Render(fmt.Sprintf("Slide %d / %d", m.Page+1, len(m.Slides)))
right := styles.Page.Render(m.numbering())
status := styles.Status.Render(styles.JoinHorizontal(left, right, m.viewport.Width))
return styles.JoinVertical(slide, status, m.viewport.Height)
}
func (m *Model) numbering() string {
switch strings.Count(m.Numbering, "%d") {
case 2:
return fmt.Sprintf(m.Numbering, m.Page+1, len(m.Slides))
case 1:
return fmt.Sprintf(m.Numbering, m.Page+1)
default:
return m.Numbering
}
}
func readFile(path string) (string, error) {
s, err := os.Stat(path)
if err != nil {
@@ -164,7 +179,6 @@ func readFile(path string) (string, error) {
}
content := string(b)
// Pre-process slides if the file is executable to avoid
// unintentional code execution when presenting slides
if file.IsExecutable(s) {