2021-01-19 20:05:16 +00:00
|
|
|
package note
|
|
|
|
|
|
|
|
import (
|
|
|
|
"path/filepath"
|
|
|
|
"regexp"
|
|
|
|
"strings"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/mickael-menu/zk/core/style"
|
|
|
|
"github.com/mickael-menu/zk/core/templ"
|
|
|
|
"github.com/mickael-menu/zk/util/opt"
|
|
|
|
)
|
|
|
|
|
|
|
|
// Formatter formats notes to be printed on the screen.
|
|
|
|
type Formatter struct {
|
|
|
|
basePath string
|
|
|
|
currentPath string
|
|
|
|
renderer templ.Renderer
|
|
|
|
// Regex replacement for a term marked in a snippet.
|
|
|
|
snippetTermReplacement string
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewFormatter creates a Formatter from a given format template.
|
|
|
|
//
|
2021-02-15 21:44:31 +00:00
|
|
|
// The absolute path to the notebook (basePath) and the working directory
|
2021-01-19 20:05:16 +00:00
|
|
|
// (currentPath) are used to make the path of each note relative to the working
|
|
|
|
// directory.
|
|
|
|
func NewFormatter(basePath string, currentPath string, format opt.String, templates templ.Loader, styler style.Styler) (*Formatter, error) {
|
|
|
|
template := resolveFormatTemplate(format)
|
|
|
|
renderer, err := templates.Load(template)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
termRepl, err := styler.Style("$1", style.RuleTerm)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return &Formatter{
|
|
|
|
basePath: basePath,
|
|
|
|
currentPath: currentPath,
|
|
|
|
renderer: renderer,
|
|
|
|
snippetTermReplacement: termRepl,
|
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func resolveFormatTemplate(format opt.String) string {
|
2021-02-11 20:31:47 +00:00
|
|
|
templ, ok := formatTemplates[format.OrString("short").Unwrap()]
|
2021-01-19 20:05:16 +00:00
|
|
|
if !ok {
|
|
|
|
templ = format.String()
|
|
|
|
// Replace raw \n and \t by actual newlines and tabs in user format.
|
|
|
|
templ = strings.ReplaceAll(templ, "\\n", "\n")
|
|
|
|
templ = strings.ReplaceAll(templ, "\\t", "\t")
|
|
|
|
}
|
|
|
|
return templ
|
|
|
|
}
|
|
|
|
|
|
|
|
var formatTemplates = map[string]string{
|
|
|
|
"path": `{{path}}`,
|
|
|
|
|
|
|
|
"oneline": `{{style "title" title}} {{style "path" path}} ({{date created "elapsed"}})`,
|
|
|
|
|
|
|
|
"short": `{{style "title" title}} {{style "path" path}} ({{date created "elapsed"}})
|
|
|
|
|
2021-01-30 18:30:46 +00:00
|
|
|
{{list snippets}}`,
|
2021-01-19 20:05:16 +00:00
|
|
|
|
|
|
|
"medium": `{{style "title" title}} {{style "path" path}}
|
|
|
|
Created: {{date created "short"}}
|
|
|
|
|
2021-01-30 18:30:46 +00:00
|
|
|
{{list snippets}}`,
|
2021-01-19 20:05:16 +00:00
|
|
|
|
|
|
|
"long": `{{style "title" title}} {{style "path" path}}
|
|
|
|
Created: {{date created "short"}}
|
|
|
|
Modified: {{date created "short"}}
|
|
|
|
|
2021-01-30 18:30:46 +00:00
|
|
|
{{list snippets}}`,
|
2021-01-19 20:05:16 +00:00
|
|
|
|
|
|
|
"full": `{{style "title" title}} {{style "path" path}}
|
|
|
|
Created: {{date created "short"}}
|
|
|
|
Modified: {{date created "short"}}
|
|
|
|
|
2021-01-23 12:29:14 +00:00
|
|
|
{{prepend " " body}}
|
|
|
|
`,
|
2021-01-19 20:05:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
var termRegex = regexp.MustCompile(`<zk:match>(.*?)</zk:match>`)
|
|
|
|
|
|
|
|
// Format formats a note to be printed on the screen.
|
|
|
|
func (f *Formatter) Format(match Match) (string, error) {
|
|
|
|
path, err := filepath.Rel(f.currentPath, filepath.Join(f.basePath, match.Path))
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
|
2021-01-30 17:08:02 +00:00
|
|
|
snippets := make([]string, 0)
|
|
|
|
for _, snippet := range match.Snippets {
|
|
|
|
snippets = append(snippets, termRegex.ReplaceAllString(snippet, f.snippetTermReplacement))
|
|
|
|
}
|
|
|
|
|
2021-01-19 20:05:16 +00:00
|
|
|
return f.renderer.Render(formatRenderContext{
|
2021-01-30 17:08:02 +00:00
|
|
|
Path: path,
|
|
|
|
Title: match.Title,
|
|
|
|
Lead: match.Lead,
|
|
|
|
Body: match.Body,
|
|
|
|
Snippets: snippets,
|
2021-01-19 20:05:16 +00:00
|
|
|
RawContent: match.RawContent,
|
|
|
|
WordCount: match.WordCount,
|
|
|
|
Created: match.Created,
|
|
|
|
Modified: match.Modified,
|
2021-01-19 22:06:17 +00:00
|
|
|
Checksum: match.Checksum,
|
2021-01-19 20:05:16 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
type formatRenderContext struct {
|
|
|
|
Path string
|
|
|
|
Title string
|
|
|
|
Lead string
|
|
|
|
Body string
|
2021-01-30 17:08:02 +00:00
|
|
|
Snippets []string
|
2021-01-19 20:05:16 +00:00
|
|
|
RawContent string `handlebars:"raw-content"`
|
|
|
|
WordCount int `handlebars:"word-count"`
|
|
|
|
Created time.Time
|
|
|
|
Modified time.Time
|
2021-01-19 22:06:17 +00:00
|
|
|
Checksum string
|
2021-01-19 20:05:16 +00:00
|
|
|
}
|