diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml deleted file mode 100644 index aa906a48e..000000000 --- a/.github/workflows/docs.yml +++ /dev/null @@ -1,70 +0,0 @@ -name: Documentation compatibility - -on: - push: - branches: [master] - pull_request: - branches: [master] - workflow_dispatch: - -permissions: - contents: read - -jobs: - examples: - name: Compile source-owned examples - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v6 - - uses: actions/setup-go@v6 - with: - go-version: '1.27' - cache-dependency-path: docs/examples/go.sum - - name: Compile examples against this Echo revision - run: go test ./... - working-directory: docs/examples - - name: Extract source-backed config fields - run: go run ./cmd/config-fields -revision "$GITHUB_SHA" > config-fields.json - working-directory: docs/examples - - name: Keep the generated reference for the website integration - uses: actions/upload-artifact@v4 - with: - name: echo-config-fields - path: docs/examples/config-fields.json - - website: - name: Build echox against this Echo revision - runs-on: ubuntu-latest - steps: - - name: Checkout Echo - uses: actions/checkout@v6 - with: - path: echo - - name: Checkout website - uses: actions/checkout@v6 - with: - repository: labstack/echox - path: echox - - uses: actions/setup-go@v6 - with: - go-version: '1.27' - cache-dependency-path: echox/go.sum - - name: Use proposed Echo source for cookbook tests - run: go work init ../echo . - working-directory: echox - - name: Compile cookbook examples - run: go test ./... - working-directory: echox - - uses: actions/setup-node@v6 - with: - node-version: '24' - cache: npm - cache-dependency-path: echox/site/package-lock.json - - name: Install site dependencies - run: npm ci --ignore-scripts - working-directory: echox/site - - name: Build site - run: npm run build - working-directory: echox/site - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/docs/examples/.gitignore b/docs/examples/.gitignore deleted file mode 100644 index 2c846f858..000000000 --- a/docs/examples/.gitignore +++ /dev/null @@ -1 +0,0 @@ -config-fields.json diff --git a/docs/examples/README.md b/docs/examples/README.md deleted file mode 100644 index e8058db7d..000000000 --- a/docs/examples/README.md +++ /dev/null @@ -1,27 +0,0 @@ -# Echo documentation examples - -These complete programs are intended to be the source for code displayed on the -Echo website. The site should embed the files directly instead of maintaining -copied snippets. -They compile against the Echo checkout that contains them. - -Run `go test ./...` from this directory. The nested module keeps example-only -dependencies and files out of the published Echo library module. The local -`replace` directive is intentional: it makes an Echo pull request test its own -source rather than a previously released version. - -To try the Static example, run `go run .` from `static/`, then open -`http://localhost:1323/`. Its `public/index.html` is the file served at `/`. - -`go run ./cmd/config-fields -root ../.. -revision ` emits deterministic -JSON for exported middleware `*Config` fields, types, deprecation markers, and -source line numbers. It is source data for the website, not a published page. -It does not generate runtime defaults, behavior claims, or security guidance. - -The Echo documentation workflow also checks out `echox`, compiles its cookbook -against the proposed Echo checkout using a temporary Go workspace, and builds -the current site. A future `echox` change will consume the JSON and these exact -example files before the reference-drift check becomes a required gate. - -This is the first source-owned slice: Request Logger and Static. Behavior notes, -security guidance, and translated explanations remain authored in `echox`. diff --git a/docs/examples/REFERENCE_TRIAL.md b/docs/examples/REFERENCE_TRIAL.md deleted file mode 100644 index 77d21d300..000000000 --- a/docs/examples/REFERENCE_TRIAL.md +++ /dev/null @@ -1,23 +0,0 @@ -# API reference tool trial - -The first trial used `gomarkdoc` v1.1.0 against this Echo checkout's -`middleware` package, which includes CORS, Request Logger, and Static, and -against the external `github.com/labstack/echo-jwt/v5` package from the current -`echox` module. The package output was 2,422 lines for core middleware and 389 -lines for JWT. `gomarkdoc --check --output ...` successfully detected that the -unmodified generated core file matched its source. The output included -`EnablePathUnescaping` and excluded the removed `RequestLoggerConfig.LogError`. - -`--embed` supports marked regions within authored Markdown. A check against an -unmarked, fully generated file failed because embed mode would append a second -generated block. This confirms that an existing page must add embed markers -before using that mode. Templates can change generated Markdown, but this -package-wide output is too broad for individual middleware pages and is not a -machine-readable field manifest. Those two requirements motivate the small -`config-fields` extractor in this module. It extracts only fields, types, -deprecation markers, and source positions; it does not infer defaults or -rewrite authored pages. - -The site integration will separately evaluate a targeted `gomarkdoc` template -and marked embedding on a real page before choosing how to render reference -sections. This trial does not justify generating behavior explanations. diff --git a/docs/examples/cmd/config-fields/main.go b/docs/examples/cmd/config-fields/main.go deleted file mode 100644 index 7748f8848..000000000 --- a/docs/examples/cmd/config-fields/main.go +++ /dev/null @@ -1,128 +0,0 @@ -// SPDX-License-Identifier: MIT - -// config-fields emits source-backed middleware config fields for the website. -// It does not claim to determine runtime defaults or behavior. -package main - -import ( - "bytes" - "encoding/json" - "flag" - "fmt" - "go/ast" - "go/format" - "go/parser" - "go/token" - "os" - "path/filepath" - "sort" - "strings" -) - -type field struct { - Name string `json:"name"` - Type string `json:"type"` - Deprecated bool `json:"deprecated,omitempty"` - Line int `json:"line"` -} - -type config struct { - Name string `json:"name"` - File string `json:"file"` - Line int `json:"line"` - Fields []field `json:"fields"` -} - -type manifest struct { - Module string `json:"module"` - Revision string `json:"revision,omitempty"` - Configs []config `json:"configs"` -} - -func main() { - root := flag.String("root", "../..", "Echo repository root, relative to the current directory") - revision := flag.String("revision", "", "exact Echo commit or tag used for this build") - flag.Parse() - - result, err := extract(*root, *revision) - if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(1) - } - encoder := json.NewEncoder(os.Stdout) - encoder.SetIndent("", " ") - if err := encoder.Encode(result); err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(1) - } -} - -func extract(root, revision string) (manifest, error) { - root, err := filepath.Abs(root) - if err != nil { - return manifest{}, err - } - fs := token.NewFileSet() - packageDir := filepath.Join(root, "middleware") - packages, err := parser.ParseDir(fs, packageDir, func(info os.FileInfo) bool { - return strings.HasSuffix(info.Name(), ".go") && !strings.HasSuffix(info.Name(), "_test.go") - }, parser.ParseComments) - if err != nil { - return manifest{}, err - } - pkg, ok := packages["middleware"] - if !ok { - return manifest{}, fmt.Errorf("middleware package not found in %s", packageDir) - } - - result := manifest{Module: "github.com/labstack/echo/v5", Revision: revision, Configs: []config{}} - for filename, source := range pkg.Files { - for _, declaration := range source.Decls { - group, ok := declaration.(*ast.GenDecl) - if !ok || group.Tok != token.TYPE { - continue - } - for _, item := range group.Specs { - typeSpec := item.(*ast.TypeSpec) - structure, ok := typeSpec.Type.(*ast.StructType) - if !ok || !ast.IsExported(typeSpec.Name.Name) || !strings.HasSuffix(typeSpec.Name.Name, "Config") { - continue - } - entry := config{ - Name: typeSpec.Name.Name, - File: filepath.ToSlash(strings.TrimPrefix(filename, root+string(filepath.Separator))), - Line: fs.Position(typeSpec.Pos()).Line, - Fields: []field{}, - } - for _, sourceField := range structure.Fields.List { - var rendered bytes.Buffer - if err := format.Node(&rendered, fs, sourceField.Type); err != nil { - return manifest{}, err - } - fieldDoc := comment(sourceField.Doc) - for _, name := range sourceField.Names { - if !ast.IsExported(name.Name) { - continue - } - entry.Fields = append(entry.Fields, field{ - Name: name.Name, - Type: rendered.String(), - Deprecated: strings.Contains(fieldDoc, "Deprecated:"), - Line: fs.Position(name.Pos()).Line, - }) - } - } - result.Configs = append(result.Configs, entry) - } - } - } - sort.Slice(result.Configs, func(i, j int) bool { return result.Configs[i].Name < result.Configs[j].Name }) - return result, nil -} - -func comment(group *ast.CommentGroup) string { - if group == nil { - return "" - } - return strings.TrimSpace(group.Text()) -} diff --git a/docs/examples/cmd/config-fields/main_test.go b/docs/examples/cmd/config-fields/main_test.go deleted file mode 100644 index 33a402969..000000000 --- a/docs/examples/cmd/config-fields/main_test.go +++ /dev/null @@ -1,45 +0,0 @@ -// SPDX-License-Identifier: MIT - -package main - -import ( - "os" - "path/filepath" - "testing" -) - -func TestExtractOnlyExportedConfigFields(t *testing.T) { - root := t.TempDir() - dir := filepath.Join(root, "middleware") - if err := os.Mkdir(dir, 0755); err != nil { - t.Fatal(err) - } - source := `package middleware -type ExampleConfig struct { - // Deprecated: use New instead. - Old bool - New string - private int -} -type hiddenConfig struct { Visible bool } -type OtherType struct { Visible bool } -` - if err := os.WriteFile(filepath.Join(dir, "example.go"), []byte(source), 0644); err != nil { - t.Fatal(err) - } - - got, err := extract(root, "abc123") - if err != nil { - t.Fatal(err) - } - if got.Revision != "abc123" || len(got.Configs) != 1 { - t.Fatalf("unexpected manifest: %#v", got) - } - fields := got.Configs[0].Fields - if got.Configs[0].File != "middleware/example.go" || len(fields) != 2 { - t.Fatalf("unexpected config: %#v", got.Configs[0]) - } - if fields[0].Name != "Old" || fields[0].Type != "bool" || !fields[0].Deprecated || fields[1].Name != "New" { - t.Fatalf("unexpected fields: %#v", fields) - } -} diff --git a/docs/examples/go.mod b/docs/examples/go.mod deleted file mode 100644 index deafd6a52..000000000 --- a/docs/examples/go.mod +++ /dev/null @@ -1,9 +0,0 @@ -module github.com/labstack/echo/docs/examples - -go 1.25.0 - -require github.com/labstack/echo/v5 v5.3.0 - -require golang.org/x/time v0.15.0 // indirect - -replace github.com/labstack/echo/v5 => ../.. diff --git a/docs/examples/go.sum b/docs/examples/go.sum deleted file mode 100644 index 8b2a4ffa2..000000000 --- a/docs/examples/go.sum +++ /dev/null @@ -1,14 +0,0 @@ -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= -github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= -golang.org/x/net v0.57.0 h1:K5+3DljvIuDG9/Jv9rvyMywYNFCQ9RSUY6OOTTkT+tE= -golang.org/x/net v0.57.0/go.mod h1:KpXc8iv+r3XplLAG/f7Jsf9RPszJzdR0f58q9vGOuEU= -golang.org/x/text v0.40.0 h1:Ub2Z6/xjgF1WrYQz2nuITOEegKFtiIy+rieRJ5lHZKs= -golang.org/x/text v0.40.0/go.mod h1:hpnzDAfGV753zIKo+wk3u1bVKCGPbrnF7+7LBF/UHVY= -golang.org/x/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U= -golang.org/x/time v0.15.0/go.mod h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/docs/examples/request-logger/main.go b/docs/examples/request-logger/main.go deleted file mode 100644 index edbcbe57c..000000000 --- a/docs/examples/request-logger/main.go +++ /dev/null @@ -1,40 +0,0 @@ -// SPDX-License-Identifier: MIT - -// This complete example is the source for the Request Logger documentation. -package main - -import ( - "log/slog" - "net/http" - "os" - - "github.com/labstack/echo/v5" - "github.com/labstack/echo/v5/middleware" -) - -func main() { - e := echo.New() - logger := slog.New(slog.NewJSONHandler(os.Stdout, nil)) - - e.Use(middleware.RequestLoggerWithConfig(middleware.RequestLoggerConfig{ - LogURI: true, - LogStatus: true, - HandleError: true, - LogValuesFunc: func(c *echo.Context, v middleware.RequestLoggerValues) error { - if v.Error != nil { - logger.Error("request failed", "uri", v.URI, "status", v.Status, "error", v.Error) - return nil - } - logger.Info("request", "uri", v.URI, "status", v.Status) - return nil - }, - })) - - e.GET("/", func(c *echo.Context) error { - return c.String(http.StatusOK, "hello") - }) - - if err := e.Start(":1323"); err != nil { - e.Logger.Error("server stopped", "error", err) - } -} diff --git a/docs/examples/static/main.go b/docs/examples/static/main.go deleted file mode 100644 index 7c066599c..000000000 --- a/docs/examples/static/main.go +++ /dev/null @@ -1,21 +0,0 @@ -// SPDX-License-Identifier: MIT - -// This complete example is the source for the Static middleware documentation. -package main - -import ( - "github.com/labstack/echo/v5" - "github.com/labstack/echo/v5/middleware" -) - -func main() { - e := echo.New() - e.Use(middleware.StaticWithConfig(middleware.StaticConfig{ - Root: "public", - EnablePathUnescaping: false, // Keep encoded slashes encoded when route guards protect files. - })) - - if err := e.Start(":1323"); err != nil { - e.Logger.Error("server stopped", "error", err) - } -} diff --git a/docs/examples/static/public/index.html b/docs/examples/static/public/index.html deleted file mode 100644 index 5fbf861c6..000000000 --- a/docs/examples/static/public/index.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - Echo Static example - - -

Hello from Echo Static middleware

- -