Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/main' into document-symbol
Browse files Browse the repository at this point in the history
  • Loading branch information
jackielii committed Aug 19, 2024
2 parents ac97290 + ae99146 commit fcc0770
Show file tree
Hide file tree
Showing 51 changed files with 735 additions and 327 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
2 changes: 1 addition & 1 deletion .version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.2.753
0.2.766
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
3 changes: 2 additions & 1 deletion cmd/templ/generatecmd/proxy/script.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
(function () {
(function() {
let templ_reloadSrc = window.templ_reloadSrc || new EventSource("/_templ/reload/events");
templ_reloadSrc.onmessage = (event) => {
if (event && event.data === "reload") {
window.location.reload();
}
};
window.templ_reloadSrc = templ_reloadSrc;
window.onbeforeunload = () => window.templ_reloadSrc.close();
})();
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: 1 addition & 1 deletion docs/docs/03-syntax-and-usage/03-attributes.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ It's possible to spread any variable of type `templ.Attributes`. `templ.Attribut

```templ
templ component(shouldBeUsed bool, attrs templ.Attributes) {
<p { attrs... }></p>
<p { attrs... }>Text</p>
<hr
if shouldBeUsed {
{ attrs... }
Expand Down
24 changes: 23 additions & 1 deletion docs/docs/03-syntax-and-usage/12-script-templates.md
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ Pass data from the server to the client by embedding it in the HTML as a JSON ob

```templ title="input.templ"
templ body(data any) {
<button id="alerter" alert-data={ templ.JSONString(attributeData) }>Show alert</button>
<button id="alerter" alert-data={ templ.JSONString(data) }>Show alert</button>
}
```

Expand Down Expand Up @@ -403,3 +403,25 @@ After building and running the executable, running `curl http://localhost:8080/`
</body>
</html>
```

The `JSExpression` type is used to pass arbitrary JavaScript expressions to a templ script template.

A common use case is to pass the `event` or `this` objects to an event handler.

```templ
package main
script showButtonWasClicked(event templ.JSExpression) {
const originalButtonText = event.target.innerText
event.target.innerText = "I was Clicked!"
setTimeout(() => event.target.innerText = originalButtonText, 2000)
}
templ page() {
<html>
<body>
<button type="button" onclick={ showButtonWasClicked(templ.JSExpression("event")) }>Click Me</button>
</body>
</html>
}
```
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
Loading

0 comments on commit fcc0770

Please sign in to comment.