Skip to content

Commit

Permalink
Merge branch 'main' into rawgo-comment-parse
Browse files Browse the repository at this point in the history
  • Loading branch information
a-h authored Aug 18, 2024
2 parents f64b7fd + 65c2618 commit b5c85db
Show file tree
Hide file tree
Showing 24 changed files with 176 additions and 31 deletions.
1 change: 1 addition & 0 deletions .envrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
use flake
5 changes: 1 addition & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,7 @@ jobs:
- uses: DeterminateSystems/magic-nix-cache-action@v3

- name: Generate
run: nix develop --command xc generate

- name: Ensure clean
run: git diff --exit-code
run: nix develop --command xc ensure-generated

ensure-fmt:
runs-on: ubuntu-latest
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,6 @@ result

# Go workspace.
go.work

# direnv
.direnv
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,10 +137,22 @@ go run ./cmd/templ fmt .

### lint

Run the lint operations that are run as part of the CI.

```sh
golangci-lint run --verbose
```

### ensure-generated

Ensure that templ files have been generated with the local version of templ, and that those files have been added to git.

Requires: generate

```sh
git diff --exit-code
```

### push-release-tag

Push a semantic version number to Github to trigger the release process.
Expand Down
2 changes: 2 additions & 0 deletions cmd/templ/generatecmd/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ func (cmd Generate) Run(ctx context.Context) (err error) {
cmd.Args.GenerateSourceMapVisualisations,
cmd.Args.KeepOrphanedFiles,
cmd.Args.FileWriter,
cmd.Args.Lazy,
)

