Skip to content
Merged
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
4 changes: 4 additions & 0 deletions docs/mdbook/configuration/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ Lefthook supports the following file names for the main config:
| JSON | `lefthook.json` |
| JSON | `.lefthook.json` |
| JSON | `.config/lefthook.json` |
| | |
| JSONC | `lefthook.jsonc` |
| JSONC | `.lefthook.jsonc` |
| JSONC | `.config/lefthook.jsonc` |

If there are more than 1 file in the project, only one will be used, and you'll never know which one. So, please, use one format in a project.

Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ require (
github.com/mitchellh/copystructure v1.2.0 // indirect
github.com/mitchellh/reflectwalk v1.0.2 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/tidwall/jsonc v0.3.2 // indirect
github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
golang.org/x/tools v0.39.0 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I=
github.com/spf13/afero v1.15.0/go.mod h1:NC2ByUVxtQs4b3sIUphxK0NioZnmxgyCrfzeuq8lxMg=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
github.com/tidwall/jsonc v0.3.2 h1:ZTKrmejRlAJYdn0kcaFqRAKlxxFIC21pYq8vLa4p2Wc=
github.com/tidwall/jsonc v0.3.2/go.mod h1:dw+3CIxqHi+t8eFSpzzMlcVYxKp08UP5CD8/uSFCyJE=
github.com/urfave/cli/v3 v3.6.1 h1:j8Qq8NyUawj/7rTYdBGrxcH7A/j7/G8Q5LhWEW4G3Mo=
github.com/urfave/cli/v3 v3.6.1/go.mod h1:ysVLtOEmg2tOy6PknnYVhDoouyC/6N42TMeoMzskhso=
github.com/wk8/go-ordered-map/v2 v2.1.8 h1:5h/BUHu93oj4gIdvHHHGsScSTMijfx5PeYkE/fJgbpc=
Expand Down
4 changes: 1 addition & 3 deletions internal/command/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,9 +99,7 @@ func (l *Lefthook) findMainConfig(path string) (string, error) {
}

for _, name := range config.MainConfigNames {
for _, extension := range []string{
".yml", ".yaml", ".toml", ".json",
} {
for _, extension := range config.Extensions {
configPath := filepath.Join(path, name+extension)
if ok, _ := afero.Exists(l.fs, configPath); ok {
return configPath, nil
Expand Down
26 changes: 26 additions & 0 deletions internal/config/jsonc_parser.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package config

import (
"encoding/json"

"github.com/tidwall/jsonc"
)

type JSONC struct{}

func jsoncParser() *JSONC {
return &JSONC{}
}

func (p *JSONC) Unmarshal(b []byte) (map[string]any, error) {
var out map[string]any
if err := json.Unmarshal(jsonc.ToJSON(b), &out); err != nil {
return nil, err
}
return out, nil
}

// Marshal marshals the given config map to JSON bytes.
func (p *JSONC) Marshal(o map[string]any) ([]byte, error) {
return json.Marshal(o)
}
16 changes: 9 additions & 7 deletions internal/config/load.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,19 @@ var (
hookKeyRegexp = regexp.MustCompile(`^(?P<hookName>[^.]+)\.(?:scripts|commands|jobs)`)
LocalConfigNames = []string{"lefthook-local", ".lefthook-local", filepath.Join(".config", "lefthook-local")}
MainConfigNames = []string{"lefthook", ".lefthook", filepath.Join(".config", "lefthook")}
extensions = []string{
Extensions = []string{
".yml",
".yaml",
".json",
".jsonc",
".toml",
}
parsers = map[string]koanf.Parser{
".yml": yaml.Parser(),
".yaml": yaml.Parser(),
".json": json.Parser(),
".toml": toml.Parser(),
".yml": yaml.Parser(),
".yaml": yaml.Parser(),
".json": json.Parser(),
".jsonc": jsoncParser(),
".toml": toml.Parser(),
}

mergeJobsOption = koanf.WithMergeFunc(mergeJobs)
Expand Down Expand Up @@ -70,7 +72,7 @@ func loadConfig(k *koanf.Koanf, filesystem afero.Fs, path string) error {

// loadFirst loads the first existing config from given names and supported extensions.
func loadFirst(k *koanf.Koanf, filesystem afero.Fs, root string, names []string) error {
for _, extension := range extensions {
for _, extension := range Extensions {
for _, name := range names {
config := filepath.Join(root, name+extension)
if ok, _ := afero.Exists(filesystem, config); !ok {
Expand All @@ -90,7 +92,7 @@ func loadFirstMain(k *koanf.Koanf, filesystem afero.Fs, root string) error {
if ok := errors.As(err, &ConfigNotFoundError{}); ok {
var hasLocalConfig bool
OUT:
for _, extension := range extensions {
for _, extension := range Extensions {
for _, name := range LocalConfigNames {
if ok, _ := afero.Exists(filesystem, filepath.Join(root, name+extension)); ok {
hasLocalConfig = true
Expand Down
22 changes: 22 additions & 0 deletions tests/integration/run_jsonc.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
exec git init
exec git config user.email "you@example.com"
exec git config user.name "Your Name"
exec git add -A
exec lefthook install
exec git commit -m 'test'
stderr '\s*Hi there from Lefthook\s*'

-- lefthook.jsonc --
{
/* Prints only what's being executed */
"output": [
"execution"
],
"pre-commit": {
"commands": {
"echo": {
"run": "echo Hi there from Lefthook" // echoes Hi there from Lefthook
}
}
}
}
Loading