Skip to content

add creation-date-key modification-date-key` configuration options #531

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions docs/notes/note-format.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,18 @@ You can set up some features of `zk`'s Markdown parser from your

[1]: https://blog.bear.app/2017/11/bear-tips-how-to-create-multi-word-tags/

### `YAML` Frontmatter

The following configuration options are available for changing `zk`'s interactions with the
frontmatter:

| Setting | Default | Description |
| ----------------------- | --------- | --------------------------------------------------------------- |
| `creation-date-key` | `"date"` | Yaml key used to store the creation date & time of the file |
| `modification-date-key` | none [^2] | Yaml key used to store the modification date & time of the file |

[^2]: When this value is not set, the file's modification date is taken from the filesystem.

### Customizing the Markdown links generated by `zk`

By default, `zk` will generate regular Markdown links for internal links. If you
Expand Down
3 changes: 3 additions & 0 deletions docs/notes/note-frontmatter.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,6 @@ keywords: [writing, essay, practice]
All metadata are indexed and can be printed in `zk list` output, using the
template variable `{{metadata.<key>}}`, e.g. `{{metadata.description}}`. The
keys are normalized to lower case.

Some of the keys above can be changed by the configuration file, see [`YAML`
Frontmatter](note-format.md#yaml-frontmatter).
49 changes: 43 additions & 6 deletions internal/core/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ func NewDefaultConfig() Config {
LinkFormat: "markdown",
LinkEncodePath: true,
LinkDropExtension: true,
Frontmatter: YamlFrontmatterConfig{
CreationDate: "date",
ModificationDate: opt.NullString,
},
},
},
LSP: LSPConfig{
Expand Down Expand Up @@ -161,6 +165,18 @@ type MarkdownConfig struct {
LinkEncodePath bool
// Indicates whether a link's path file extension will be removed.
LinkDropExtension bool

// Frontmatter determines the keys used in the frontmatter
Frontmatter YamlFrontmatterConfig
}

// YamlFrontmatterConfig holds the configuration for Yaml frontmatter.
type YamlFrontmatterConfig struct {
// CreationDate indicates what name the key for the creation date has. Default is "date"
CreationDate string
// ModificationDate indicates what name the key for the modification date has. If not present,
// the filesystems modification time is used.
ModificationDate opt.String
}

// ToolConfig holds the external tooling configuration.
Expand Down Expand Up @@ -391,6 +407,21 @@ func ParseConfig(content []byte, path string, parentConfig Config, isGlobal bool
config.Format.Markdown.LinkDropExtension = *markdown.LinkDropExtension
}

// Frontmatter
frontmatter := markdown.Frontmatter
if frontmatter.CreationDate != nil && *frontmatter.CreationDate == "" {
*frontmatter.CreationDate = "date"
}
if frontmatter.CreationDate != nil {
config.Format.Markdown.Frontmatter.CreationDate = *frontmatter.CreationDate
}
if frontmatter.ModificationDate != nil && *frontmatter.ModificationDate == "" {
frontmatter.ModificationDate = nil
}
if frontmatter.ModificationDate != nil {
config.Format.Markdown.Frontmatter.ModificationDate = opt.NewString(*frontmatter.ModificationDate)
}

// Tool
tool := tomlConf.Tool
if tool.Editor != nil {
Expand Down Expand Up @@ -554,12 +585,18 @@ type tomlFormatConfig struct {
}

type tomlMarkdownConfig struct {
Hashtags *bool `toml:"hashtags"`
ColonTags *bool `toml:"colon-tags"`
MultiwordTags *bool `toml:"multiword-tags"`
LinkFormat *string `toml:"link-format"`
LinkEncodePath *bool `toml:"link-encode-path"`
LinkDropExtension *bool `toml:"link-drop-extension"`
Hashtags *bool `toml:"hashtags"`
ColonTags *bool `toml:"colon-tags"`
MultiwordTags *bool `toml:"multiword-tags"`
LinkFormat *string `toml:"link-format"`
LinkEncodePath *bool `toml:"link-encode-path"`
LinkDropExtension *bool `toml:"link-drop-extension"`
Frontmatter tomlYamlFrontmatterConfig `toml:"frontmatter"`
}

type tomlYamlFrontmatterConfig struct {
CreationDate *string `toml:"creation-date-key"`
ModificationDate *string `toml:"modification-date-key"`
}

type tomlToolConfig struct {
Expand Down
16 changes: 16 additions & 0 deletions internal/core/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ func TestParseDefaultConfig(t *testing.T) {
LinkFormat: "markdown",
LinkEncodePath: true,
LinkDropExtension: true,
Frontmatter: YamlFrontmatterConfig{
CreationDate: "date",
ModificationDate: opt.NullString,
},
},
},
Tool: ToolConfig{
Expand Down Expand Up @@ -91,6 +95,10 @@ func TestParseComplete(t *testing.T) {
link-encode-path = true
link-drop-extension = false

[format.markdown.frontmatter]
creation-date-key = "created"
modification-date-key = "changed"

[tool]
editor = "vim"
shell = "/bin/bash"
Expand Down Expand Up @@ -235,6 +243,10 @@ func TestParseComplete(t *testing.T) {
LinkFormat: "custom",
LinkEncodePath: true,
LinkDropExtension: false,
Frontmatter: YamlFrontmatterConfig {
CreationDate: "created",
ModificationDate: opt.NewString("changed"),
},
},
},
Tool: ToolConfig{
Expand Down Expand Up @@ -421,6 +433,10 @@ func TestParseMergesGroupConfig(t *testing.T) {
LinkFormat: "markdown",
LinkEncodePath: true,
LinkDropExtension: true,
Frontmatter: YamlFrontmatterConfig{
CreationDate: "date",
ModificationDate: opt.NullString,
},
},
},
LSP: LSPConfig{
Expand Down
29 changes: 25 additions & 4 deletions internal/core/note_parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,16 +94,16 @@ func (n *Notebook) ParseNoteWithContent(absPath string, content []byte) (*Note,

times, err := times.Stat(absPath)
if err == nil {
note.Modified = times.ModTime().UTC()
note.Created = creationDateFrom(note.Metadata, times)
note.Modified = n.modificationDateFrom(note.Metadata, times)
note.Created = n.creationDateFrom(note.Metadata, times)
}

return &note, nil
}

func creationDateFrom(metadata map[string]interface{}, times times.Timespec) time.Time {
func (n *Notebook) creationDateFrom(metadata map[string]interface{}, times times.Timespec) time.Time {
// Read the creation date from the YAML frontmatter `date` key.
if dateVal, ok := metadata["date"]; ok {
if dateVal, ok := metadata[n.Config.Format.Markdown.Frontmatter.CreationDate]; ok {
if dateStr, ok := dateVal.(string); ok {
if time, err := iso8601.ParseString(dateStr); err == nil {
return time
Expand All @@ -124,3 +124,24 @@ func creationDateFrom(metadata map[string]interface{}, times times.Timespec) tim

return time.Now().UTC()
}

func (n *Notebook) modificationDateFrom(metadata map[string]interface{}, times times.Timespec) time.Time {
configKey := n.Config.Format.Markdown.Frontmatter.ModificationDate
if !configKey.IsNull() {
if dateVal, ok := metadata[configKey.Unwrap()]; ok {
if dateStr, ok := dateVal.(string); ok {
if time, err := iso8601.ParseString(dateStr); err == nil {
return time
}
// Omitting the `T` is common
if time, err := time.Parse("2006-01-02 15:04:05", dateStr); err == nil {
return time
}
if time, err := time.Parse("2006-01-02 15:04", dateStr); err == nil {
return time
}
}
}
}
return times.ModTime().UTC()
}
7 changes: 7 additions & 0 deletions tests/config-format-markdown-frontmatter-creation-date.tesh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
$ cd blank

$ echo "[format.markdown.frontmatter] creation-date-key = \"created\"" > .zk/config.toml

$ echo "---\ncreated: 2025-03-27 01:18:43\n---\n\n# Note" > note.md
$ zk list -qflink
>{"filename":"note"}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
$ cd blank

$ echo "[format.markdown.frontmatter] modification-date-key = \"changed\"" > .zk/config.toml

$ echo "---\nchanged: 2025-03-27 01:18:43\n---\n\n# Note" > note.md
$ zk list -qflink
>{"filename":"note"}