// If we're processing a single file, don't bother setting up the channels/multithreaing.
Expand Down Expand Up @@ -183,6 +184,7 @@ func (cmd Generate) Run(ctx context.Context) (err error) {
cmd.Args.GenerateSourceMapVisualisations,
cmd.Args.KeepOrphanedFiles,
cmd.Args.FileWriter,
cmd.Args.Lazy,
)
errorCount.Store(0)
if err := watcher.WalkFiles(ctx, cmd.Args.Path, events); err != nil {
Expand Down
35 changes: 27 additions & 8 deletions cmd/templ/generatecmd/eventhandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ func NewFSEventHandler(
genSourceMapVis bool,
keepOrphanedFiles bool,
fileWriter FileWriterFunc,
lazy bool,
) *FSEventHandler {
if !path.IsAbs(dir) {
dir, _ = filepath.Abs(dir)
Expand All @@ -63,6 +64,7 @@ func NewFSEventHandler(
DevMode: devMode,
keepOrphanedFiles: keepOrphanedFiles,
writer: fileWriter,
lazy: lazy,
}
if devMode {
fseh.genOpts = append(fseh.genOpts, generator.WithExtractStrings())
Expand All @@ -86,6 +88,7 @@ type FSEventHandler struct {
Errors []error
keepOrphanedFiles bool
writer func(string, []byte) error
lazy bool
}

func (h *FSEventHandler) HandleEvent(ctx context.Context, event fsnotify.Event) (goUpdated, textUpdated bool, err error) {
Expand Down Expand Up @@ -125,10 +128,16 @@ func (h *FSEventHandler) HandleEvent(ctx context.Context, event fsnotify.Event)
}

// If the file hasn't been updated since the last time we processed it, ignore it.
if !h.UpsertLastModTime(event.Name) {
lastModTime, updatedModTime := h.UpsertLastModTime(event.Name)
if !updatedModTime {
h.Log.Debug("Skipping file because it wasn't updated", slog.String("file", event.Name))
return false, false, nil
}
// If the go file is newer than the templ file, skip generation, because it's up-to-date.
if h.lazy && goFileIsUpToDate(event.Name, lastModTime) {
h.Log.Debug("Skipping file because the Go file is up-to-date", slog.String("file", event.Name))
return false, false, nil
}

// Start a processor.
start := time.Now()
Expand Down Expand Up @@ -159,6 +168,15 @@ func (h *FSEventHandler) HandleEvent(ctx context.Context, event fsnotify.Event)
return goUpdated, textUpdated, nil
}

func goFileIsUpToDate(templFileName string, templFileLastMod time.Time) (upToDate bool) {
goFileName := strings.TrimSuffix(templFileName, ".templ") + "_templ.go"
goFileInfo, err := os.Stat(goFileName)
if err != nil {
return false
}
return goFileInfo.ModTime().After(templFileLastMod)
}

func (h *FSEventHandler) SetError(fileName string, hasError bool) (previouslyHadError bool, errorCount int) {
h.fileNameToErrorMutex.Lock()
defer h.fileNameToErrorMutex.Unlock()
Expand All @@ -170,19 +188,20 @@ func (h *FSEventHandler) SetError(fileName string, hasError bool) (previouslyHad
return previouslyHadError, len(h.fileNameToError)
}

func (h *FSEventHandler) UpsertLastModTime(fileName string) (updated bool) {
func (h *FSEventHandler) UpsertLastModTime(fileName string) (modTime time.Time, updated bool) {
fileInfo, err := os.Stat(fileName)
if err != nil {
return false
return modTime, false
}
h.fileNameToLastModTimeMutex.Lock()
defer h.fileNameToLastModTimeMutex.Unlock()
lastModTime := h.fileNameToLastModTime[fileName]
if !fileInfo.ModTime().After(lastModTime) {
return false
previousModTime := h.fileNameToLastModTime[fileName]
currentModTime := fileInfo.ModTime()
if !currentModTime.After(previousModTime) {
return currentModTime, false
}
h.fileNameToLastModTime[fileName] = fileInfo.ModTime()
return true
h.fileNameToLastModTime[fileName] = currentModTime
return currentModTime, true
}

func (h *FSEventHandler) UpsertHash(fileName string, hash [sha256.Size]byte) (updated bool) {
Expand Down
1 change: 1 addition & 0 deletions cmd/templ/generatecmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ type Arguments struct {
// PPROFPort is the port to run the pprof server on.
PPROFPort int
KeepOrphanedFiles bool
Lazy bool
}

func Run(ctx context.Context, log *slog.Logger, args Arguments) (err error) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ func TestErrorLocationMapping(t *testing.T) {

slog := slog.New(slog.NewTextHandler(io.Discard, &slog.HandlerOptions{}))
var fw generatecmd.FileWriterFunc
fseh := generatecmd.NewFSEventHandler(slog, ".", false, []generator.GenerateOpt{}, false, false, fw)
fseh := generatecmd.NewFSEventHandler(slog, ".", false, []generator.GenerateOpt{}, false, false, fw, false)
for _, test := range tests {
// The raw files cannot end in .templ because they will cause the generator to fail. Instead,
// we create a tmp file that ends in .templ only for the duration of the test.
Expand Down
4 changes: 4 additions & 0 deletions cmd/templ/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,8 @@ Args:
If present, the command will issue a reload event to the proxy 127.0.0.1:7331, or use proxyport and proxybind to specify a different address.
-w
Number of workers to use when generating code. (default runtime.NumCPUs)
-lazy
Only generate .go files if the source .templ file is newer.
-pprof
Port to run the pprof server on.
-keep-orphaned-files
Expand Down Expand Up @@ -215,6 +217,7 @@ func generateCmd(stdout, stderr io.Writer, args []string) (code int) {
keepOrphanedFilesFlag := cmd.Bool("keep-orphaned-files", false, "")
verboseFlag := cmd.Bool("v", false, "")
logLevelFlag := cmd.String("log-level", "info", "")
lazyFlag := cmd.Bool("lazy", false, "")
helpFlag := cmd.Bool("help", false, "")
err := cmd.Parse(args)
if err != nil {
Expand Down Expand Up @@ -259,6 +262,7 @@ func generateCmd(stdout, stderr io.Writer, args []string) (code int) {
IncludeTimestamp: *includeTimestampFlag,
PPROFPort: *pprofPortFlag,
KeepOrphanedFiles: *keepOrphanedFilesFlag,
Lazy: *lazyFlag,
})
if err != nil {
color.New(color.FgRed).Fprint(stderr, "(✗) ")
Expand Down
2 changes: 2 additions & 0 deletions docs/docs/04-core-concepts/02-template-generation.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ Args:
If present, the command will issue a reload event to the proxy 127.0.0.1:7331, or use proxyport and proxybind to specify a different address.
-w
Number of workers to use when generating code. (default runtime.NumCPUs)
-lazy
Only generate .go files if the source .templ file is newer.
-pprof
Port to run the pprof server on.
-keep-orphaned-files
Expand Down
2 changes: 1 addition & 1 deletion docs/docs/05-server-side-rendering/05-streaming.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

The default behaviour of the `templ.Handler` is to render the template to a buffer and then write the buffer to the response.

This ensures that the template has successfully rendered before the response is sent to the client, so that appropriate repsonse codes can be set if the template fails to render, and partial responses are not sent to the client.
This ensures that the template has successfully rendered before the response is sent to the client, so that appropriate response codes can be set if the template fails to render, and partial responses are not sent to the client.

## Rendering lifecycle

Expand Down
2 changes: 2 additions & 0 deletions docs/docs/09-commands-and-tools/01-cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ Args:
The address the proxy will listen on. (default 127.0.0.1)
-w
Number of workers to use when generating code. (default runtime.NumCPUs)
-lazy
Only generate .go files if the source .templ file is newer.
-pprof
Port to run the pprof server on.
-keep-orphaned-files
Expand Down
14 changes: 14 additions & 0 deletions docs/docs/13-experimental/01-overview.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Experimental packages

Experimental Packages for templ are available at https://github.com/templ-go/x/

:::warning
- Packages in this module are experimental and may be removed at any time.
- There is no guarantee of compatibility with future versions.
- There is no guarantee of stability.
- Use at your own risk.
:::

## Approval Process

As of right now, there is no formal approval process for packages to be stabilized and moved into https://github.com/a-h/templ. Feel free to contribute via GitHub discussions at https://github.com/a-h/templ/discussions
31 changes: 31 additions & 0 deletions docs/docs/13-experimental/02-urlbuilder.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# urlbuilder

A simple URL builder to construct a `templ.SafeURL`.

```templ title="component.templ"
import (
"github.com/templ-go/x/urlbuilder"
"strconv"
"strings"
)
templ component(o Order) {
<a
href={ urlbuilder.New("https", "example.com").
Path("orders").
Path(o.ID).
Path("line-items").
Query("page", strconv.Itoa(1)).
Query("limit", strconv.Itoa(10)).
Build() }
>
{ strings.ToUpper(o.Name) }
</a>
}
```

See [URL Attribures](/syntax-and-usage/attributes#url-attributes) for more information.

## Feedback

Please leave your feedback on this feature at https://github.com/a-h/templ/discussions/867
4 changes: 4 additions & 0 deletions docs/docs/13-experimental/_category_.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"position": 13,
"label": "Experimental"
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"position": 13,
"position": 14,
"label": "Help and community"
}
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"position": 14,
"position": 15,
"label": "FAQ"
}
File renamed without changes.
24 changes: 24 additions & 0 deletions examples/integration-gofiber/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
## Example

This example demonstrates the usage of templ with gofiber.

As soon as you start the server you can access http://localhost:3000/ and see the rendered page.

If you change the URL to http://localhost:3000/john you will see your parameter printed on the page.

This happens both through parameter passing into the templ component and through context using fiber locals.

## Tasks

### build-templ

```
templ generate
```

### run

```
go run .
```

2 changes: 1 addition & 1 deletion examples/integration-gofiber/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module github.com/a-h/templ/examples/integration-gofiber
go 1.21

require (
github.com/a-h/templ v0.2.501
github.com/a-h/templ v0.2.747
github.com/gofiber/fiber/v2 v2.52.5
)

Expand Down
10 changes: 10 additions & 0 deletions examples/integration-gofiber/home.templ
Original file line number Diff line number Diff line change
@@ -1,7 +1,17 @@
package main

import "context"

func NameFromContext(ctx context.Context) string {
if name, ok := ctx.Value("name").(string); ok && name != "" {
return name
}
return "World"
}

templ Home(name string) {
<div>Hello { name }</div>
<div>Hello { NameFromContext(ctx) } (from context)</div>
}

templ NotFound() {
Expand Down
32 changes: 27 additions & 5 deletions examples/integration-gofiber/home_templ.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit b5c85db

Please sign in to comment.