livebud / bud

The Full-Stack Web Framework for Go
MIT License
5.53k stars 182 forks source link

Add transpiler generator #366

Closed matthewmueller closed 1 year ago

matthewmueller commented 1 year ago

This PR adds support for a transpiler/ directory where you can define custom transpilers (e.g. .md to .html).

This generator is low-level and meant to allow you to hook custom transpilers into other higher-level generators, like the view generator or the public generator. By decoupling transpiling from those generators, it can be used anywhere you need to change from one file format to another, including your custom generators.

Some use cases include:

Here's how you could define a custom transpiler in transpiler/md/md.go (untested):

package md

import "github.com/livebud/bud/runtime/transpiler"
import "https://github.com/yuin/goldmark"

func New() *Transpiler {
  return &Transpiler{
    md: goldmark.New(),
  }
}

type Transpiler struct {
  md goldmark.Markdown
}

func (t *Transpiler) MdToHtml(file *transpiler.File) error {
  var buf bytes.Buffer
  if err := md.Convert(file.Data, &buf); err != nil {
    return err
  }
  file.Data = buf.Bytes()
  return nil
}

This will define a custom transpiler in that will get triggered whenever you request an HTML file from a Markdown file. As I mentioned, this won't write any files, it's meant to be used by other generators.

In a subsequent PR, the view generator will hook up the transpiler generator, but you could also trigger this from a custom generator in generator/static/static.go:

package frontend

import "github.com/livebud/bud/runtime/transpiler"

type Generator struct {

}

func (g *Generator) Generate(fsys genfs.FS, dir *genfs.Dir) error {
  dir.GenerateFile("index.html", func(fsys genfs.FS, file *genfs.File) error {
    html, err := transpiler.TranspileFile(fsys, "view/index.md", ".html")
    if err != nil {
      return err
    }
    file.Data = html
    return nil
  })
  return nil
}

Now when bud run or bud build is called, you'll end up with a bud/internal/static/index.html file containing the transpiled version of view/index.md into HTML.

Todo: