Skip to content

Commit

Permalink
task: initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
paganotoni committed Aug 4, 2023
0 parents commit 4d81c9a
Show file tree
Hide file tree
Showing 7 changed files with 280 additions and 0 deletions.
39 changes: 39 additions & 0 deletions build.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package tailo

import (
"fmt"
"os"
"os/exec"
)

// Build runs the Tailwind CSS CLI binary to build the
// CSS file and generate compiled CSS it expects to find
// the options in the config file.
func Build(options ...option) {
// Applying passed options
for _, option := range options {
option()
}

if _, err := os.Stat(binaryPath); os.IsNotExist(err) {
err := Setup()
if err != nil {
panic(err)
}
}

cmd := exec.Command(binaryPath)
cmd.Args = append(cmd.Args, "--config", configPath)
cmd.Args = append(cmd.Args, "--input", inputPath)
cmd.Args = append(cmd.Args, "--output", outputPath)

cmd.Stdout = writer(0)
cmd.Stderr = writer(0)

fmt.Println("[tailo] Running:", cmd.String())

err := cmd.Run()
if err != nil {
panic(err)
}
}
7 changes: 7 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module github.com/paganotoni/tailo

go 1.20

require github.com/fsnotify/fsnotify v1.6.0

require golang.org/x/sys v0.0.0-20220908164124-27713097b956 // indirect
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
golang.org/x/sys v0.0.0-20220908164124-27713097b956 h1:XeJjHH1KiLpKGb6lvMiksZ9l0fVUh+AmGcm0nOMEBOY=
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
49 changes: 49 additions & 0 deletions options.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package tailo

var (
// configPath is the path to the TailwindCSS configuration file.
configPath = "config/tailwind.config.js"

// inputPath is the path to the input file, the one with @apply rules.
inputPath = "web/assets/application.css"

// outputPath is the path to the output file, the one with compiled CSS.
outputPath = "web/public/application.css"

// binaryPath is the path to the TailwindCSS CLI binary.
binaryPath = "bin/tailwindcss"
)

type option func()

// UseConfigPath sets the path to the TailwindCSS configuration file
// otherwise it defaults to "config/tailwind.config.js".
func UseConfigPath(path string) option {
return func() {
configPath = path
}
}

// UseInputPath sets the path to the input file, the one with @apply rules
// otherwise it defaults to "web/assets/application.css".
func UseInputPath(path string) option {
return func() {
inputPath = path
}
}

// UseOutputPath sets the path to the output file, the one with compiled CSS
// otherwise it defaults to "web/public/application.css".
func UseOutputPath(path string) option {
return func() {
outputPath = path
}
}

// UseBinaryPath sets the path to the TailwindCSS CLI binary otherwise it
// defaults to "bin/tailwindcss".
func UseBinaryPath(path string) option {
return func() {
binaryPath = path
}
}
75 changes: 75 additions & 0 deletions setup.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// tailo is a wrapper for the Tailwind CSS CLI that
// facilitates the download and of the CLI and the
// config file.
package tailo

import (
"fmt"
"io"
"net/http"
"os"
"runtime"
)

var (
binaries = map[string]string{
"darwin_amd64": "tailwindcss-macos-x64",
"darwin_arm64": "tailwindcss-macos-arm64",
"linux_amd64": "tailwindcss-linux-x64",
"linux_arm64": "tailwindcss-linux-arm64",
"linux_arm": "tailwindcss-linux-armv7",
"windows_amd64": "tailwindcss-windows-x64",
"windows_arm64": "tailwindcss-windows-arm64",
}
)

// Setup downloads the Tailwind CSS CLI binary for the
// given operating system and architecture. It makes the
// binary executable and places it in the bin/ directory.
func Setup() error {
if _, err := os.Stat("bin/tailwindcss"); err == nil {
fmt.Println("Tailwind CSS CLI binary already exists.")

return nil
}

currentArch := fmt.Sprintf("%v_%v", runtime.GOOS, runtime.GOARCH)
binary, ok := binaries[currentArch]
if !ok {
return fmt.Errorf("Unsupported operating system and architecture: %s", currentArch)
}

url := fmt.Sprintf("https://github.com/tailwindlabs/tailwindcss/releases/latest/download/%v", binary)
fmt.Println(url)

resp, err := http.Get(url)
if err != nil {
return err
}

defer resp.Body.Close()
if resp.StatusCode != 200 {
return fmt.Errorf("Could not download Tailwind CSS CLI binary: %s", resp.Status)
}

// Create the file
out, err := os.Create("bin/tailwindcss")
if err != nil {
return err
}

defer out.Close()

err = os.MkdirAll("bin", 0755)
if err != nil {
return err
}

err = os.Chmod("bin/tailwindcss", 0755)
if err != nil {
return err
}

_, err = io.Copy(out, resp.Body)
return err
}
88 changes: 88 additions & 0 deletions tailo.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
// tailo is a wrapper for the Tailwind CSS CLI that
// facilitates the download and of the CLI and the
// config file.
package tailo

import (
"fmt"
"log"
"os"
"path/filepath"

"github.com/fsnotify/fsnotify"
)

type extensions []string

func (e extensions) Has(ext string) bool {
for _, v := range e {
if v == ext {
return true
}
}

return false
}

func Watch() {
Build()

watcher, err := buildWatcher()
if err != nil {
panic(err)
}

// Start listening for events.
go func() {
for {
select {
case event, ok := <-watcher.Events:
if !ok {
return
}

if event.Has(fsnotify.Write) {
Build()
}
case err, ok := <-watcher.Errors:
if !ok {
return
}
log.Println("error:", err)
}
}
}()

<-make(chan struct{})
}

// Extensions to watch for changes.
var watchExtensions = extensions{".html", ".css"}

func buildWatcher() (*fsnotify.Watcher, error) {
watcher, err := fsnotify.NewWatcher()
if err != nil {
return watcher, fmt.Errorf("error creating watcher: %w", err)
}

// Add all files that need to be watched to the
// watcher so it notifies the errors that it needs to
// restart.
err = filepath.Walk(".", func(path string, info os.FileInfo, err error) error {
if info.IsDir() {
return nil
}

if !watchExtensions.Has(filepath.Ext(path)) {
return nil
}

return watcher.Add(path)
})

if err != nil {
return watcher, fmt.Errorf("error loading paths: %w", err)
}

return watcher, err
}
18 changes: 18 additions & 0 deletions writer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package tailo

import (
"fmt"
"strings"
)

type writer int

func (w writer) Write(p []byte) (n int, err error) {
content := strings.TrimSpace(string(p))
if content == "" {
return len(p), nil
}

fmt.Println("[tailo]", content)
return len(p), nil
}

0 comments on commit 4d81c9a

Please sign in to comment.