Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package zk for openSUSE:Factory checked in at 2026-06-18 18:44:55 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/zk (Old) and /work/SRC/openSUSE:Factory/.zk.new.1981 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "zk" Thu Jun 18 18:44:55 2026 rev:14 rq:1360257 version:0.15.5 Changes: -------- --- /work/SRC/openSUSE:Factory/zk/zk.changes 2026-05-10 16:48:42.341715740 +0200 +++ /work/SRC/openSUSE:Factory/.zk.new.1981/zk.changes 2026-06-18 18:45:47.277972004 +0200 @@ -1,0 +2,13 @@ +Mon Jun 15 09:04:20 UTC 2026 - Andrea Manzini <[email protected]> + +- Update to version 0.15.5: + * List, edit and filter for broken links with --broken-links + * Update strftime package, supporting %g and %G formats in the + {{format-date}} helper + * Option to append links to selected text, instead of replacing + * Paths with ~ and env variables no longer error when passed to + --notebook-dir and --working-dir + * Guard LSP against unnecessary erroring on missing textDocument/definition + capabilities + +------------------------------------------------------------------- Old: ---- zk-0.15.4.tar.gz New: ---- zk-0.15.5.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ zk.spec ++++++ --- /var/tmp/diff_new_pack.PLN47o/_old 2026-06-18 18:45:48.266013228 +0200 +++ /var/tmp/diff_new_pack.PLN47o/_new 2026-06-18 18:45:48.270013394 +0200 @@ -17,7 +17,7 @@ Name: zk -Version: 0.15.4 +Version: 0.15.5 Release: 0 Summary: Plain text note-taking assistant for markdown License: BSD-2-Clause ++++++ vendor.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/github.com/lestrrat-go/strftime/Changes new/vendor/github.com/lestrrat-go/strftime/Changes --- old/vendor/github.com/lestrrat-go/strftime/Changes 2026-05-04 14:26:40.000000000 +0200 +++ new/vendor/github.com/lestrrat-go/strftime/Changes 2026-06-08 13:03:02.000000000 +0200 @@ -1,6 +1,16 @@ Changes ======= +v1.1.1 - 29 Jul 2025 + * Implement %G and %g (#67) + +v1.1.0 - 28 Aug 2024 +[Miscellaneous] + * github.com/pkg/errors has been removed (it has been two years :) + * Updated build/test actions + * Updated minimum required go version to go 1.21 + * Fix week number handling + v1.0.6 - 20 Apr 2022 [Miscellaneous] * Minimum go version is now go 1.13 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/github.com/lestrrat-go/strftime/README.md new/vendor/github.com/lestrrat-go/strftime/README.md --- old/vendor/github.com/lestrrat-go/strftime/README.md 2026-05-04 14:26:40.000000000 +0200 +++ new/vendor/github.com/lestrrat-go/strftime/README.md 2026-06-08 13:03:02.000000000 +0200 @@ -2,9 +2,7 @@ Fast strftime for Go -[](https://travis-ci.org/lestrrat-go/strftime) - -[](https://godoc.org/github.com/lestrrat-go/strftime) + [](https://github.com/lestrrat-go/strftime/actions?query=branch%3Amaster) [](https://pkg.go.dev/github.com/lestrrat-go/strftime) # SYNOPSIS @@ -59,6 +57,8 @@ | %d | day of the month as a decimal number (01-31) | | %e | the day of the month as a decimal number (1-31); single digits are preceded by a blank | | %F | equivalent to %Y-%m-%d | +| %G | the ISO week year with century as a decimal number with 4 digits | +| %g | the ISO week year without century as a decimal number (00-99) with 2 digits | | %H | the hour (24-hour clock) as a decimal number (00-23) | | %h | same as %b | | %I | the hour (12-hour clock) as a decimal number (01-12) | diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/github.com/lestrrat-go/strftime/appenders.go new/vendor/github.com/lestrrat-go/strftime/appenders.go --- old/vendor/github.com/lestrrat-go/strftime/appenders.go 2026-05-04 14:26:40.000000000 +0200 +++ new/vendor/github.com/lestrrat-go/strftime/appenders.go 2026-06-08 13:03:02.000000000 +0200 @@ -36,13 +36,15 @@ secondsNumberZeroPad = StdlibFormat("05") hms = StdlibFormat("15:04:05") tab = Verbatim("\t") - weekNumberSundayOrigin = weeknumberOffset(0) // week number of the year, Sunday first + weekNumberSundayOrigin = weeknumberOffset(true) // week number of the year, Sunday first weekdayMondayOrigin = weekday(1) // monday as the first day, and 01 as the first value weekNumberMondayOriginOneOrigin = AppendFunc(appendWeekNumber) eby = StdlibFormat("_2-Jan-2006") + weekyear = AppendFunc(appendWeekYear) // week year, with century + weekyearNoCentury = AppendFunc(appendWeekYearNoCentury) // week year, without century // monday as the first day, and 00 as the first value - weekNumberMondayOrigin = weeknumberOffset(1) // week number of the year, Monday first + weekNumberMondayOrigin = weeknumberOffset(false) // week number of the year, Monday first weekdaySundayOrigin = weekday(0) natReprTime = StdlibFormat("15:04:05") // national representation of the time XXX is this correct? natReprDate = StdlibFormat("01/02/06") // national representation of the date XXX is this correct? @@ -243,24 +245,54 @@ return append(b, byte(n+48)) } -type weeknumberOffset int +type weeknumberOffset bool func (v weeknumberOffset) Append(b []byte, t time.Time) []byte { - yd := t.YearDay() - offset := int(t.Weekday()) - int(v) - if offset < 0 { - offset += 7 + offset := int(t.Weekday()) + if v { + offset = 6 - offset + } else if offset != 0 { + offset = 7 - offset } + n := (t.YearDay() + offset) / 7 + if n < 10 { + b = append(b, '0') + } + return append(b, strconv.Itoa(n)...) +} + +func appendWeekYear(b []byte, t time.Time) []byte { + year, _ := t.ISOWeek() - if yd < offset { - return append(b, '0', '0') + // Handle negative years (BCE) + if year < 0 { + b = append(b, '-') + year = -year + } + // Ensure 4-digit formatting + if year < 1000 { + if year < 10 { + b = append(b, '0', '0', '0') + } else if year < 100 { + b = append(b, '0', '0') + } else { + b = append(b, '0') + } } + return append(b, strconv.Itoa(year)...) +} - n := ((yd - offset) / 7) + 1 - if n < 10 { +func appendWeekYearNoCentury(b []byte, t time.Time) []byte { + year, _ := t.ISOWeek() + if year < 0 { + b = append(b, '-') + year = -year + } + yearNoCentury := year % 100 + if yearNoCentury < 10 { b = append(b, '0') } - return append(b, strconv.Itoa(n)...) + return append(b, strconv.Itoa(yearNoCentury)...) } func appendWeekNumber(b []byte, t time.Time) []byte { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/github.com/lestrrat-go/strftime/internal/errors/errors_fmt.go new/vendor/github.com/lestrrat-go/strftime/internal/errors/errors_fmt.go --- old/vendor/github.com/lestrrat-go/strftime/internal/errors/errors_fmt.go 2026-05-04 14:26:40.000000000 +0200 +++ new/vendor/github.com/lestrrat-go/strftime/internal/errors/errors_fmt.go 1970-01-01 01:00:00.000000000 +0100 @@ -1,18 +0,0 @@ -//go:build strftime_native_errors -// +build strftime_native_errors - -package errors - -import "fmt" - -func New(s string) error { - return fmt.Errorf(s) -} - -func Errorf(s string, args ...interface{}) error { - return fmt.Errorf(s, args...) -} - -func Wrap(err error, s string) error { - return fmt.Errorf(s+`: %w`, err) -} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/github.com/lestrrat-go/strftime/internal/errors/errors_pkg.go new/vendor/github.com/lestrrat-go/strftime/internal/errors/errors_pkg.go --- old/vendor/github.com/lestrrat-go/strftime/internal/errors/errors_pkg.go 2026-05-04 14:26:40.000000000 +0200 +++ new/vendor/github.com/lestrrat-go/strftime/internal/errors/errors_pkg.go 1970-01-01 01:00:00.000000000 +0100 @@ -1,18 +0,0 @@ -//go:build !strftime_native_errors -// +build !strftime_native_errors - -package errors - -import "github.com/pkg/errors" - -func New(s string) error { - return errors.New(s) -} - -func Errorf(s string, args ...interface{}) error { - return errors.Errorf(s, args...) -} - -func Wrap(err error, s string) error { - return errors.Wrap(err, s) -} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/github.com/lestrrat-go/strftime/specifications.go new/vendor/github.com/lestrrat-go/strftime/specifications.go --- old/vendor/github.com/lestrrat-go/strftime/specifications.go 2026-05-04 14:26:40.000000000 +0200 +++ new/vendor/github.com/lestrrat-go/strftime/specifications.go 2026-06-08 13:03:02.000000000 +0200 @@ -1,10 +1,9 @@ package strftime import ( + "errors" "fmt" "sync" - - "github.com/lestrrat-go/strftime/internal/errors" ) // because there is no such thing was a sync.RWLocker @@ -78,6 +77,8 @@ 'D': mdy, 'd': dayOfMonthZeroPad, 'e': dayOfMonthSpacePad, + 'G': weekyear, + 'g': weekyearNoCentury, 'F': ymd, 'H': twentyFourHourClockZeroPad, 'h': abbrvMonthName, @@ -124,7 +125,7 @@ } v, ok := ds.store[b] if !ok { - return nil, errors.Errorf(`lookup failed: '%%%c' was not found in specification set`, b) + return nil, fmt.Errorf(`lookup failed: '%%%c' was not found in specification set`, b) } return v, nil } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/github.com/lestrrat-go/strftime/strftime.go new/vendor/github.com/lestrrat-go/strftime/strftime.go --- old/vendor/github.com/lestrrat-go/strftime/strftime.go 2026-05-04 14:26:40.000000000 +0200 +++ new/vendor/github.com/lestrrat-go/strftime/strftime.go 2026-06-08 13:03:02.000000000 +0200 @@ -1,12 +1,12 @@ package strftime import ( + "errors" + "fmt" "io" "strings" "sync" "time" - - "github.com/lestrrat-go/strftime/internal/errors" ) type compileHandler interface { @@ -62,7 +62,7 @@ specification, err := ds.Lookup(p[1]) if err != nil { - return errors.Wrap(err, `pattern compilation failed`) + return fmt.Errorf("pattern compilation failed: %w", err) } handler.handle(specification) @@ -127,14 +127,14 @@ // TODO: this may be premature optimization ds, err := getSpecificationSetFor(options...) if err != nil { - return "", errors.Wrap(err, `failed to get specification set`) + return "", fmt.Errorf("failed to get specification set: %w", err) } h := getFmtAppendExecutor() defer releasdeFmtAppendExecutor(h) h.t = t if err := compile(h, p, ds); err != nil { - return "", errors.Wrap(err, `failed to compile format`) + return "", fmt.Errorf("failed to compile format: %w", err) } return string(h.dst), nil @@ -152,14 +152,14 @@ // TODO: this may be premature optimization ds, err := getSpecificationSetFor(options...) if err != nil { - return nil, errors.Wrap(err, `failed to get specification set`) + return nil, fmt.Errorf("failed to get specification set: %w", err) } var h appenderListBuilder h.list = &combiningAppend{} if err := compile(&h, p, ds); err != nil { - return nil, errors.Wrap(err, `failed to compile format`) + return nil, fmt.Errorf("failed to compile format: %w", err) } return &Strftime{ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/modules.txt new/vendor/modules.txt --- old/vendor/modules.txt 2026-05-04 14:26:40.000000000 +0200 +++ new/vendor/modules.txt 2026-06-08 13:03:02.000000000 +0200 @@ -45,10 +45,9 @@ # github.com/kr/text v0.2.0 ## explicit github.com/kr/text -# github.com/lestrrat-go/strftime v1.0.6 -## explicit; go 1.13 +# github.com/lestrrat-go/strftime v1.1.1 +## explicit; go 1.21 github.com/lestrrat-go/strftime -github.com/lestrrat-go/strftime/internal/errors # github.com/mattn/go-colorable v0.1.12 ## explicit; go 1.13 github.com/mattn/go-colorable ++++++ zk-0.15.4.tar.gz -> zk-0.15.5.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/zk-0.15.4/.github/ISSUE_TEMPLATE/bug.yml new/zk-0.15.5/.github/ISSUE_TEMPLATE/bug.yml --- old/zk-0.15.4/.github/ISSUE_TEMPLATE/bug.yml 1970-01-01 01:00:00.000000000 +0100 +++ new/zk-0.15.5/.github/ISSUE_TEMPLATE/bug.yml 2026-06-08 13:03:02.000000000 +0200 @@ -0,0 +1,68 @@ +name: Bug Report +description: File a bug report to help improve zk. +title: "Don't start with 'bug:'" +labels: + - bug +body: + - type: markdown + attributes: + value: | + Thank you for filing a bug report! + - type: checkboxes + id: checks + attributes: + label: Check if applicable + description: | + :warning: Our time is limited and if we don't plan on fixing the reported bug myself, we might close this issue. No hard feelings. + :heart: But if you would like to contribute a fix yourself, **we'll be happy to guide you through the codebase and review a pull request**. + options: + - label: I have searched the existing issues (**required**) + required: true + - label: I'm willing to help fix the problem and contribute a pull request + - type: textarea + id: bug-description + attributes: + label: Describe the bug + description: Also tell us, what did you expect to happen? + placeholder: A clear and concise description of what the bug is. + validations: + required: true + - type: textarea + id: bug-steps + attributes: + label: How to reproduce? + description: | + Step by step explanation to reproduce the issue. + + If you can, drag and drop: + - a zipped sample notebook + - screenshots or a screencast showing the issue + placeholder: | + 1. Add a note with the content "..." + 2. Run `zk edit --interactive` + 3. See error + ... + validations: + required: true + - type: textarea + id: vim-config + attributes: + label: zk configuration + description: | + Paste the minimal `zk` configuration file (`.zk/config.toml`) reproducing the issue. + render: toml + validations: + required: true + - type: textarea + id: bug-environment + attributes: + label: Environment + description: | + Run the following shell commands and paste the result here: + ``` + zk --version && echo "system: `uname -srmo`" + ``` + placeholder: | + zk 0.13.0 + system: Darwin 22.5.0 arm64 + render: bash diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/zk-0.15.4/.github/ISSUE_TEMPLATE/bug_report.yml new/zk-0.15.5/.github/ISSUE_TEMPLATE/bug_report.yml --- old/zk-0.15.4/.github/ISSUE_TEMPLATE/bug_report.yml 2026-05-04 14:26:40.000000000 +0200 +++ new/zk-0.15.5/.github/ISSUE_TEMPLATE/bug_report.yml 1970-01-01 01:00:00.000000000 +0100 @@ -1,65 +0,0 @@ -name: Bug report -description: File a bug report to help improve zk. -body: - - type: markdown - attributes: - value: | - Thank you for filing a bug report! - - type: checkboxes - id: checks - attributes: - label: Check if applicable - description: | - :warning: My time is limited and if I don't plan on fixing the reported bug myself, I might close this issue. No hard feelings. - :heart: But if you would like to contribute a fix yourself, **I'll be happy to guide you through the codebase and review a pull request**. - options: - - label: I have searched the existing issues (**required**) - required: true - - label: I'm willing to help fix the problem and contribute a pull request - - type: textarea - id: bug-description - attributes: - label: Describe the bug - description: Also tell me, what did you expect to happen? - placeholder: A clear and concise description of what the bug is. - validations: - required: true - - type: textarea - id: bug-steps - attributes: - label: How to reproduce? - description: | - Step by step explanation to reproduce the issue. - - If you can, drag and drop: - - a zipped sample notebook - - screenshots or a screencast showing the issue - placeholder: | - 1. Add a note with the content "..." - 2. Run `zk edit --interactive` - 3. See error - ... - validations: - required: true - - type: textarea - id: vim-config - attributes: - label: zk configuration - description: | - Paste the minimal `zk` configuration file (`.zk/config.toml`) reproducing the issue. - render: toml - validations: - required: true - - type: textarea - id: bug-environment - attributes: - label: Environment - description: | - Run the following shell commands and paste the result here: - ``` - zk --version && echo "system: `uname -srmo`" - ``` - placeholder: | - zk 0.13.0 - system: Darwin 22.5.0 arm64 - render: bash diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/zk-0.15.4/.github/ISSUE_TEMPLATE/config.yml new/zk-0.15.5/.github/ISSUE_TEMPLATE/config.yml --- old/zk-0.15.4/.github/ISSUE_TEMPLATE/config.yml 1970-01-01 01:00:00.000000000 +0100 +++ new/zk-0.15.5/.github/ISSUE_TEMPLATE/config.yml 2026-06-08 13:03:02.000000000 +0200 @@ -0,0 +1 @@ +blank_issues_enabled: false diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/zk-0.15.4/.github/ISSUE_TEMPLATE/enhancement.yml new/zk-0.15.5/.github/ISSUE_TEMPLATE/enhancement.yml --- old/zk-0.15.4/.github/ISSUE_TEMPLATE/enhancement.yml 1970-01-01 01:00:00.000000000 +0100 +++ new/zk-0.15.5/.github/ISSUE_TEMPLATE/enhancement.yml 2026-06-08 13:03:02.000000000 +0200 @@ -0,0 +1,19 @@ +name: Enhancement +description: Something that exists, but can be improved. +labels: + - enhancement +body: + - type: textarea + id: description + attributes: + label: Description + description: + Describe the enhancement. What is currently not working so well? And how + can it be improved? + - type: checkboxes + id: ownership + attributes: + label: "Do I plan to submit a PR for this?" + options: + - label: "No" + - label: "Yes" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/zk-0.15.4/.github/ISSUE_TEMPLATE/feature.yml new/zk-0.15.5/.github/ISSUE_TEMPLATE/feature.yml --- old/zk-0.15.4/.github/ISSUE_TEMPLATE/feature.yml 1970-01-01 01:00:00.000000000 +0100 +++ new/zk-0.15.5/.github/ISSUE_TEMPLATE/feature.yml 2026-06-08 13:03:02.000000000 +0200 @@ -0,0 +1,20 @@ +name: Feature +description: Suggest a new feature for this project. +title: "Don't start with 'feat:'" +labels: + - feature +body: + - type: textarea + id: description + attributes: + label: Description + description: + Describe the feature. Why should it be implemented? What problem does it + solve? What value does it bring? How could it be implemented? + - type: checkboxes + id: ownership + attributes: + label: "Do I plan to submit a PR for this?" + options: + - label: "No" + - label: "Yes" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/zk-0.15.4/.github/ISSUE_TEMPLATE/feature_request.yml new/zk-0.15.5/.github/ISSUE_TEMPLATE/feature_request.yml --- old/zk-0.15.4/.github/ISSUE_TEMPLATE/feature_request.yml 2026-05-04 14:26:40.000000000 +0200 +++ new/zk-0.15.5/.github/ISSUE_TEMPLATE/feature_request.yml 1970-01-01 01:00:00.000000000 +0100 @@ -1,12 +0,0 @@ -name: Feature request -description: Suggest an idea for this project. -body: - - type: markdown - attributes: - value: | - If you have an idea, _please [open as a discussion](https://github.com/zk-org/zk/discussions/new?category=ideas)_ instead of an issue. This helps keep the issue tracker more relavent. - Be aware that feature requests [may not get much attention through 2025!](https://github.com/zk-org/zk/discussions/486) - - type: textarea - attributes: - label: Exception - placeholder: If you're not going to open a discussion instead, briefly explain why. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/zk-0.15.4/.github/ISSUE_TEMPLATE/support.yml new/zk-0.15.5/.github/ISSUE_TEMPLATE/support.yml --- old/zk-0.15.4/.github/ISSUE_TEMPLATE/support.yml 2026-05-04 14:26:40.000000000 +0200 +++ new/zk-0.15.5/.github/ISSUE_TEMPLATE/support.yml 1970-01-01 01:00:00.000000000 +0100 @@ -1,13 +0,0 @@ -name: User support -description: You need help? -body: - - type: markdown - attributes: - value: | - :warning: Unfortunately, my time is limited and I can't offer reliable user support. I might answer if you catch me on a slow day, or hopefully someone else will. - - type: checkboxes - id: checks - attributes: - label: If you need help, open a discussion - options: - - label: I will [create a new discussion](https://github.com/zk-org/zk/discussions/new?category=help) instead of an issue. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/zk-0.15.4/.github/workflows/deploy-docs.yml new/zk-0.15.5/.github/workflows/deploy-docs.yml --- old/zk-0.15.4/.github/workflows/deploy-docs.yml 1970-01-01 01:00:00.000000000 +0100 +++ new/zk-0.15.5/.github/workflows/deploy-docs.yml 2026-06-08 13:03:02.000000000 +0200 @@ -0,0 +1,25 @@ +name: Deploy GitHub Pages + +# NOTE: workflow uses this repo: https://github.com/sphinx-notes/pages + +on: + push: + branches: [main] + paths: [docs/**] + +concurrency: + group: "pages" + cancel-in-progress: false + +jobs: + pages: + runs-on: ubuntu-latest + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + permissions: + pages: write + id-token: write + steps: + - id: deployment + uses: sphinx-notes/pages@v3 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/zk-0.15.4/.github/workflows/gh-pages.yml new/zk-0.15.5/.github/workflows/gh-pages.yml --- old/zk-0.15.4/.github/workflows/gh-pages.yml 2026-05-04 14:26:40.000000000 +0200 +++ new/zk-0.15.5/.github/workflows/gh-pages.yml 1970-01-01 01:00:00.000000000 +0100 @@ -1,25 +0,0 @@ -name: Deploy GitHub Pages - -# NOTE: workflow uses this repo: https://github.com/sphinx-notes/pages - -on: - push: - branches: [main] - paths: [docs/**] - -concurrency: - group: "pages" - cancel-in-progress: false - -jobs: - pages: - runs-on: ubuntu-latest - environment: - name: github-pages - url: ${{ steps.deployment.outputs.page_url }} - permissions: - pages: write - id-token: write - steps: - - id: deployment - uses: sphinx-notes/pages@v3 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/zk-0.15.4/CHANGELOG.md new/zk-0.15.5/CHANGELOG.md --- old/zk-0.15.4/CHANGELOG.md 2026-05-04 14:26:40.000000000 +0200 +++ new/zk-0.15.5/CHANGELOG.md 2026-06-08 13:03:02.000000000 +0200 @@ -9,8 +9,18 @@ ### Added +- List, edit and filter for broken links with `--broken-links` (by + @WhyNotHugo, 708) +- Update strftime package, supporting `%g` and `%G` formats in the + `{{format-date}}` helper (by @tjex, 723) +- Option to append links to selected text, instead of replacing (by @tjex, 724) + ### Fixed +- Paths with `~` and env variables no longer error when passed to + `--notebook-dir` and `--working-dir` (by @tjex, 732) +- Guard LSP against unnecessary erroring on missing textDocument/definition + capabilities (by @SAY-5, 718) ## 0.15.4 @@ -31,9 +41,12 @@ - Links in markdown footnotes now included in :ZkLinks (by @WhyNotHugo, 639) - Indexing notebook now 35% and 74% faster for full and incremental indexing respectively (by @WhyNotHugo, 642) -- Stop crashing lsp server when server received `textDocument/completion` request with out of range parameters. (by @virusbb001, 667) -- lsp: Provide completion after [[ on lines with multi-byte characters (by @virusbb001, 671) -- Prevent crash in LookForward when the parameters is out of characters number. (by @virusbb001, 673) +- Stop crashing lsp server when server received `textDocument/completion` + request with out of range parameters. (by @virusbb001, 667) +- lsp: Provide completion after [[ on lines with multi-byte characters (by + @virusbb001, 671) +- Prevent crash in LookForward when the parameters is out of characters number. + (by @virusbb001, 673) ## 0.15.2 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/zk-0.15.4/README.md new/zk-0.15.5/README.md --- old/zk-0.15.4/README.md 2026-05-04 14:26:40.000000000 +0200 +++ new/zk-0.15.5/README.md 2026-06-08 13:03:02.000000000 +0200 @@ -164,7 +164,7 @@ - [Neuron](https://github.com/srid/neuron) – a great tool to publish a Zettelkasten on the web -- [Emanote](https://emanote.srid.ca/) – an improved successor to Neuron +- [Emanote](https://emanote.srid.ca/) – an improved successor to Neuron (see [Emanote configuration for zk](https://emanote.srid.ca/zk)) - [Weave](https://github.com/matze/weave) – another tool to publish Zettelkasten on the web - [sirupsen's zk](https://github.com/sirupsen/zk) – a collection of scripts with diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/zk-0.15.4/VERSION.txt new/zk-0.15.5/VERSION.txt --- old/zk-0.15.4/VERSION.txt 2026-05-04 14:26:40.000000000 +0200 +++ new/zk-0.15.5/VERSION.txt 2026-06-08 13:03:02.000000000 +0200 @@ -1 +1 @@ -v0.15.4 +v0.15.5 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/zk-0.15.4/docs/notes/note-filtering.md new/zk-0.15.5/docs/notes/note-filtering.md --- old/zk-0.15.4/docs/notes/note-filtering.md 2026-05-04 14:26:40.000000000 +0200 +++ new/zk-0.15.5/docs/notes/note-filtering.md 2026-06-08 13:03:02.000000000 +0200 @@ -63,7 +63,8 @@ - `re` enables regular expression for advanced use cases. Change the currently used strategy with `--match-strategy <strategy>` (or `-M`). -To set the default strategy, you can declare a [custom alias](../config/config-alias.md): +To set the default strategy, you can declare a +[custom alias](../config/config-alias.md): ```toml [alias] @@ -228,8 +229,8 @@ $ zk list --tag "year/201*" ``` -A useful [notebook housekeeping](../tips/notebook-housekeeping.md) feature is to find -tags which _do not_ have tags. +A useful [notebook housekeeping](../tips/notebook-housekeeping.md) feature is to +find tags which _do not_ have tags. ```sh $ zk list --tagless @@ -278,11 +279,17 @@ --linked-by 200911172034 --recursive --max-distance 3 ``` -Finally, it can be useful to see which notes have no links pointing to them at -all. You can use the `--orphan` option for this. +## Troubleshoot Links -You can also find notes that are targets of links from other notes but don't -link back to them using `--missing-backlink`. +You can also find notes that are linked to from other notes but don't link back +to them using `--missing-backlink`. + +It can also be useful to see which notes have no links pointing to them at all +by using the `--orphan` flag. + +Lastly, `--broken-links` will return notes that have outgoing links, but where +at least one of those links is broken (e.g., due to an incorrect filepath or +pointing to a deleted file). ## Find related notes @@ -361,8 +368,8 @@ editor. Use `--interactive` (or `-i`) to select filtered notes manually. The interactive -selection is handled by [`fzf`](../config/tool-fzf.md) which brings a powerful fuzzy -matching search into the mix. +selection is handled by [`fzf`](../config/tool-fzf.md) which brings a powerful +fuzzy matching search into the mix. ## Sort the results diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/zk-0.15.4/docs/tips/editors-integration.md new/zk-0.15.5/docs/tips/editors-integration.md --- old/zk-0.15.4/docs/tips/editors-integration.md 2026-05-04 14:26:40.000000000 +0200 +++ new/zk-0.15.5/docs/tips/editors-integration.md 2026-06-08 13:03:02.000000000 +0200 @@ -51,9 +51,9 @@ "command": "zk", "args": ["lsp"], "trace.server": "messages", - "filetypes": ["markdown"], - }, - }, + "filetypes": ["markdown"] + } + } } ``` @@ -131,10 +131,11 @@ ``` <!-- prettier-ignore --> -:::{note} + +:::{note}\ This configuration disables Helix's [default language servers](https://docs.helix-editor.com/lang-support.html) for -Markdown. +Markdown.\ ::: </details> @@ -155,9 +156,9 @@ "command": ["zk", "lsp"], "languageId": "markdown", "scopes": ["source.markdown"], - "syntaxes": ["Packages/MarkdownEditing/Markdown.sublime-syntax"], - }, - }, + "syntaxes": ["Packages/MarkdownEditing/Markdown.sublime-syntax"] + } + } } ``` @@ -211,6 +212,7 @@ | `date` | string | A date of creation for the note in natural language, e.g. "tomorrow" | | `edit` | boolean | When true, the editor will open the newly created note (**not supported by all editors**) | | `dryRun` | boolean | When true, `zk` will not actually create the note on the file system, but will return its generated content and path | + | `append` | boolean | Append the link to selection instead of replacing it. | | `insertLinkAtLocation` | location<sup>1</sup> | A location in another note where a link to the new note will be inserted | | `insertContentAtLocation` | location<sup>1</sup> | A location in another note where the content of the new note will be inserted | @@ -258,41 +260,41 @@ 1. A path to any file or directory in the notebook, to locate it. 2. <details><summary>A dictionary of additional options (click to expand)</summary> - | Key | Type | Required? | Description | - | ---------------- | ------------ | --------- | --------------------------------------------------------------------------------------------------------- | - | `select` | string array | Yes | List of note fields to return<sup>1</sup> | - | `hrefs` | string array | No | Find notes matching the given path, including its descendants | - | `limit` | integer | No | Limit the number of notes found | - | `match` | string array | No | Terms to search for in the notes | - | `exactMatch` | boolean | No | (deprecated: use `matchStrategy`) Search for exact occurrences of the `match` argument (case insensitive) | - | `matchStrategy` | string | No | Specify match strategy, which may be "fts" (default), "exact" or "re" | - | `excludeHrefs` | string array | No | Ignore notes matching the given path, including its descendants | - | `tags` | string array | No | Find notes tagged with the given tags | - | `mention` | string array | No | Find notes mentioning the title of the given ones | - | `mentionedBy` | string array | No | Find notes whose title is mentioned in the given ones | - | `linkTo` | string array | No | Find notes which are linking to the given ones | - | `linkedBy` | string array | No | Find notes which are linked by the given ones | - | `orphan` | boolean | No | Find notes which are not linked by any other note | - | `tagless` | boolean | No | Find notes which have no tags | - | `related` | string array | No | Find notes which might be related to the given ones | - | `maxDistance` | integer | No | Maximum distance between two linked notes | - | `recursive` | boolean | No | Follow links recursively | - | `created` | string | No | Find notes created on the given date | - | `createdBefore` | string | No | Find notes created before the given date | - | `createdAfter` | string | No | Find notes created after the given date | - | `modified` | string | No | Find notes modified on the given date | - | `modifiedBefore` | string | No | Find notes modified before the given date | - | `modifiedAfter` | string | No | Find notes modified after the given date | - | `sort` | string array | No | Order the notes by the given criterion | - - 1. As the output of this command might be very verbose and put a heavy load on - the LSP client, you need to explicitly set which note fields you want to - receive with the `select` option. The following fields are available: - `filename`, `filenameStem`, `path`, `absPath`, `title`, `lead`, `body`, - `snippets`, `rawContent`, `wordCount`, `tags`, `metadata`, `created`, - `modified` and `checksum`. + | Key | Type | Required? | Description | + | ---------------- | ------------ | --------- | --------------------------------------------------------------------------------------------------------- | + | `select` | string array | Yes | List of note fields to return<sup>1</sup> | + | `hrefs` | string array | No | Find notes matching the given path, including its descendants | + | `limit` | integer | No | Limit the number of notes found | + | `match` | string array | No | Terms to search for in the notes | + | `exactMatch` | boolean | No | (deprecated: use `matchStrategy`) Search for exact occurrences of the `match` argument (case insensitive) | + | `matchStrategy` | string | No | Specify match strategy, which may be "fts" (default), "exact" or "re" | + | `excludeHrefs` | string array | No | Ignore notes matching the given path, including its descendants | + | `tags` | string array | No | Find notes tagged with the given tags | + | `mention` | string array | No | Find notes mentioning the title of the given ones | + | `mentionedBy` | string array | No | Find notes whose title is mentioned in the given ones | + | `linkTo` | string array | No | Find notes which are linking to the given ones | + | `linkedBy` | string array | No | Find notes which are linked by the given ones | + | `orphan` | boolean | No | Find notes which are not linked by any other note | + | `tagless` | boolean | No | Find notes which have no tags | + | `related` | string array | No | Find notes which might be related to the given ones | + | `maxDistance` | integer | No | Maximum distance between two linked notes | + | `recursive` | boolean | No | Follow links recursively | + | `created` | string | No | Find notes created on the given date | + | `createdBefore` | string | No | Find notes created before the given date | + | `createdAfter` | string | No | Find notes created after the given date | + | `modified` | string | No | Find notes modified on the given date | + | `modifiedBefore` | string | No | Find notes modified before the given date | + | `modifiedAfter` | string | No | Find notes modified after the given date | + | `sort` | string array | No | Order the notes by the given criterion | + + 1. As the output of this command might be very verbose and put a heavy load + on the LSP client, you need to explicitly set which note fields you want + to receive with the `select` option. The following fields are available: + `filename`, `filenameStem`, `path`, `absPath`, `title`, `lead`, `body`, + `snippets`, `rawContent`, `wordCount`, `tags`, `metadata`, `created`, + `modified` and `checksum`. - </details> + </details> `zk.list` returns the found notes as a JSON array. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/zk-0.15.4/go.mod new/zk-0.15.5/go.mod --- old/zk-0.15.4/go.mod 2026-05-04 14:26:40.000000000 +0200 +++ new/zk-0.15.5/go.mod 2026-06-08 13:03:02.000000000 +0200 @@ -12,7 +12,7 @@ github.com/google/go-cmp v0.5.8 github.com/gosimple/slug v1.12.0 github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 - github.com/lestrrat-go/strftime v1.0.6 + github.com/lestrrat-go/strftime v1.1.1 github.com/mattn/go-isatty v0.0.14 github.com/mattn/go-sqlite3 v1.14.22 github.com/mvdan/xurls v1.1.0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/zk-0.15.4/go.sum new/zk-0.15.5/go.sum --- old/zk-0.15.4/go.sum 2026-05-04 14:26:40.000000000 +0200 +++ new/zk-0.15.5/go.sum 2026-06-08 13:03:02.000000000 +0200 @@ -102,8 +102,8 @@ github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc h1:RKf14vYWi2ttpEmkA4aQ3j4u9dStX2t4M8UM6qqNsG8= github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc/go.mod h1:kopuH9ugFRkIXf3YoqHKyrJ9YfUFsckUU9S7B+XP+is= -github.com/lestrrat-go/strftime v1.0.6 h1:CFGsDEt1pOpFNU+TJB0nhz9jl+K0hZSLE205AhTIGQQ= -github.com/lestrrat-go/strftime v1.0.6/go.mod h1:f7jQKgV5nnJpYgdEasS+/y7EsTb8ykN2z68n3TtcTaw= +github.com/lestrrat-go/strftime v1.1.1 h1:zgf8QCsgj27GlKBy3SU9/8MMgegZ8UCzlCyHYrUF0QU= +github.com/lestrrat-go/strftime v1.1.1/go.mod h1:YDrzHJAODYQ+xxvrn5SG01uFIQAeDTzpxNVppCz7Nmw= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= @@ -174,8 +174,9 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/tj/assert v0.0.0-20190920132354-ee03d75cd160 h1:NSWpaDaurcAJY7PkL8Xt0PhZE7qpvbZl5ljd8r6U0bI= github.com/tj/assert v0.0.0-20190920132354-ee03d75cd160/go.mod h1:mZ9/Rh9oLWpLLDRpvE+3b7gP/C2YyLFYxNmcLnPTMe0= github.com/tj/go-naturaldate v1.3.0 h1:OgJIPkR/Jk4bFMBLbxZ8w+QUxwjqSvzd9x+yXocY4RI= @@ -264,5 +265,6 @@ gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/zk-0.15.4/internal/adapter/handlebars/handlebars_test.go new/zk-0.15.5/internal/adapter/handlebars/handlebars_test.go --- old/zk-0.15.4/internal/adapter/handlebars/handlebars_test.go 2026-05-04 14:26:40.000000000 +0200 +++ new/zk-0.15.5/internal/adapter/handlebars/handlebars_test.go 2026-06-08 13:03:02.000000000 +0200 @@ -238,6 +238,8 @@ testString(t, "{{format-date now 'timestamp'}}", context, "200911172034") testString(t, "{{format-date now 'timestamp-unix'}}", context, "1258490098") testString(t, "{{format-date now 'cust: %Y-%m'}}", context, "cust: 2009-11") + testString(t, "{{format-date now 'cust: %G-%m'}}", context, "cust: 2009-11") + testString(t, "{{format-date now 'cust: %g-%m'}}", context, "cust: 09-11") } func TestFormatDateHelperElapsedYear(t *testing.T) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/zk-0.15.4/internal/adapter/lsp/cmd_new.go new/zk-0.15.5/internal/adapter/lsp/cmd_new.go --- old/zk-0.15.4/internal/adapter/lsp/cmd_new.go 2026-05-04 14:26:40.000000000 +0200 +++ new/zk-0.15.5/internal/adapter/lsp/cmd_new.go 2026-06-08 13:03:02.000000000 +0200 @@ -24,6 +24,7 @@ Date string `json:"date"` Edit jsonBoolean `json:"edit"` DryRun jsonBoolean `json:"dryRun"` + Append bool `json:"append"` InsertLinkAtLocation *protocol.Location `json:"insertLinkAtLocation"` InsertContentAtLocation *protocol.Location `json:"insertContentAtLocation"` } @@ -85,10 +86,23 @@ if !opts.DryRun && opts.InsertLinkAtLocation != nil { minNote := note.AsMinimalNote() + var prefix string + // Inserts link inline after selected text. + if opts.Append { + r := opts.InsertLinkAtLocation.Range + opts.InsertLinkAtLocation.Range = protocol.Range{ + Start: r.End, + End: r.End, + } + // Seperate last selected character and link with a space. + prefix = " " + } + info := &linkInfo{ note: &minNote, location: opts.InsertLinkAtLocation, title: &opts.Title, + prefix: prefix, } err := linkNote(notebook, documents, context, info) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/zk-0.15.4/internal/adapter/lsp/server.go new/zk-0.15.5/internal/adapter/lsp/server.go --- old/zk-0.15.4/internal/adapter/lsp/server.go 2026-05-04 14:26:40.000000000 +0200 +++ new/zk-0.15.5/internal/adapter/lsp/server.go 2026-06-08 13:03:02.000000000 +0200 @@ -325,7 +325,7 @@ return nil, err } - if isTrue(clientCapabilities.TextDocument.Definition.LinkSupport) { + if definitionLinkSupport(clientCapabilities) { return protocol.LocationLink{ OriginSelectionRange: &link.Range, TargetURI: target.URI, @@ -936,6 +936,11 @@ return v != nil && *v } +// definitionLinkSupport reports whether the client advertised textDocument.definition.linkSupport=true. +func definitionLinkSupport(caps protocol.ClientCapabilities) bool { + return caps.TextDocument != nil && caps.TextDocument.Definition != nil && isTrue(caps.TextDocument.Definition.LinkSupport) +} + func stringPtr(v string) *string { s := v return &s diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/zk-0.15.4/internal/adapter/lsp/server_test.go new/zk-0.15.5/internal/adapter/lsp/server_test.go --- old/zk-0.15.4/internal/adapter/lsp/server_test.go 2026-05-04 14:26:40.000000000 +0200 +++ new/zk-0.15.5/internal/adapter/lsp/server_test.go 2026-06-08 13:03:02.000000000 +0200 @@ -169,3 +169,40 @@ }) } } + +func TestDefinitionLinkSupport_NilCapabilities(t *testing.T) { + caps := protocol.ClientCapabilities{} + assert.Equal(t, definitionLinkSupport(caps), false) + + caps = protocol.ClientCapabilities{ + TextDocument: &protocol.TextDocumentClientCapabilities{}, + } + assert.Equal(t, definitionLinkSupport(caps), false) + + caps = protocol.ClientCapabilities{ + TextDocument: &protocol.TextDocumentClientCapabilities{ + Definition: &protocol.DefinitionClientCapabilities{}, + }, + } + assert.Equal(t, definitionLinkSupport(caps), false) + + flag := false + caps = protocol.ClientCapabilities{ + TextDocument: &protocol.TextDocumentClientCapabilities{ + Definition: &protocol.DefinitionClientCapabilities{ + LinkSupport: &flag, + }, + }, + } + assert.Equal(t, definitionLinkSupport(caps), false) + + flag = true + caps = protocol.ClientCapabilities{ + TextDocument: &protocol.TextDocumentClientCapabilities{ + Definition: &protocol.DefinitionClientCapabilities{ + LinkSupport: &flag, + }, + }, + } + assert.Equal(t, definitionLinkSupport(caps), true) +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/zk-0.15.4/internal/adapter/lsp/util.go new/zk-0.15.5/internal/adapter/lsp/util.go --- old/zk-0.15.4/internal/adapter/lsp/util.go 2026-05-04 14:26:40.000000000 +0200 +++ new/zk-0.15.5/internal/adapter/lsp/util.go 2026-06-08 13:03:02.000000000 +0200 @@ -67,6 +67,7 @@ note *core.MinimalNote location *protocol.Location title *string + prefix string } func linkNote(notebook *core.Notebook, documents *documentStore, context *glsp.Context, info *linkInfo) error { @@ -108,6 +109,8 @@ return err } + link = info.prefix + link + go context.Call(protocol.ServerWorkspaceApplyEdit, protocol.ApplyWorkspaceEditParams{ Edit: protocol.WorkspaceEdit{ Changes: map[string][]protocol.TextEdit{ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/zk-0.15.4/internal/adapter/sqlite/note_dao.go new/zk-0.15.5/internal/adapter/sqlite/note_dao.go --- old/zk-0.15.4/internal/adapter/sqlite/note_dao.go 2026-05-04 14:26:40.000000000 +0200 +++ new/zk-0.15.5/internal/adapter/sqlite/note_dao.go 2026-06-08 13:03:02.000000000 +0200 @@ -691,6 +691,14 @@ )`) } + if opts.BrokenLinks { + whereExprs = append(whereExprs, `n.id IN ( + SELECT DISTINCT source_id + FROM links + WHERE external = 0 AND target_id IS NULL + )`) + } + if opts.CreatedStart != nil { whereExprs = append(whereExprs, "created >= ?") args = append(args, opts.CreatedStart) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/zk-0.15.4/internal/adapter/sqlite/note_dao_test.go new/zk-0.15.5/internal/adapter/sqlite/note_dao_test.go --- old/zk-0.15.4/internal/adapter/sqlite/note_dao_test.go 2026-05-04 14:26:40.000000000 +0200 +++ new/zk-0.15.5/internal/adapter/sqlite/note_dao_test.go 2026-06-08 13:03:02.000000000 +0200 @@ -1023,6 +1023,13 @@ ) } +func TestNoteDAOFindBrokenLinks(t *testing.T) { + testNoteDAOFindPaths(t, + core.NoteFindOpts{BrokenLinks: true}, + []string{"index.md"}, + ) +} + func TestNoteDAOFindCreatedOn(t *testing.T) { start := time.Date(2020, 11, 22, 0, 0, 0, 0, time.UTC) end := time.Date(2020, 11, 23, 0, 0, 0, 0, time.UTC) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/zk-0.15.4/internal/cli/filtering.go new/zk-0.15.5/internal/cli/filtering.go --- old/zk-0.15.4/internal/cli/filtering.go 2026-05-04 14:26:40.000000000 +0200 +++ new/zk-0.15.5/internal/cli/filtering.go 2026-06-08 13:03:02.000000000 +0200 @@ -30,6 +30,7 @@ Orphan bool `kong:"group='filter',help='Find notes which are not linked by any other note.'" json:"orphan"` Tagless bool `kong:"group='filter',help='Find notes which have no tags.'" json:"tagless"` MissingBacklink bool `kong:"group='filter',help='Find notes with at least one missing backlink.'" json:"missingBacklink"` + BrokenLinks bool `kong:"group='filter',help='Find notes with at least one broken internal link.'" json:"brokenLinks"` Related []string `kong:"group='filter',placeholder='PATH',help='Find notes which might be related to the given ones.'" json:"related"` MaxDistance int `kong:"group='filter',placeholder='COUNT',help='Maximum distance between two linked notes.'" json:"maxDistance"` Recursive bool `kong:"group='filter',short='r',help='Follow links recursively.'" json:"recursive"` @@ -90,6 +91,7 @@ f.Orphan = f.Orphan || parsedFilter.Orphan f.Tagless = f.Tagless || parsedFilter.Tagless f.MissingBacklink = f.MissingBacklink || parsedFilter.MissingBacklink + f.BrokenLinks = f.BrokenLinks || parsedFilter.BrokenLinks f.Recursive = f.Recursive || parsedFilter.Recursive if f.Limit == 0 { @@ -206,6 +208,7 @@ opts.Orphan = f.Orphan opts.Tagless = f.Tagless opts.MissingBacklink = f.MissingBacklink + opts.BrokenLinks = f.BrokenLinks if f.Created != "" { start, end, err := parseDayRange(f.Created) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/zk-0.15.4/internal/core/note_find.go new/zk-0.15.5/internal/core/note_find.go --- old/zk-0.15.4/internal/core/note_find.go 2026-05-04 14:26:40.000000000 +0200 +++ new/zk-0.15.5/internal/core/note_find.go 2026-06-08 13:03:02.000000000 +0200 @@ -42,6 +42,8 @@ Tagless bool // Filter to select notes with at least one missing backlink. MissingBacklink bool + // Filter to select notes with at least one broken internal link. + BrokenLinks bool // Filter notes created after the given date. CreatedStart *time.Time // Filter notes created before the given date. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/zk-0.15.4/main.go new/zk-0.15.5/main.go --- old/zk-0.15.4/main.go 2026-05-04 14:26:40.000000000 +0200 +++ new/zk-0.15.5/main.go 2026-06-08 13:03:02.000000000 +0200 @@ -16,6 +16,7 @@ "github.com/zk-org/zk/internal/cli/cmd" "github.com/zk-org/zk/internal/core" executil "github.com/zk-org/zk/internal/util/exec" + "github.com/zk-org/zk/internal/util/paths" ) var Version = "dev" @@ -307,7 +308,11 @@ } if option != "" && value != "" { - path, err := filepath.Abs(value) + valueAbs, err := paths.ExpandPath(value) + if err != nil { + return "", newArgs, err + } + path, err := filepath.Abs(valueAbs) return path, newArgs, err } else if option != "" && value == "" { return "", newArgs, errors.New(option + " requires a path argument") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/zk-0.15.4/main_test.go new/zk-0.15.5/main_test.go --- old/zk-0.15.4/main_test.go 1970-01-01 01:00:00.000000000 +0100 +++ new/zk-0.15.5/main_test.go 2026-06-08 13:03:02.000000000 +0200 @@ -0,0 +1,61 @@ +package main + +import ( + "os" + "os/user" + "testing" + + "github.com/zk-org/zk/internal/cli" +) + +func Test_parseDirsPathExpansion(t *testing.T) { + user, _ := user.Current() + _ = os.Setenv("FOO", "/home/foo") + tests := []struct { + name string + args []string + wantDirs cli.Dirs + }{ + { + name: "With tilde (working dir)", + args: []string{"--working-dir=~/notes"}, + wantDirs: cli.Dirs{WorkingDir: user.HomeDir + "/notes"}, + }, + { + name: "With tilde (notebook dir)", + args: []string{"--notebook-dir=~/notes"}, + wantDirs: cli.Dirs{NotebookDir: user.HomeDir + "/notes"}, + }, + { + name: "With absolute path", + args: []string{"--notebook-dir=" + user.HomeDir + "/notes"}, + wantDirs: cli.Dirs{NotebookDir: user.HomeDir + "/notes"}, + }, + { + name: "With environment variable in path", + args: []string{"--notebook-dir=${FOO}/notes"}, + wantDirs: cli.Dirs{NotebookDir: os.Getenv("FOO") + "/notes"}, + }, + { + name: "With environment variable and two string argument", + args: []string{"--notebook-dir", "${FOO}/notes"}, + wantDirs: cli.Dirs{NotebookDir: os.Getenv("FOO") + "/notes"}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cliDirs, _, gotErr := parseDirs(tt.args) + workDir := cliDirs.WorkingDir + noteDir := cliDirs.NotebookDir + if gotErr != nil { + t.Errorf("parseDirs() failed: %v", gotErr) + } + if workDir != tt.wantDirs.WorkingDir { + t.Errorf("parseDirs() got WorkingDir = %v, want %v", cliDirs.WorkingDir, tt.wantDirs.WorkingDir) + } + if noteDir != tt.wantDirs.NotebookDir { + t.Errorf("parseDirs() got NotebookDir = %v, want %v", cliDirs.NotebookDir, tt.wantDirs.NotebookDir) + } + }) + } +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/zk-0.15.4/tests/cmd-graph.tesh new/zk-0.15.5/tests/cmd-graph.tesh --- old/zk-0.15.4/tests/cmd-graph.tesh 2026-05-04 14:26:40.000000000 +0200 +++ new/zk-0.15.5/tests/cmd-graph.tesh 2026-06-08 13:03:02.000000000 +0200 @@ -46,6 +46,8 @@ > --tagless Find notes which have no tags. > --missing-backlink Find notes with at least one missing > backlink. +> --broken-links Find notes with at least one broken internal +> link. > --related=PATH,... Find notes which might be related to the > given ones. > --max-distance=COUNT Maximum distance between two linked notes. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/zk-0.15.4/tests/cmd-list.tesh new/zk-0.15.5/tests/cmd-list.tesh --- old/zk-0.15.4/tests/cmd-list.tesh 2026-05-04 14:26:40.000000000 +0200 +++ new/zk-0.15.5/tests/cmd-list.tesh 2026-06-08 13:03:02.000000000 +0200 @@ -54,6 +54,8 @@ > --tagless Find notes which have no tags. > --missing-backlink Find notes with at least one missing > backlink. +> --broken-links Find notes with at least one broken internal +> link. > --related=PATH,... Find notes which might be related to the > given ones. > --max-distance=COUNT Maximum distance between two linked notes.
