Skip to content

docs: format code snippets in markdown files #1324

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

Merged
merged 2 commits into from
May 24, 2025
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
34 changes: 33 additions & 1 deletion .github/workflows/lint.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,38 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: DavidAnson/markdownlint-cli2-action@v20

- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: stable

- name: Setup mdsf
uses: hougesen/[email protected]

- name: Setup goimports
# https://pkg.go.dev/golang.org/x/tools/cmd/goimports
run: go install golang.org/x/tools/cmd/[email protected]

- name: Setup shfmt
# https://github.com/mvdan/sh#shfmt
run: go install mvdan.cc/sh/v3/cmd/[email protected]

- name: Setup taplo
# https://taplo.tamasfe.dev/cli/installation/binary.html
run: curl -fsSL https://github.com/tamasfe/taplo/releases/download/0.10.0/taplo-linux-x86_64.gz | gzip -d - | install -m 755 /dev/stdin /usr/local/bin/taplo

- name: Verify files format using markdownlint-cli2
uses: DavidAnson/markdownlint-cli2-action@v20
with:
config: .markdownlint-cli2.yaml

- name: Verify code snippets using mdsf
id: verify_snippets
run: mdsf verify --on-missing-language-definition ignore --on-missing-tool-binary fail-fast .

- name: Show diff when mdsf failed
if: failure() && steps.verify_snippets.outcome == 'failure'
run: |
mdsf format --debug --on-missing-language-definition ignore --on-missing-tool-binary fail-fast .
git diff --exit-code
25 changes: 20 additions & 5 deletions DEVELOPING.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ We can set the banned identifier by using the TOML configuration file:

```toml
[rule.ban-struct-name]
arguments = ["Foo"]
arguments = ["Foo"]
```

