add an html interpreter
This commit is contained in:
@ -11,9 +11,15 @@ import (
|
||||
vue_gen "masonry/vue-gen"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
"github.com/alecthomas/participle/v2"
|
||||
|
||||
"masonry/interpreter"
|
||||
"masonry/lang"
|
||||
)
|
||||
|
||||
//go:embed templates/proto/application.proto.tmpl
|
||||
@ -156,104 +162,143 @@ func generateCmd() *cli.Command {
|
||||
return &cli.Command{
|
||||
Name: "generate",
|
||||
Aliases: []string{"g"},
|
||||
Usage: "Generate code from proto files",
|
||||
Usage: "Generate code from proto files or Masonry files",
|
||||
Category: "generator",
|
||||
Description: "This command will generate code from the proto files in the proto directory and place them in a language folder in the gen folder.",
|
||||
Description: "This command will generate code from proto files or convert Masonry files to various formats.",
|
||||
Subcommands: []*cli.Command{
|
||||
{
|
||||
Name: "proto",
|
||||
Usage: "Generate code from proto files",
|
||||
Action: func(c *cli.Context) error {
|
||||
return generateProtoCode()
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "html",
|
||||
Usage: "Generate HTML from Masonry files",
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "input",
|
||||
Usage: "Input Masonry file path",
|
||||
Required: true,
|
||||
Aliases: []string{"i"},
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "output",
|
||||
Usage: "Output directory for generated HTML files",
|
||||
Value: "./output",
|
||||
Aliases: []string{"o"},
|
||||
},
|
||||
},
|
||||
Action: func(c *cli.Context) error {
|
||||
inputFile := c.String("input")
|
||||
outputDir := c.String("output")
|
||||
|
||||
return generateHTML(inputFile, outputDir)
|
||||
},
|
||||
},
|
||||
},
|
||||
Action: func(c *cli.Context) error {
|
||||
fmt.Println("Generating code...")
|
||||
|
||||
protocArgs := []string{
|
||||
"-I",
|
||||
".",
|
||||
"--go_out",
|
||||
"gen/go",
|
||||
"--go-grpc_out",
|
||||
"gen/go",
|
||||
"--go-grpc_opt=require_unimplemented_servers=false",
|
||||
"--gorm_out",
|
||||
"gen/go",
|
||||
"--grpc-gateway_out",
|
||||
"gen/go",
|
||||
"--grpc-gateway_opt",
|
||||
"logtostderr=true",
|
||||
"--openapiv2_out",
|
||||
"gen/openapi",
|
||||
"--openapiv2_opt",
|
||||
"logtostderr=true",
|
||||
"--proto_path=./proto_include",
|
||||
"proto/*.proto",
|
||||
}
|
||||
|
||||
// generate go code
|
||||
cmd := exec.Command(
|
||||
"protoc",
|
||||
protocArgs...,
|
||||
)
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
|
||||
var buff bytes.Buffer
|
||||
cmd.Stderr = &buff
|
||||
fmt.Println(buff.String())
|
||||
|
||||
return fmt.Errorf("error generating go code | %w", err)
|
||||
}
|
||||
|
||||
// Generate ts code
|
||||
// if webapp folder is present, generate typescript code
|
||||
if _, err := os.Stat("webapp"); err == nil {
|
||||
err = os.Chdir("webapp")
|
||||
if err != nil {
|
||||
return fmt.Errorf("error changing directory to webapp | %w", err)
|
||||
}
|
||||
|
||||
cmd = exec.Command("npx",
|
||||
"openapi-typescript-codegen",
|
||||
"--input",
|
||||
"../gen/openapi/proto/service.swagger.json",
|
||||
"--output",
|
||||
"src/generated",
|
||||
"--client",
|
||||
"fetch",
|
||||
)
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
err = cmd.Run()
|
||||
if err != nil {
|
||||
return fmt.Errorf("error generating typescript code | %w", err)
|
||||
}
|
||||
|
||||
// make sure src/generated-sample-components exists
|
||||
err = os.Mkdir("src/generated-sample-components", 0755)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error creating src/generated-components directory | %w", err)
|
||||
}
|
||||
|
||||
// generate vue components
|
||||
err = vue_gen.GenVueFromSwagger("../gen/openapi/proto/service.swagger.json", "src/generated-sample-components")
|
||||
if err != nil {
|
||||
return fmt.Errorf("error generating vue components | %w", err)
|
||||
}
|
||||
|
||||
cmd := exec.Command("npm", "install", "@masonitestudios/dynamic-vue")
|
||||
err = cmd.Run()
|
||||
if err != nil {
|
||||
return fmt.Errorf("error installing @masonitestudios/dynamic-vue | %w", err)
|
||||
}
|
||||
|
||||
err = os.Chdir("..")
|
||||
if err != nil {
|
||||
return fmt.Errorf("error changing directory back to root | %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
// Default action - generate proto code for backward compatibility
|
||||
return generateProtoCode()
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// generateProtoCode handles the original proto code generation logic
|
||||
func generateProtoCode() error {
|
||||
fmt.Println("Generating code...")
|
||||
|
||||
protocArgs := []string{
|
||||
"-I",
|
||||
".",
|
||||
"--go_out",
|
||||
"gen/go",
|
||||
"--go-grpc_out",
|
||||
"gen/go",
|
||||
"--go-grpc_opt=require_unimplemented_servers=false",
|
||||
"--gorm_out",
|
||||
"gen/go",
|
||||
"--grpc-gateway_out",
|
||||
"gen/go",
|
||||
"--grpc-gateway_opt",
|
||||
"logtostderr=true",
|
||||
"--openapiv2_out",
|
||||
"gen/openapi",
|
||||
"--openapiv2_opt",
|
||||
"logtostderr=true",
|
||||
"--proto_path=./proto_include",
|
||||
"proto/*.proto",
|
||||
}
|
||||
|
||||
// generate go code
|
||||
cmd := exec.Command(
|
||||
"protoc",
|
||||
protocArgs...,
|
||||
)
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
|
||||
var buff bytes.Buffer
|
||||
cmd.Stderr = &buff
|
||||
fmt.Println(buff.String())
|
||||
|
||||
return fmt.Errorf("error generating go code | %w", err)
|
||||
}
|
||||
|
||||
// Generate ts code
|
||||
// if webapp folder is present, generate typescript code
|
||||
if _, err := os.Stat("webapp"); err == nil {
|
||||
err = os.Chdir("webapp")
|
||||
if err != nil {
|
||||
return fmt.Errorf("error changing directory to webapp | %w", err)
|
||||
}
|
||||
|
||||
cmd = exec.Command("npx",
|
||||
"openapi-typescript-codegen",
|
||||
"--input",
|
||||
"../gen/openapi/proto/service.swagger.json",
|
||||
"--output",
|
||||
"src/generated",
|
||||
"--client",
|
||||
"fetch",
|
||||
)
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
err = cmd.Run()
|
||||
if err != nil {
|
||||
return fmt.Errorf("error generating typescript code | %w", err)
|
||||
}
|
||||
|
||||
// make sure src/generated-sample-components exists
|
||||
err = os.Mkdir("src/generated-sample-components", 0755)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error creating src/generated-components directory | %w", err)
|
||||
}
|
||||
|
||||
// generate vue components
|
||||
err = vue_gen.GenVueFromSwagger("../gen/openapi/proto/service.swagger.json", "src/generated-sample-components")
|
||||
if err != nil {
|
||||
return fmt.Errorf("error generating vue components | %w", err)
|
||||
}
|
||||
|
||||
cmd := exec.Command("npm", "install", "@masonitestudios/dynamic-vue")
|
||||
err = cmd.Run()
|
||||
if err != nil {
|
||||
return fmt.Errorf("error installing @masonitestudios/dynamic-vue | %w", err)
|
||||
}
|
||||
|
||||
err = os.Chdir("..")
|
||||
if err != nil {
|
||||
return fmt.Errorf("error changing directory back to root | %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func webappCmd() *cli.Command {
|
||||
return &cli.Command{
|
||||
Name: "webapp",
|
||||
@ -368,3 +413,54 @@ func vueGenCmd() *cli.Command {
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// generateHTML parses a Masonry file and generates HTML output
|
||||
func generateHTML(inputFile, outputDir string) error {
|
||||
fmt.Printf("Generating HTML from %s to %s\n", inputFile, outputDir)
|
||||
|
||||
// Read the input file
|
||||
content, err := os.ReadFile(inputFile)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to read input file: %w", err)
|
||||
}
|
||||
|
||||
// Create parser
|
||||
parser, err := participle.Build[lang.AST]()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create parser: %w", err)
|
||||
}
|
||||
|
||||
// Parse the Masonry file
|
||||
ast, err := parser.ParseString(inputFile, string(content))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to parse Masonry file: %w", err)
|
||||
}
|
||||
|
||||
// Create HTML interpreter
|
||||
htmlInterpreter := interpreter.NewHTMLInterpreter()
|
||||
|
||||
// Generate HTML
|
||||
htmlFiles, err := htmlInterpreter.GenerateHTML(ast)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to generate HTML: %w", err)
|
||||
}
|
||||
|
||||
// Create output directory
|
||||
err = os.MkdirAll(outputDir, 0755)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create output directory: %w", err)
|
||||
}
|
||||
|
||||
// Write HTML files
|
||||
for filename, content := range htmlFiles {
|
||||
outputPath := filepath.Join(outputDir, filename)
|
||||
err = os.WriteFile(outputPath, []byte(content), 0644)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to write file %s: %w", outputPath, err)
|
||||
}
|
||||
fmt.Printf("Generated: %s\n", outputPath)
|
||||
}
|
||||
|
||||
fmt.Printf("Successfully generated %d HTML file(s)\n", len(htmlFiles))
|
||||
return nil
|
||||
}
|
||||
|
Reference in New Issue
Block a user