Skip to content

Commit

Permalink
feat(tidy-up): remove double spaces and save Markdown file
Browse files Browse the repository at this point in the history
  • Loading branch information
andreoliwa committed Dec 28, 2024
1 parent 7dfc21e commit 212014a
Show file tree
Hide file tree
Showing 8 changed files with 158 additions and 80 deletions.
4 changes: 3 additions & 1 deletion .golangci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@ linters:
- gci
- gochecknoinits
- godox
- gofmt
- gofumpt
- goimports
- intrange
- ireturn
- paralleltest
- testpackage
# keep-sorted end
7 changes: 7 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,13 @@ build-go: # Build the Golang executable
$(MAKE) list-go
.PHONY: build-go

refresh-go: # Refresh the Go dependencies from the last commit
LAST_COMMIT=$$(cd ../logseq-go; git log -1 --format=%h); \
echo "LAST_COMMIT: $$LAST_COMMIT"; \
go get -u github.com/andreoliwa/logseq-go@$$LAST_COMMIT
go mod tidy
.PHONY: refresh-go

clean: # Clean the build artifacts
cargo clean
-rm `go env GOPATH`/bin/logseq-doctor
Expand Down
2 changes: 2 additions & 0 deletions cmd/testdata/graph/pages/spaces.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,5 @@
- child 2
- child 3
- Here we have #[[some tag with spaces]]
- top level 2
- [[some page title with spaces]]
9 changes: 9 additions & 0 deletions cmd/testdata/graph/pages/spaces.md.golden
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
- Regular text with spaces
- child
- nested [Link With Spaces ](https://example.com)
- top level
- child 2
- child 3
- Here we have #[[some tag with spaces]]
- top level 2
- [[some page title with spaces]]
85 changes: 59 additions & 26 deletions cmd/tidy_up.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"
"log"
"os"
"regexp"
"sort"
"strings"

Expand Down Expand Up @@ -35,36 +36,50 @@ var tidyUpCmd = &cobra.Command{ //nolint:exhaustruct,gochecknoglobals
log.Fatalln("error opening graph: %w", err)
}

transaction := graph.NewTransaction()
shouldSave := false

exitCode := 0
for _, path := range args {
if !isValidMarkdownFile(path) {
fmt.Printf("%s: skipping, not a Markdown file\n", path)
} else {
page, err := graph.OpenViaPath(path)
page, err := transaction.OpenViaPath(path)
if err != nil {
log.Fatalf("%s: error opening file via path: %s\n", path, err)
}
if page == nil {
log.Fatalf("%s: error opening file via path: page is nil\n", path)
}

changes := make([]string, 0)
messages := make([]string, 0)

functions := []func(logseq.Page) string{checkForbiddenReferences, checkRunningTasks, checkDoubleSpaces}
functions := []func(logseq.Page) tidyInfo{
checkForbiddenReferences, checkRunningTasks, removeDoubleSpaces}
for _, f := range functions {
if msg := f(page); msg != "" {
changes = append(changes, msg)
info := f(page)
if info.msg != "" {
messages = append(messages, info.msg)
}
if info.changed {
shouldSave = true
}
}

if len(changes) > 0 {
if len(messages) > 0 {
exitCode = 1
for _, change := range changes {
fmt.Printf("%s: %s\n", path, change)
for _, msg := range messages {
fmt.Printf("%s: %s\n", path, msg)
}
}
}
}
if shouldSave {
err = transaction.Save()
if err != nil {
log.Fatalf("error saving transaction: %s\n", err)
}
}
os.Exit(exitCode)
},
}
Expand All @@ -91,12 +106,17 @@ func isValidMarkdownFile(filePath string) bool {
return !info.IsDir()
}

type tidyInfo struct {
msg string
changed bool
}

// checkForbiddenReferences checks if a page has forbidden references to other pages or tags.
func checkForbiddenReferences(page logseq.Page) string {
func checkForbiddenReferences(page logseq.Page) tidyInfo {
all := make([]string, 0)

for _, block := range page.Blocks() {
block.Children().FilterDeep(func(n content.Node) bool {
block.Children().FindDeep(func(n content.Node) bool {
var reference string
if pageLink, ok := n.(*content.PageLink); ok {
reference = pageLink.To
Expand Down Expand Up @@ -125,10 +145,11 @@ func checkForbiddenReferences(page logseq.Page) string {
if count := len(all); count > 0 {
unique := sortAndRemoveDuplicates(all)

return fmt.Sprintf("remove %d forbidden references to pages/tags: %s", count, strings.Join(unique, ", "))
return tidyInfo{fmt.Sprintf("remove %d forbidden references to pages/tags: %s",
count, strings.Join(unique, ", ")), false}
}

return ""
return tidyInfo{"", false}
}

func sortAndRemoveDuplicates(elements []string) []string {
Expand All @@ -149,11 +170,11 @@ func sortAndRemoveDuplicates(elements []string) []string {
}

// checkRunningTasks checks if a page has running tasks (DOING, etc.).
func checkRunningTasks(page logseq.Page) string {
func checkRunningTasks(page logseq.Page) tidyInfo {
all := make([]string, 0)

for _, block := range page.Blocks() {
block.Children().FilterDeep(func(n content.Node) bool {
block.Children().FindDeep(func(n content.Node) bool {
if task, ok := n.(*content.TaskMarker); ok {
status := task.Status
// TODO: convert to strings "DOING"/"IN-PROGRESS" in logseq-go
Expand All @@ -173,29 +194,41 @@ func checkRunningTasks(page logseq.Page) string {
if count := len(all); count > 0 {
unique := sortAndRemoveDuplicates(all)

return fmt.Sprintf("stop %d running task(s): %s", count, strings.Join(unique, ", "))
return tidyInfo{fmt.Sprintf("stop %d running task(s): %s", count, strings.Join(unique, ", ")), false}
}

return ""
return tidyInfo{"", false}
}

func checkDoubleSpaces(page logseq.Page) string {
func removeDoubleSpaces(page logseq.Page) tidyInfo {
all := make([]string, 0)
doubleSpaceRegex := regexp.MustCompile(`\s{2,}`)
fixed := false

for _, block := range page.Blocks() {
block.Children().FilterDeep(func(node content.Node) bool {
var value string
block.Children().FindDeep(func(node content.Node) bool {
var oldValue string

if text, ok := node.(*content.Text); ok {
value = text.Value
oldValue = text.Value
} else if pageLink, ok := node.(*content.PageLink); ok {
value = pageLink.To
oldValue = pageLink.To
} else if tag, ok := node.(*content.Hashtag); ok {
value = tag.To
oldValue = tag.To
}

if strings.Contains(value, " ") {
all = append(all, fmt.Sprintf("'%s'", value))
if strings.Contains(oldValue, " ") {
all = append(all, fmt.Sprintf("'%s'", oldValue))
newValue := doubleSpaceRegex.ReplaceAllString(oldValue, " ")
fixed = true

if text, ok := node.(*content.Text); ok {
text.Value = newValue
} else if pageLink, ok := node.(*content.PageLink); ok {
pageLink.To = newValue
} else if tag, ok := node.(*content.Hashtag); ok {
tag.To = newValue
}
}

return false
Expand All @@ -205,8 +238,8 @@ func checkDoubleSpaces(page logseq.Page) string {
if count := len(all); count > 0 {
unique := sortAndRemoveDuplicates(all)

return fmt.Sprintf("%d double spaces: %s", count, strings.Join(unique, ", "))
return tidyInfo{fmt.Sprintf("fixed %d double spaces: %s", count, strings.Join(unique, ", ")), fixed}
}

return ""
return tidyInfo{"", fixed}
}
25 changes: 16 additions & 9 deletions cmd/tidy_up_test.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package cmd
package cmd //nolint:testpackage

import (
"context"
Expand Down Expand Up @@ -93,27 +93,34 @@ func setupPage(t *testing.T, name string) logseq.Page {

func TestCheckForbiddenReferences(t *testing.T) {
invalid := setupPage(t, "forbidden")
assert.Equal(t, "remove 4 forbidden references to pages/tags: Inbox, quick capture",
assert.Equal(t, tidyInfo{"remove 4 forbidden references to pages/tags: Inbox, quick capture", false},
checkForbiddenReferences(invalid))

valid := setupPage(t, "valid")
assert.Equal(t, "", checkForbiddenReferences(valid))
assert.Equal(t, tidyInfo{"", false}, checkForbiddenReferences(valid))
}

func TestCheckRunningTasks(t *testing.T) {
invalid := setupPage(t, "running")
assert.Equal(t, "stop 2 running task(s): DOING, IN-PROGRESS", checkRunningTasks(invalid))
assert.Equal(t, tidyInfo{"stop 2 running task(s): DOING, IN-PROGRESS", false}, checkRunningTasks(invalid))

valid := setupPage(t, "valid")
assert.Equal(t, "", checkRunningTasks(valid))
assert.Equal(t, tidyInfo{"", false}, checkRunningTasks(valid))
}

func TestCheckDoubleSpaces(t *testing.T) {
func TestRemoveDoubleSpaces(t *testing.T) {
invalid := setupPage(t, "spaces")
assert.Equal(t,
"3 double spaces: 'Link With Spaces ', 'Regular text with spaces', 'some tag with spaces'",
checkDoubleSpaces(invalid))
tidyInfo{"fixed 4 double spaces: 'Link With Spaces ', 'Regular text with spaces'," +
" 'some page title with spaces', 'some tag with spaces'", true},
removeDoubleSpaces(invalid))

// TODO: compare the saved Markdown file with spaces.md.golden.
// I tested manually and it works but I need to do something like:
// actual := os.ReadFile(invalid.Path())
// expected := os.ReadFile(invalid.Path() + ".golden")
// assert.Equal(t, expected, actual)

valid := setupPage(t, "valid")
assert.Equal(t, "", checkDoubleSpaces(valid))
assert.Equal(t, tidyInfo{"", false}, removeDoubleSpaces(valid))
}
34 changes: 19 additions & 15 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,40 +1,44 @@
module github.com/andreoliwa/logseq-doctor

go 1.21
go 1.23

toolchain go1.23.4

require (
github.com/andreoliwa/logseq-go v0.0.0-20241226195503-ec30920a9c1c
github.com/andreoliwa/logseq-go v0.0.0-20241228161444-32088a5a9491
github.com/spf13/cobra v1.8.1
github.com/stretchr/testify v1.10.0
)

require (
github.com/RoaringBitmap/roaring v0.9.4 // indirect
github.com/axiomhq/hyperloglog v0.0.0-20191112132149-a4c4c47bc57f // indirect
github.com/bits-and-blooms/bitset v1.2.0 // indirect
github.com/RoaringBitmap/roaring v1.9.4 // indirect
github.com/axiomhq/hyperloglog v0.2.2 // indirect
github.com/bits-and-blooms/bitset v1.20.0 // indirect
github.com/blevesearch/go-porterstemmer v1.0.3 // indirect
github.com/blevesearch/mmap-go v1.0.4 // indirect
github.com/blevesearch/segment v0.9.0 // indirect
github.com/blevesearch/segment v0.9.1 // indirect
github.com/blevesearch/snowballstem v0.9.0 // indirect
github.com/blevesearch/vellum v1.0.7 // indirect
github.com/blevesearch/vellum v1.1.0 // indirect
github.com/blugelabs/bluge v0.2.2 // indirect
github.com/blugelabs/bluge_segment_api v0.2.0 // indirect
github.com/blugelabs/ice v1.0.0 // indirect
github.com/blugelabs/ice/v2 v2.0.1 // indirect
github.com/caio/go-tdigest v3.1.0+incompatible // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dgryski/go-metro v0.0.0-20180109044635-280f6062b5bc // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/golang/snappy v0.0.1 // indirect
github.com/google/uuid v1.5.0 // indirect
github.com/dgryski/go-metro v0.0.0-20211217172704-adc40b04c140 // indirect
github.com/fsnotify/fsnotify v1.8.0 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/klauspost/compress v1.15.2 // indirect
github.com/kamstrup/intmap v0.5.1 // indirect
github.com/klauspost/compress v1.17.11 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/mschoch/smat v0.2.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/yuin/goldmark v1.6.0 // indirect
golang.org/x/sys v0.8.0 // indirect
golang.org/x/text v0.9.0 // indirect
github.com/yuin/goldmark v1.7.8 // indirect
golang.org/x/sys v0.28.0 // indirect
golang.org/x/text v0.21.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
olympos.io/encoding/edn v0.0.0-20201019073823-d3554ca0b0a3 // indirect
)
Loading

0 comments on commit 212014a

Please sign in to comment.