With the snippet above we:
Expand Down Expand Up @@ -89,12 +89,17 @@ type Formatter interface {

### Lint Markdown files

We are using [markdownlint](https://github.com/DavidAnson/markdownlint) for checking Markdown files.
We use [markdownlint](https://github.com/DavidAnson/markdownlint) and [mdsf](https://github.com/hougesen/mdsf) to check Markdown files.
`markdownlint` verifies document formatting, such as line length and empty lines, while `mdsf` is responsible for formatting code snippets.

1. Install [markdownlint-cli2](https://github.com/DavidAnson/markdownlint-cli2#install).
2. Run the following command:
2. Install [mdsf](https://mdsf.mhouge.dk/#installation) and formatters:
- [goimports](https://pkg.go.dev/golang.org/x/tools/cmd/goimports) for `go`: `go install golang.org/x/tools/cmd/goimports@latest`
- [shfmt](https://github.com/mvdan/sh#shfmt) for `sh, shell, bash`: `go install mvdan.cc/sh/v3/cmd/shfmt@latest`
- [taplo](https://taplo.tamasfe.dev/cli/installation/binary.html) for `toml`
3. Run the following command to check formatting:

```sh
```shellsession
$ markdownlint-cli2 .
Finding: *.{md,markdown} *.md
Found:
Expand All @@ -107,4 +112,14 @@ Linting: 5 file(s)
Summary: 0 error(s)
```

The tool automatically uses the config file [.markdownlint-cli2.yaml](./.markdownlint-cli2.yaml).
_The `markdownlint-cli2` tool automatically uses the config file [.markdownlint-cli2.yaml](./.markdownlint-cli2.yaml)._
\
4. Run the following commands to verify and format code snippets:

```sh
mdsf verify .
```

```sh
mdsf format .
```
98 changes: 52 additions & 46 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ A volume must be mounted to share the current repository with the container.
Please refer to the [bind mounts Docker documentation](https://docs.docker.com/storage/bind-mounts/)

```bash
docker run -v "$(pwd)":/var/<repository> ghcr.io/mgechev/revive:v1.3.7 -config /var/<repository>/revive.toml -formatter stylish ./var/kidle/...
docker run -v "$(pwd)":/var/YOUR_REPOSITORY ghcr.io/mgechev/revive:v1.3.7 -config /var/YOUR_REPOSITORY/revive.toml -formatter stylish ./var/YOUR_REPOSITORY/...
```

- `-v` is for the volume
Expand Down Expand Up @@ -238,6 +238,7 @@ Using comments, you can disable the linter for the entire file or only a range o
//revive:disable

func Public() {}

//revive:enable
```

Expand All @@ -251,8 +252,9 @@ You can do the same on a rule level. In case you want to disable only a particul
```go
//revive:disable:unexported-return
func Public() private {
return private
return private
}

//revive:enable:unexported-return
```

Expand All @@ -278,7 +280,7 @@ in the configuration. You can set the severity (defaults to _warning_) of the vi

```toml
[directive.specify-disable-reason]
severity = "error"
severity = "error"
```

### Configuration
Expand All @@ -305,11 +307,11 @@ warningCode = 0
# Configuration of the `cyclomatic` rule. Here we specify that
# the rule should fail if it detects code with higher complexity than 10.
[rule.cyclomatic]
arguments = [10]
arguments = [10]

# Sets the severity of the `package-comments` rule to "error".
[rule.package-comments]
severity = "error"
severity = "error"
```

By default `revive` will enable only the linting rules that are named in the configuration file.
Expand All @@ -328,7 +330,7 @@ For example:

```toml
[rule.line-length-limit]
Disabled = true
Disabled = true
```

When enabling all rules you still need/can provide specific configurations for rules.
Expand All @@ -346,29 +348,29 @@ enableAllRules = true

# Disabled rules
[rule.blank-imports]
Disabled = true
Disabled = true
[rule.file-header]
Disabled = true
Disabled = true
[rule.max-public-structs]
Disabled = true
Disabled = true
[rule.line-length-limit]
Disabled = true
Disabled = true
[rule.function-length]
Disabled = true
Disabled = true
[rule.banned-characters]
Disabled = true
Disabled = true

# Rule tuning
[rule.argument-limit]
Arguments = [5]
Arguments = [5]
[rule.cyclomatic]
Arguments = [10]
Arguments = [10]
[rule.cognitive-complexity]
Arguments = [7]
Arguments = [7]
[rule.function-result-limit]
Arguments = [3]
Arguments = [3]
[rule.error-strings]
Arguments = ["mypackage.Error"]
Arguments = ["mypackage.Error"]
```

### Default Configuration
Expand Down Expand Up @@ -440,9 +442,9 @@ errorCode = 0
warningCode = 0

[rule.blank-imports]
Exclude=["**/*.pb.go"]
Exclude = ["**/*.pb.go"]
[rule.context-as-argument]
Exclude=["src/somepkg/*.go", "TEST"]
Exclude = ["src/somepkg/*.go", "TEST"]
```

You can use the following exclude patterns
Expand Down Expand Up @@ -560,7 +562,7 @@ in `golint` but optionally, you can relax it (see [golint/lint/issues/89](https:

```toml
[rule.var-naming]
arguments = [["ID"], ["VM"]]
arguments = [["ID"], ["VM"]]
```

This way, revive will not warn for an identifier called `customId` but will warn that `customVm` should be called `customVM`.
Expand Down Expand Up @@ -657,7 +659,9 @@ func (f myRule) Name() string {
return "myRule"
}

func (f myRule) Apply(*lint.File, lint.Arguments) []lint.Failure { ... }
func (f myRule) Apply(*lint.File, lint.Arguments) []lint.Failure {
// ...
}
```

You can still go further and use `revive` without its CLI, as part of your library, or your CLI:
Expand All @@ -666,39 +670,39 @@ You can still go further and use `revive` without its CLI, as part of your libra
package mylib

import (
"github.com/mgechev/revive/cli"
"github.com/mgechev/revive/revivelib"
"github.com/mgechev/revive/config"
"github.com/mgechev/revive/lint"
"github.com/mgechev/revive/revivelib"
)

// Error checking removed for clarity
func LintMyFile(file string) {
conf, _:= config.GetConfig("../defaults.toml")
conf, _ := config.GetConfig("../defaults.toml")

revive, _ := revivelib.New(
conf, // Configuration file
true, // Set exit status
2048, // Max open files
conf, // Configuration file
true, // Set exit status
2048, // Max open files

// Then add as many extra rules as you need
revivelib.NewExtraRule(&myRule{}, lint.RuleConfig{}),
)

failuresChan, err := revive.Lint(
revivelib.Include(file),
revivelib.Exclude("./fixtures"),
// You can use as many revivelib.Include or revivelib.Exclude as required
)
if err != nil {
panic("Shouldn't have failed: " + err.Error())
}

// Now let's return the formatted errors
revivelib.Include(file),
revivelib.Exclude("./fixtures"),
// You can use as many revivelib.Include or revivelib.Exclude as required
)
if err != nil {
panic("Shouldn't have failed: " + err.Error())
}

// Now let's return the formatted errors
failures, exitCode, _ := revive.Format("stylish", failuresChan)

// failures is the string with all formatted lint error messages
// exit code is 0 if no errors, 1 if errors (unless config options change it)
// ... do something with them
// failures is the string with all formatted lint error messages
// exit code is 0 if no errors, 1 if errors (unless config options change it)
// ... do something with them
}

type myRule struct{}
Expand All @@ -707,7 +711,9 @@ func (f myRule) Name() string {
return "myRule"
}

func (f myRule) Apply(*lint.File, lint.Arguments) []lint.Failure { ... }
func (f myRule) Apply(*lint.File, lint.Arguments) []lint.Failure {
// ...
}
```

### Custom Formatter
Expand All @@ -734,8 +740,8 @@ Here's a basic performance benchmark on MacBook Pro Early 2013 run on Kubernetes

### golint

```shell
time golint kubernetes/... > /dev/null
```shellsession
$ time golint kubernetes/... > /dev/null

real 0m54.837s
user 0m57.844s
Expand All @@ -744,9 +750,9 @@ sys 0m9.146s

### revive's speed

```shell
```shellsession
# no type checking
time revive -config untyped.toml kubernetes/... > /dev/null
$ time revive -config untyped.toml kubernetes/... > /dev/null

real 0m8.471s
user 0m40.721s
Expand All @@ -755,9 +761,9 @@ sys 0m3.262s

Keep in mind that if you use rules that require type checking, the performance may drop to 2x faster than `golint`:

```shell
```shellsession
# type checking enabled
time revive kubernetes/... > /dev/null
$ time revive kubernetes/... > /dev/null

real 0m26.211s
user 2m6.708s
Expand Down
Loading