From 6b8d588c434da5fdff472317fabcf0acf8f4207d Mon Sep 17 00:00:00 2001 From: Sergey Filkin Date: Sat, 18 Apr 2026 11:36:39 +0300 Subject: [PATCH] phase1: go module skeleton with subcommand stubs --- .air.toml | 8 +++ Makefile | 31 ++++++++++ cmd/md-to-html/main.go | 92 ++++++++++++++++++++++++++++ go.mod | 16 +++++ go.sum | 38 ++++++++++++ internal/converter/testdata/.gitkeep | 1 + internal/server/.gitkeep | 1 + internal/ui/components/.gitkeep | 1 + internal/version/version.go | 4 ++ tools.go | 14 +++++ web/static/src/.gitkeep | 1 + web/template/.gitkeep | 1 + 12 files changed, 208 insertions(+) create mode 100644 .air.toml create mode 100644 Makefile create mode 100644 cmd/md-to-html/main.go create mode 100644 go.mod create mode 100644 go.sum create mode 100644 internal/converter/testdata/.gitkeep create mode 100644 internal/server/.gitkeep create mode 100644 internal/ui/components/.gitkeep create mode 100644 internal/version/version.go create mode 100644 tools.go create mode 100644 web/static/src/.gitkeep create mode 100644 web/template/.gitkeep diff --git a/.air.toml b/.air.toml new file mode 100644 index 0000000..7a1f11f --- /dev/null +++ b/.air.toml @@ -0,0 +1,8 @@ +root = "." +tmp_dir = "tmp" + +[build] +cmd = "go build -o tmp/md-to-html ./cmd/md-to-html" +bin = "tmp/md-to-html serve" +exclude_dir = ["archive", "tmp", "bin", "web/static/dist", "node_modules", ".review-sandboxes", ".git"] +include_ext = ["go", "templ", "html"] diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..98d3514 --- /dev/null +++ b/Makefile @@ -0,0 +1,31 @@ +VERSION := $(shell cat VERSION) +LDFLAGS := -X github.com/fserg/md-to-html/internal/version.Version=$(VERSION) + +.PHONY: build run test templ tailwind dev docker clean tools + +build: + go build -ldflags "$(LDFLAGS)" -o bin/md-to-html ./cmd/md-to-html + +run: + go run ./cmd/md-to-html serve + +test: + go test ./... + +templ: + templ generate + +tailwind: + @echo "tailwind target will be implemented in phase 4" + +dev: + @echo "dev target will be implemented in phase 4" + +docker: + @echo "docker target will be implemented in phase 6" + +clean: + rm -rf bin/ tmp/ web/static/dist/ + +tools: + go install github.com/a-h/templ/cmd/templ@v0.3.1001 diff --git a/cmd/md-to-html/main.go b/cmd/md-to-html/main.go new file mode 100644 index 0000000..badd8bc --- /dev/null +++ b/cmd/md-to-html/main.go @@ -0,0 +1,92 @@ +package main + +import ( + "flag" + "fmt" + "io" + "os" + + "github.com/fserg/md-to-html/internal/version" +) + +func main() { + os.Exit(run(os.Args[1:], os.Stdout, os.Stderr)) +} + +func run(args []string, stdout, stderr io.Writer) int { + if len(args) == 0 { + printUsage(stdout) + return 0 + } + + switch args[0] { + case "-h", "--help", "help": + printUsage(stdout) + return 0 + case "serve": + return runServe(args[1:], stdout) + case "cli": + return runCLI(args[1:], stdout, stderr) + case "version": + return runVersion(args[1:], stdout, stderr) + default: + fmt.Fprintf(stderr, "unknown subcommand %q\n\n", args[0]) + printUsage(stderr) + return 2 + } +} + +func runServe(args []string, stdout io.Writer) int { + fs := flag.NewFlagSet("serve", flag.ContinueOnError) + fs.SetOutput(io.Discard) + if err := fs.Parse(args); err != nil { + return 2 + } + fmt.Fprintln(stdout, "serve not implemented yet") + return 0 +} + +func runCLI(args []string, stdout, stderr io.Writer) int { + fs := flag.NewFlagSet("cli", flag.ContinueOnError) + fs.SetOutput(io.Discard) + if err := fs.Parse(args); err != nil { + return 2 + } + + if fs.NArg() != 1 { + fmt.Fprintln(stderr, "usage: md-to-html cli ") + return 2 + } + + fmt.Fprintf(stdout, "cli not implemented yet: %s\n", fs.Arg(0)) + return 0 +} + +func runVersion(args []string, stdout, stderr io.Writer) int { + fs := flag.NewFlagSet("version", flag.ContinueOnError) + fs.SetOutput(io.Discard) + if err := fs.Parse(args); err != nil { + return 2 + } + + if fs.NArg() != 0 { + fmt.Fprintln(stderr, "usage: md-to-html version") + return 2 + } + + fmt.Fprintln(stdout, version.Version) + return 0 +} + +func printUsage(w io.Writer) { + fmt.Fprint(w, `Usage: + md-to-html serve + md-to-html cli + md-to-html version + +Commands: + serve Start the HTTP server stub + cli Convert a Markdown file stub + version Print the build version +`) +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..960cd23 --- /dev/null +++ b/go.mod @@ -0,0 +1,16 @@ +module github.com/fserg/md-to-html + +go 1.23.0 + +require ( + github.com/a-h/templ v0.3.1001 + github.com/alecthomas/chroma/v2 v2.23.1 + github.com/go-chi/chi/v5 v5.2.5 + github.com/google/uuid v1.6.0 + github.com/mozillazg/go-unidecode v0.2.0 + github.com/yuin/goldmark v1.7.17 + github.com/yuin/goldmark-emoji v1.0.6 + github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc +) + +require github.com/dlclark/regexp2 v1.11.5 // indirect diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..07e9991 --- /dev/null +++ b/go.sum @@ -0,0 +1,38 @@ +github.com/a-h/templ v0.3.1001 h1:yHDTgexACdJttyiyamcTHXr2QkIeVF1MukLy44EAhMY= +github.com/a-h/templ v0.3.1001/go.mod h1:oCZcnKRf5jjsGpf2yELzQfodLphd2mwecwG4Crk5HBo= +github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0= +github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k= +github.com/alecthomas/chroma/v2 v2.2.0/go.mod h1:vf4zrexSH54oEjJ7EdB65tGNHmH3pGZmVkgTP5RHvAs= +github.com/alecthomas/chroma/v2 v2.23.1 h1:nv2AVZdTyClGbVQkIzlDm/rnhk1E9bU9nXwmZ/Vk/iY= +github.com/alecthomas/chroma/v2 v2.23.1/go.mod h1:NqVhfBR0lte5Ouh3DcthuUCTUpDC9cxBOfyMbMQPs3o= +github.com/alecthomas/repr v0.0.0-20220113201626-b1b626ac65ae/go.mod h1:2kn6fqh/zIyPLmm3ugklbEi5hg5wS435eygvNfaDQL8= +github.com/alecthomas/repr v0.5.2 h1:SU73FTI9D1P5UNtvseffFSGmdNci/O6RsqzeXJtP0Qs= +github.com/alecthomas/repr v0.5.2/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= +github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= +github.com/dlclark/regexp2 v1.11.5 h1:Q/sSnsKerHeCkc/jSTNq1oCm7KiVgUMZRDUoRu0JQZQ= +github.com/dlclark/regexp2 v1.11.5/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= +github.com/go-chi/chi/v5 v5.2.5 h1:Eg4myHZBjyvJmAFjFvWgrqDTXFyOzjj7YIm3L3mu6Ug= +github.com/go-chi/chi/v5 v5.2.5/go.mod h1:X7Gx4mteadT3eDOMTsXzmI4/rwUpOwBHLpAfupzFJP0= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= +github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= +github.com/mozillazg/go-unidecode v0.2.0 h1:vFGEzAH9KSwyWmXCOblazEWDh7fOkpmy/Z4ArmamSUc= +github.com/mozillazg/go-unidecode v0.2.0/go.mod h1:zB48+/Z5toiRolOZy9ksLryJ976VIwmDmpQ2quyt1aA= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/yuin/goldmark v1.4.15/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/yuin/goldmark v1.7.17 h1:p36OVWwRb246iHxA/U4p8OPEpOTESm4n+g+8t0EE5uA= +github.com/yuin/goldmark v1.7.17/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg= +github.com/yuin/goldmark-emoji v1.0.6 h1:QWfF2FYaXwL74tfGOW5izeiZepUDroDJfWubQI9HTHs= +github.com/yuin/goldmark-emoji v1.0.6/go.mod h1:ukxJDKFpdFb5x0a5HqbdlcKtebh086iJpI31LTKmWuA= +github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc h1:+IAOyRda+RLrxa1WC7umKOZRsGq4QrFFMYApOeHzQwQ= +github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc/go.mod h1:ovIvrum6DQJA4QsJSovrkC4saKHQVs7TvcaeO8AIl5I= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/internal/converter/testdata/.gitkeep b/internal/converter/testdata/.gitkeep new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/internal/converter/testdata/.gitkeep @@ -0,0 +1 @@ + diff --git a/internal/server/.gitkeep b/internal/server/.gitkeep new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/internal/server/.gitkeep @@ -0,0 +1 @@ + diff --git a/internal/ui/components/.gitkeep b/internal/ui/components/.gitkeep new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/internal/ui/components/.gitkeep @@ -0,0 +1 @@ + diff --git a/internal/version/version.go b/internal/version/version.go new file mode 100644 index 0000000..5550e3e --- /dev/null +++ b/internal/version/version.go @@ -0,0 +1,4 @@ +package version + +// Version устанавливается через -ldflags при сборке. +var Version = "dev" diff --git a/tools.go b/tools.go new file mode 100644 index 0000000..18d36de --- /dev/null +++ b/tools.go @@ -0,0 +1,14 @@ +//go:build tools + +package tools + +import ( + _ "github.com/a-h/templ" + _ "github.com/alecthomas/chroma/v2" + _ "github.com/go-chi/chi/v5" + _ "github.com/google/uuid" + _ "github.com/mozillazg/go-unidecode" + _ "github.com/yuin/goldmark" + _ "github.com/yuin/goldmark-emoji" + _ "github.com/yuin/goldmark-highlighting/v2" +) diff --git a/web/static/src/.gitkeep b/web/static/src/.gitkeep new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/web/static/src/.gitkeep @@ -0,0 +1 @@ + diff --git a/web/template/.gitkeep b/web/template/.gitkeep new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/web/template/.gitkeep @@ -0,0 +1 @@ +