(DOCS): Created the Project Structure guide.
This serves as outsider notes as well as my own reference sheet.
This commit is contained in:
parent
9b7166f3b6
commit
e8d4d8d8ab
101
doc/ProjectStructure.md
Normal file
101
doc/ProjectStructure.md
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
# Project Structure
|
||||||
|
|
||||||
|
<!--toc:start-->
|
||||||
|
- [Project Structure](#project-structure)
|
||||||
|
- [Data Flow](#data-flow)
|
||||||
|
- [Directory Structure](#directory-structure)
|
||||||
|
- [Handler](#internalapphanders)
|
||||||
|
- [Services](#internalappservices)
|
||||||
|
- [Domain](#internaldomain)
|
||||||
|
- [Infrastructure](#internalinfrastructuredatabase)
|
||||||
|
- [Templates](#internaltemplates)
|
||||||
|
- [Static](#webstatic)
|
||||||
|
<!--toc:end-->
|
||||||
|
|
||||||
|
This document describes how the **Potion project** is build. Where each piece can
|
||||||
|
be found, and where new pieces should be built.
|
||||||
|
|
||||||
|
This project attempts to follow the **Domain Driven Design** (DDD) pattern which
|
||||||
|
means that the software should be written in a way that represents the business
|
||||||
|
requirements and domain. The goal is to produce software that is technically
|
||||||
|
sound but also a strong reflection of the business domain.
|
||||||
|
|
||||||
|
DDD implementation in this project means that each "domain" (users, recipes,
|
||||||
|
etc) are defined in their own domain segment and should be used throughout the
|
||||||
|
project.
|
||||||
|
|
||||||
|
|
||||||
|
## Data Flow
|
||||||
|
|
||||||
|
Data flows through a strict pipe line, as described bellow:
|
||||||
|
|
||||||
|
```md
|
||||||
|
**HTTP > handler > service > repository**
|
||||||
|
```
|
||||||
|
|
||||||
|
The data is first send from the client via **HTTP**. The data is routed to the
|
||||||
|
proper **handler** which will take control of request and eventually send the
|
||||||
|
response back to the client.
|
||||||
|
|
||||||
|
The handler will then call the proper **service** which will complete any business
|
||||||
|
logic required before sending the data to the respective **repository.** This
|
||||||
|
repository (which implemented the proper *domain* interface) will communicate with
|
||||||
|
the database and perform and database actions, finally returning the new data
|
||||||
|
back to the service.
|
||||||
|
|
||||||
|
Finally, the service will clean up the data and ensure the data fits into the
|
||||||
|
proper *domain* object and is then bubbled back up to the handler which sends the
|
||||||
|
response to the client.
|
||||||
|
|
||||||
|
## Directory Structure
|
||||||
|
|
||||||
|
The directory structure of this project intends to achieve the most efficient
|
||||||
|
structure while still meeting the goals defined above.
|
||||||
|
|
||||||
|
|
||||||
|
#### `internal/app/handers`
|
||||||
|
|
||||||
|
**Handlers** are responsible for receiving requests and sending back responses.
|
||||||
|
These strongly mimic the controller in the well-known **Model View Controller**
|
||||||
|
(MVC) architecture. Very little logic takes place here.
|
||||||
|
|
||||||
|
|
||||||
|
#### `internal/app/services`
|
||||||
|
|
||||||
|
**Services** are responsible for the majority of the software's business logic. When
|
||||||
|
a request is received by the handler, the service is called and executes all logic
|
||||||
|
required to achieve the end response. However, the service has no communication
|
||||||
|
and therefore relies on the repository for the database.
|
||||||
|
|
||||||
|
#### `internal/domain`
|
||||||
|
|
||||||
|
The **domain** is the definition of the data models and interfaces that are used by
|
||||||
|
the application. The data model of each domain object is defined here as well as
|
||||||
|
the respective service and repository interfaces are defined here. No logic will
|
||||||
|
be placed here, simply just definitions and interfaces.
|
||||||
|
|
||||||
|
#### `internal/infrastructure/database`
|
||||||
|
|
||||||
|
The **infrastructure** module is responsible for housing communication to outside
|
||||||
|
sources, such as the database. The database section (defined here) contains all
|
||||||
|
**migrations**: SQL definitions of database changes. It also contains all of the
|
||||||
|
**repository** implementations as defined by the domain interfaces.
|
||||||
|
|
||||||
|
#### `internal/templates`
|
||||||
|
**Templates** are HTML templates which are served to the user as the web UI. This
|
||||||
|
directory has a very module structure; being broken down into many categories:
|
||||||
|
|
||||||
|
- **Layouts:** Page layouts and other large wrappers.
|
||||||
|
- **Components:** Small scale components for use in various other templates.
|
||||||
|
- **Partials:** Smallest size elements: common buttons, headers, text elements.
|
||||||
|
- **Pages:** Individual pages which are composed and served to the user.
|
||||||
|
|
||||||
|
|
||||||
|
#### `web/static`
|
||||||
|
|
||||||
|
**Static** documents, elements, or other assets are stored in the web directory.
|
||||||
|
Items such as images, icons, style sheets, or even JS scripts can be stored here.
|
||||||
|
This directory will be hosted by the server as a static directory for access by
|
||||||
|
the UI.
|
||||||
|
|
||||||
|
|
||||||
45
examples/hello.templ
Normal file
45
examples/hello.templ
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
script log(s string) {
|
||||||
|
console.log(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
templ hello(name string) {
|
||||||
|
<div>Hello, { name }</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
templ headerTemplate(name string) {
|
||||||
|
<header data-testid="headerTemplate">
|
||||||
|
<h1>{ name } </h1>
|
||||||
|
</header>
|
||||||
|
}
|
||||||
|
|
||||||
|
templ button(text string) {
|
||||||
|
<button onClick={log("clicked")} class="button">
|
||||||
|
{ text }
|
||||||
|
</button>
|
||||||
|
}
|
||||||
|
|
||||||
|
templ component(testID string) {
|
||||||
|
<p data-testid={ testID }>text </p>
|
||||||
|
@headerTemplate("Hayden")
|
||||||
|
}
|
||||||
|
|
||||||
|
templ page2() {
|
||||||
|
<p
|
||||||
|
if 5==5 {
|
||||||
|
class="also five"
|
||||||
|
}
|
||||||
|
>
|
||||||
|
if 5 == 5 {
|
||||||
|
"five is five"
|
||||||
|
}
|
||||||
|
</p>
|
||||||
|
@component("testid-123")
|
||||||
|
}
|
||||||
|
|
||||||
|
templ spread(attrs templ.Attributes) {
|
||||||
|
<p class="bg-red-500" { attrs... }>
|
||||||
|
Text
|
||||||
|
</p>
|
||||||
|
}
|
||||||
296
examples/hello_templ.go
Normal file
296
examples/hello_templ.go
Normal file
@ -0,0 +1,296 @@
|
|||||||
|
// Code generated by templ - DO NOT EDIT.
|
||||||
|
|
||||||
|
// templ: version: v0.3.865
|
||||||
|
package main
|
||||||
|
|
||||||
|
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||||
|
|
||||||
|
import "github.com/a-h/templ"
|
||||||
|
import templruntime "github.com/a-h/templ/runtime"
|
||||||
|
|
||||||
|
func log(s string) templ.ComponentScript {
|
||||||
|
return templ.ComponentScript{
|
||||||
|
Name: `__templ_log_bfa8`,
|
||||||
|
Function: `function __templ_log_bfa8(s){console.log(s)
|
||||||
|
}`,
|
||||||
|
Call: templ.SafeScript(`__templ_log_bfa8`, s),
|
||||||
|
CallInline: templ.SafeScriptInline(`__templ_log_bfa8`, s),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func hello(name string) templ.Component {
|
||||||
|
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||||
|
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||||
|
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
||||||
|
return templ_7745c5c3_CtxErr
|
||||||
|
}
|
||||||
|
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||||
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
defer func() {
|
||||||
|
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||||
|
if templ_7745c5c3_Err == nil {
|
||||||
|
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
ctx = templ.InitializeContext(ctx)
|
||||||
|
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
|
||||||
|
if templ_7745c5c3_Var1 == nil {
|
||||||
|
templ_7745c5c3_Var1 = templ.NopComponent
|
||||||
|
}
|
||||||
|
ctx = templ.ClearChildren(ctx)
|
||||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div>Hello, ")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
var templ_7745c5c3_Var2 string
|
||||||
|
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(name)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `examples/hello.templ`, Line: 8, Col: 19}
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "</div>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func headerTemplate(name string) templ.Component {
|
||||||
|
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||||
|
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||||
|
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
||||||
|
return templ_7745c5c3_CtxErr
|
||||||
|
}
|
||||||
|
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||||
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
defer func() {
|
||||||
|
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||||
|
if templ_7745c5c3_Err == nil {
|
||||||
|
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
ctx = templ.InitializeContext(ctx)
|
||||||
|
templ_7745c5c3_Var3 := templ.GetChildren(ctx)
|
||||||
|
if templ_7745c5c3_Var3 == nil {
|
||||||
|
templ_7745c5c3_Var3 = templ.NopComponent
|
||||||
|
}
|
||||||
|
ctx = templ.ClearChildren(ctx)
|
||||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "<header data-testid=\"headerTemplate\"><h1>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
var templ_7745c5c3_Var4 string
|
||||||
|
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(name)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `examples/hello.templ`, Line: 13, Col: 12}
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "</h1></header>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func button(text string) templ.Component {
|
||||||
|
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||||
|
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||||
|
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
||||||
|
return templ_7745c5c3_CtxErr
|
||||||
|
}
|
||||||
|
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||||
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
defer func() {
|
||||||
|
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||||
|
if templ_7745c5c3_Err == nil {
|
||||||
|
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
ctx = templ.InitializeContext(ctx)
|
||||||
|
templ_7745c5c3_Var5 := templ.GetChildren(ctx)
|
||||||
|
if templ_7745c5c3_Var5 == nil {
|
||||||
|
templ_7745c5c3_Var5 = templ.NopComponent
|
||||||
|
}
|
||||||
|
ctx = templ.ClearChildren(ctx)
|
||||||
|
templ_7745c5c3_Err = templ.RenderScriptItems(ctx, templ_7745c5c3_Buffer, log("clicked"))
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "<button onClick=\"")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
var templ_7745c5c3_Var6 templ.ComponentScript = log("clicked")
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var6.Call)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "\" class=\"button\">")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
var templ_7745c5c3_Var7 string
|
||||||
|
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(text)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `examples/hello.templ`, Line: 19, Col: 9}
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "</button>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func component(testID string) templ.Component {
|
||||||
|
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||||
|
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||||
|
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
||||||
|
return templ_7745c5c3_CtxErr
|
||||||
|
}
|
||||||
|
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||||
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
defer func() {
|
||||||
|
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||||
|
if templ_7745c5c3_Err == nil {
|
||||||
|
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
ctx = templ.InitializeContext(ctx)
|
||||||
|
templ_7745c5c3_Var8 := templ.GetChildren(ctx)
|
||||||
|
if templ_7745c5c3_Var8 == nil {
|
||||||
|
templ_7745c5c3_Var8 = templ.NopComponent
|
||||||
|
}
|
||||||
|
ctx = templ.ClearChildren(ctx)
|
||||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "<p data-testid=\"")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
var templ_7745c5c3_Var9 string
|
||||||
|
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(testID)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `examples/hello.templ`, Line: 24, Col: 24}
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "\">text </p>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
templ_7745c5c3_Err = headerTemplate("Hayden").Render(ctx, templ_7745c5c3_Buffer)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func page2() templ.Component {
|
||||||
|
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||||
|
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||||
|
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
||||||
|
return templ_7745c5c3_CtxErr
|
||||||
|
}
|
||||||
|
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||||
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
defer func() {
|
||||||
|
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||||
|
if templ_7745c5c3_Err == nil {
|
||||||
|
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
ctx = templ.InitializeContext(ctx)
|
||||||
|
templ_7745c5c3_Var10 := templ.GetChildren(ctx)
|
||||||
|
if templ_7745c5c3_Var10 == nil {
|
||||||
|
templ_7745c5c3_Var10 = templ.NopComponent
|
||||||
|
}
|
||||||
|
ctx = templ.ClearChildren(ctx)
|
||||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "<p")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
if 5 == 5 {
|
||||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, " class=\"also five\"")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, ">")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
if 5 == 5 {
|
||||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "\"five is five\"")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "</p>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
templ_7745c5c3_Err = component("testid-123").Render(ctx, templ_7745c5c3_Buffer)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func spread(attrs templ.Attributes) templ.Component {
|
||||||
|
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||||
|
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||||
|
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
||||||
|
return templ_7745c5c3_CtxErr
|
||||||
|
}
|
||||||
|
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||||
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
defer func() {
|
||||||
|
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||||
|
if templ_7745c5c3_Err == nil {
|
||||||
|
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
ctx = templ.InitializeContext(ctx)
|
||||||
|
templ_7745c5c3_Var11 := templ.GetChildren(ctx)
|
||||||
|
if templ_7745c5c3_Var11 == nil {
|
||||||
|
templ_7745c5c3_Var11 = templ.NopComponent
|
||||||
|
}
|
||||||
|
ctx = templ.ClearChildren(ctx)
|
||||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "<p class=\"bg-red-500\"")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
templ_7745c5c3_Err = templ.RenderAttributes(ctx, templ_7745c5c3_Buffer, attrs)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, ">Text</p>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ = templruntime.GeneratedTemplate
|
||||||
19
examples/main.go
Normal file
19
examples/main.go
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/a-h/templ"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
component := page2()
|
||||||
|
btn := button("Click me")
|
||||||
|
|
||||||
|
http.Handle("/", templ.Handler(component))
|
||||||
|
http.Handle("/button", templ.Handler(btn))
|
||||||
|
|
||||||
|
fmt.Println("Listening on :3000")
|
||||||
|
http.ListenAndServe(":3000", nil)
|
||||||
|
}
|
||||||
@ -22,6 +22,8 @@
|
|||||||
go-tools
|
go-tools
|
||||||
htmx-lsp2
|
htmx-lsp2
|
||||||
templ
|
templ
|
||||||
|
tailwindcss_4
|
||||||
|
tailwindcss-language-server
|
||||||
];
|
];
|
||||||
|
|
||||||
# Define the shell that will be executed.
|
# Define the shell that will be executed.
|
||||||
|
|||||||
5
tailwind.config.js
Normal file
5
tailwind.config.js
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
module.exports = {
|
||||||
|
content: ["./**/*.html", "./**/*.templ", "./**/*.go",],
|
||||||
|
theme: { extend: {}, },
|
||||||
|
plugins: [],
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user