Files
masonry/cmd/cli/webapp.go

215 lines
6.6 KiB
Go

package main
import (
_ "embed"
"fmt"
"os"
"os/exec"
"strings"
)
//go:embed templates/vue/AboutView.vue.tmpl
var aboutViewTemplate string
//go:embed templates/vue/HomeView.vue.tmpl
var homeViewTemplate string
func setupWebapp(name string) error {
fmt.Println("Setting up webapp with Vue 3, TypeScript, Vue Router, Pinia, and ESLint with Prettier")
cmd := exec.Command("npm", "create", "vue@latest", "--", "--ts", "--router", "--pinia", "--eslint-with-prettier", name)
err := cmd.Run()
if err != nil {
return fmt.Errorf("error setting up webapp | %w", err)
}
fmt.Println("Switching to the new directory")
// cd into the new directory
err = os.Chdir(name)
if err != nil {
return fmt.Errorf("error changing directory | %w", err)
}
fmt.Println("Installing base dependencies")
// install all dependencies and format the code
cmd = exec.Command("npm", "install", "&&", "npm", "run", "format")
err = cmd.Run()
if err != nil {
return fmt.Errorf("error changing directory | %w", err)
}
// make src/assets/base.css and src/assets/main.css mostly empty files
err = os.WriteFile("src/assets/base.css", []byte(""), 0644)
if err != nil {
return fmt.Errorf("error writing base.css | %w", err)
}
err = os.WriteFile("src/assets/main.css", []byte("@import './base.css';"), 0644)
if err != nil {
return fmt.Errorf("error writing main.css | %w", err)
}
fmt.Println("Setting up Tailwind CSS")
err = setupTailwind()
if err != nil {
return fmt.Errorf("error setting up tailwind | %w", err)
}
// clean up the default example files
err = removeListOfFiles([]string{
"src/components/HelloWorld.vue",
"src/components/TheWelcome.vue",
"src/components/WelcomeItem.vue",
"src/views/AboutView.vue", // replace with new AboutView.vue
"src/components/icons/IconCommunity.vue",
"src/components/icons/IconDocumentation.vue",
"src/components/icons/IconEcosystem.vue",
"src/components/icons/IconSupport.vue",
"src/components/icons/IconTooling.vue",
"src/assets/logo.svg",
})
// create a new about view from the aboutViewTemplate
err = os.WriteFile("src/views/AboutView.vue", []byte(aboutViewTemplate), 0644)
if err != nil {
return fmt.Errorf("error writing new AboutView.vue | %w", err)
}
// create a new home view from the homeViewTemplate
err = os.WriteFile("src/views/HomeView.vue", []byte(homeViewTemplate), 0644)
if err != nil {
return fmt.Errorf("error writing new HomeView.vue | %w", err)
}
fmt.Println("Exiting the new directory")
err = os.Chdir("..")
if err != nil {
return fmt.Errorf("error changing directory | %w", err)
}
return nil
}
func setupTailwind() error {
// check that there is a vite.config.ts file and a package.json file
_, err := os.Stat("vite.config.ts")
if err != nil {
return fmt.Errorf("error checking for vite.config.ts | %w", err)
}
_, err = os.Stat("package.json")
if err != nil {
return fmt.Errorf("error checking for package.json | %w", err)
}
cmd := exec.Command("npm", "install", "tailwindcss", "@tailwindcss/vite")
err = cmd.Run()
if err != nil {
return fmt.Errorf("error installing tailwindcss | %w", err)
}
// In the vite.config.ts insert the following code after the last import statement `import tailwindcss from '@tailwindcss/vite'`
err = insertImportStatement("import tailwindcss from '@tailwindcss/vite'", "vite.config.ts")
if err != nil {
return fmt.Errorf("error inserting import statement | %w", err)
}
// In the vite.config.ts insert the following code after the last plugin usage `tailwindcss(),`
err = insertPluginUsage(" tailwindcss(),", "vite.config.ts")
if err != nil {
return fmt.Errorf("error inserting plugin usage | %w", err)
}
// in the base.css file add an @import statement for tailwind
// check that './src/assets/base.css' exists
_, err = os.Stat("./src/assets/base.css")
if err != nil {
return fmt.Errorf("error checking for base.css | %w", err)
}
err = insertAtTopLineOfFile("@import \"tailwindcss\";", "./src/assets/base.css")
if err != nil {
return fmt.Errorf("error inserting import statement | %w", err)
}
return nil
}
func insertImportStatement(importStatement string, filename string) error {
fileContent, err := os.ReadFile(fmt.Sprintf(".%c%s", os.PathSeparator, filename))
if err != nil {
return fmt.Errorf("error reading %s | %w", filename, err)
}
fileLines := strings.Split(strings.ReplaceAll(string(fileContent), "\r\n", "\n"), "\n")
lastImportIndex := -1
// finds the last import statement in the file and appends after that one
for i, line := range fileLines {
if strings.HasPrefix(line, "import") {
lastImportIndex = i
}
}
if lastImportIndex != -1 {
fileLines = append(fileLines[:lastImportIndex+1], append([]string{importStatement}, fileLines[lastImportIndex+1:]...)...)
} else {
// add the import to the top of the file
fileLines = append([]string{importStatement}, fileLines...)
}
err = os.WriteFile(filename, []byte(strings.Join(fileLines, "\n")), 0644)
if err != nil {
return fmt.Errorf("error writing vite.config.ts | %w", err)
}
return nil
}
func insertPluginUsage(pluginUsage string, filename string) error {
fileContent, err := os.ReadFile(fmt.Sprintf(".%c%s", os.PathSeparator, filename))
if err != nil {
return fmt.Errorf("error reading %s | %w", filename, err)
}
fileLines := strings.Split(strings.ReplaceAll(string(fileContent), "\r\n", "\n"), "\n")
startOfPluginsIndex := -1
// finds the `plugins: [` line in the file and appends after that one
for i, line := range fileLines {
if strings.Contains(line, "plugins: [") {
startOfPluginsIndex = i
}
}
if startOfPluginsIndex != -1 {
fileLines = append(fileLines[:startOfPluginsIndex+1], append([]string{pluginUsage}, fileLines[startOfPluginsIndex+1:]...)...)
} else {
// add the import to the top of the file
fileLines = append([]string{pluginUsage}, fileLines...)
}
err = os.WriteFile(filename, []byte(strings.Join(fileLines, "\n")), 0644)
if err != nil {
return fmt.Errorf("error writing vite.config.ts | %w", err)
}
return nil
}
func insertAtTopLineOfFile(content string, filename string) error {
fileContent, err := os.ReadFile(fmt.Sprintf(".%c%s", os.PathSeparator, filename))
if err != nil {
return fmt.Errorf("error reading %s | %w", filename, err)
}
fileLines := strings.Split(strings.ReplaceAll(string(fileContent), "\r\n", "\n"), "\n")
fileLines = append([]string{content}, fileLines...)
err = os.WriteFile(filename, []byte(strings.Join(fileLines, "\n")), 0644)
if err != nil {
return fmt.Errorf("error writing vite.config.ts | %w", err)
}
return nil
}
func removeListOfFiles(files []string) error {
for _, file := range files {
err := os.Remove(file)
if err != nil {
return fmt.Errorf("error removing %s | %w", file, err)
}
}
return nil
}